BSD 3 development
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Mon, 12 Feb 1979 13:51:39 +0000 (05:51 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Mon, 12 Feb 1979 13:51:39 +0000 (05:51 -0800)
Work on file usr/src/cmd/awk/awk.def
Work on file usr/src/cmd/awk/awk.g.y
Work on file usr/src/cmd/awk/b.c
Work on file usr/src/cmd/awk/tran.c
Work on file usr/src/cmd/awk/proc.c
Work on file usr/src/cmd/awk/awk.lx.l
Work on file usr/src/cmd/awk/token.c
Work on file usr/src/cmd/awk/parse.c
Work on file usr/src/cmd/awk/dump.c
Work on file usr/src/cmd/awk/awk.h
Work on file usr/src/cmd/awk/tokenscript
Work on file usr/src/cmd/eqn/diacrit.c
Work on file usr/src/cmd/dc/dc.h
Work on file usr/src/cmd/dc/dc.c
Work on file usr/src/cmd/eqn/e.h
Work on file usr/src/cmd/eqn/e.y
Work on file usr/src/cmd/eqn/pile.c
Work on file usr/src/cmd/eqn/matrix.c
Work on file usr/src/cmd/eqn/mark.c
Work on file usr/src/cmd/eqn/io.c
Work on file usr/src/cmd/eqn/sqrt.c
Work on file usr/src/cmd/eqn/font.c
Work on file usr/src/cmd/eqn/over.c
Work on file usr/src/cmd/eqn/lookup.c
Work on file usr/src/cmd/eqn/text.c
Work on file usr/src/cmd/eqn/glob.c
Work on file usr/src/cmd/eqn/integral.c
Work on file usr/src/cmd/eqn/size.c
Work on file usr/src/cmd/eqn/funny.c
Work on file usr/src/cmd/eqn/lex.c
Work on file usr/src/cmd/eqn/fromto.c
Work on file usr/src/cmd/eqn/eqnbox.c
Work on file usr/src/cmd/eqn/shift.c
Work on file usr/src/cmd/eqn/paren.c
Work on file usr/src/cmd/eqn/move.c
Work on file usr/src/cmd/graph/graph.c
Work on file usr/src/cmd/learn/lcount.c
Work on file usr/src/cmd/learn/origmakefile
Work on file usr/src/cmd/learn/selsub.c
Work on file usr/src/cmd/learn/maktee.c
Work on file usr/src/cmd/learn/lrndef
Work on file usr/src/cmd/learn/copy.c
Work on file usr/src/cmd/learn/learn.c
Work on file usr/src/cmd/learn/README
Work on file usr/src/cmd/learn/makpipe.c
Work on file usr/src/cmd/learn/list.c
Work on file usr/src/cmd/learn/selunit.c
Work on file usr/src/cmd/learn/mem.c
Work on file usr/src/cmd/learn/lrnref
Work on file usr/src/cmd/learn/mysys.c
Work on file usr/src/cmd/learn/dounit.c
Work on file usr/src/cmd/learn/whatnow.c
Work on file usr/src/cmd/learn/temp
Work on file usr/src/cmd/learn/wrapup.c
Work on file usr/src/cmd/lex/ncform
Work on file usr/src/cmd/lex/header.c
Work on file usr/src/cmd/lex/ldefs.c
Work on file usr/src/cmd/lex/lmain.c
Work on file usr/src/cmd/lex/sub1.c
Work on file usr/src/cmd/lex/once.c
Work on file usr/src/cmd/lex/parser.y
Work on file usr/src/cmd/lex/sub2.c
Work on file usr/src/cmd/lint/READ_ME
Work on file usr/src/cmd/lint/llib-lc
Work on file usr/src/cmd/lint/macdefs
Work on file usr/src/cmd/lint/lint.c
Work on file usr/src/cmd/lint/lpass2.c
Work on file usr/src/cmd/lint/SHELL
Work on file usr/src/cmd/lint/llib-port
Work on file usr/src/cmd/lint/lmanifest
Work on file usr/src/cmd/m4/m4.c
Work on file usr/src/cmd/m4/m4y.y
Work on file usr/src/cmd/neqn/integral.c
Work on file usr/src/cmd/neqn/font.c
Work on file usr/src/cmd/neqn/diacrit.c
Work on file usr/src/cmd/neqn/e.h
Work on file usr/src/cmd/neqn/eqnbox.c
Work on file usr/src/cmd/neqn/e.y
Work on file usr/src/cmd/neqn/funny.c
Work on file usr/src/cmd/neqn/glob.c
Work on file usr/src/cmd/neqn/fromto.c
Work on file usr/src/cmd/neqn/io.c
Work on file usr/src/cmd/neqn/paren.c
Work on file usr/src/cmd/neqn/shift.c
Work on file usr/src/cmd/neqn/pile.c
Work on file usr/src/cmd/neqn/mark.c
Work on file usr/src/cmd/neqn/sqrt.c
Work on file usr/src/cmd/neqn/lex.c
Work on file usr/src/cmd/neqn/matrix.c
Work on file usr/src/cmd/neqn/over.c
Work on file usr/src/cmd/neqn/text.c
Work on file usr/src/cmd/neqn/lookup.c
Work on file usr/src/cmd/neqn/size.c
Work on file usr/src/cmd/neqn/move.c
Work on file usr/src/cmd/plot/chrtab.c
Work on file usr/src/cmd/plot/driver.c
Work on file usr/src/cmd/plot/vplot.c
Work on file usr/src/cmd/ratfor/r.h
Work on file usr/src/cmd/ratfor/rlook.c
Work on file usr/src/cmd/ratfor/r1.c
Work on file usr/src/cmd/prof/prof.c
Work on file usr/src/cmd/ratfor/rlex.c
Work on file usr/src/cmd/ratfor/r.g
Work on file usr/src/cmd/ratfor/r0.c
Work on file usr/src/cmd/ratfor/r2.c
Work on file usr/src/cmd/refer/deliv1.c
Work on file usr/src/cmd/refer/hunt7.c
Work on file usr/src/cmd/refer/hunt2.c
Work on file usr/src/cmd/refer/hunt3.c
Work on file usr/src/cmd/refer/hunt5.c
Work on file usr/src/cmd/refer/hunt9.c
Work on file usr/src/cmd/refer/Makefile
Work on file usr/src/cmd/refer/hunt1.c
Work on file usr/src/cmd/refer/flagger.c
Work on file usr/src/cmd/refer/hunt6.c
Work on file usr/src/cmd/refer/glue2.c
Work on file usr/src/cmd/refer/glue4.c
Work on file usr/src/cmd/refer/deliv2.c
Work on file usr/src/cmd/refer/inv2.c
Work on file usr/src/cmd/refer/glue1.c
Work on file usr/src/cmd/refer/glue3.c
Work on file usr/src/cmd/refer/inv6.c
Work on file usr/src/cmd/refer/inv3.c
Work on file usr/src/cmd/refer/refer1.c
Work on file usr/src/cmd/refer/kaiser.c
Work on file usr/src/cmd/refer/refer4.c
Work on file usr/src/cmd/refer/refer8.c
Work on file usr/src/cmd/refer/mkey3.c
Work on file usr/src/cmd/refer/refer0.c
Work on file usr/src/cmd/refer/inv5.c
Work on file usr/src/cmd/refer/refer2.c
Work on file usr/src/cmd/refer/refer5.c
Work on file usr/src/cmd/refer/mkey2.c
Work on file usr/src/cmd/refer/refer3.c
Work on file usr/src/cmd/refer/what4.c
Work on file usr/src/cmd/refer/shell.c
Work on file usr/src/cmd/refer/what..c
Work on file usr/src/cmd/refer/what3.c
Work on file usr/src/cmd/refer/types.c
Work on file usr/src/cmd/refer/test
Work on file usr/src/cmd/refer/thash.c
Work on file usr/src/cmd/refer/sample
Work on file usr/src/cmd/refer/what1.c
Work on file usr/src/cmd/sed/sed0.c
Work on file usr/src/cmd/sh/ctype.c
Work on file usr/src/cmd/sh/cmd.c
Work on file usr/src/cmd/sh/error.c
Work on file usr/src/cmd/sh/builtin.c
Work on file usr/src/cmd/sh/dup.h
Work on file usr/src/cmd/sh/blok.c
Work on file usr/src/cmd/sh/fault.c
Work on file usr/src/cmd/sh/ctype.h
Work on file usr/src/cmd/sh/args.c
Work on file usr/src/cmd/sh/brkincr.h
Work on file usr/src/cmd/sh/expand.c
Work on file usr/src/cmd/sh/sym.h
Work on file usr/src/cmd/sh/mac.h
Work on file usr/src/cmd/sh/stak.h
Work on file usr/src/cmd/sh/macro.c
Work on file usr/src/cmd/sh/name.c
Work on file usr/src/cmd/sh/name.h
Work on file usr/src/cmd/sh/string.c
Work on file usr/src/cmd/sh/setbrk.c
Work on file usr/src/cmd/sh/mode.h
Work on file usr/src/cmd/sh/word.c
Work on file usr/src/cmd/sh/print.c
Work on file usr/src/cmd/sh/stak.c
Work on file usr/src/cmd/spell/local
Work on file usr/src/cmd/spell/stop
Work on file usr/src/cmd/spell/spell.sh
Work on file usr/src/cmd/spell/american
Work on file usr/src/cmd/spell/spell.c
Work on file usr/src/cmd/spell/spell.h
Work on file usr/src/cmd/spell/british
Work on file usr/src/cmd/spell/spellout.c
Work on file usr/src/cmd/spell/spellin.c
Work on file usr/src/cmd/struct/0.parts.c
Work on file usr/src/cmd/struct/0.extr.c
Work on file usr/src/cmd/struct/0.def.c
Work on file usr/src/cmd/struct/1.defs.h
Work on file usr/src/cmd/struct/1.form.c
Work on file usr/src/cmd/struct/1.node.c
Work on file usr/src/cmd/struct/0.graph.c
Work on file usr/src/cmd/struct/1.finish.c
Work on file usr/src/cmd/struct/0.string.c
Work on file usr/src/cmd/struct/1.main.c
Work on file usr/src/cmd/struct/1.line.c
Work on file usr/src/cmd/struct/1.hash.c
Work on file usr/src/cmd/struct/1.incl.h
Work on file usr/src/cmd/struct/0.list.c
Work on file usr/src/cmd/struct/1.fort.c
Work on file usr/src/cmd/struct/0.alloc.c
Work on file usr/src/cmd/struct/0.args.c
Work on file usr/src/cmd/struct/1.init.c
Work on file usr/src/cmd/struct/1.tables.c
Work on file usr/src/cmd/struct/3.branch.c
Work on file usr/src/cmd/struct/1.recog.c
Work on file usr/src/cmd/struct/2.tree.c
Work on file usr/src/cmd/struct/2.dfs.c
Work on file usr/src/cmd/struct/3.flow.c
Work on file usr/src/cmd/struct/3.test.c
Work on file usr/src/cmd/struct/3.main.c
Work on file usr/src/cmd/struct/2.inarc.c
Work on file usr/src/cmd/struct/3.reach.c
Work on file usr/src/cmd/struct/2.head.c
Work on file usr/src/cmd/struct/3.loop.c
Work on file usr/src/cmd/struct/2.dom.c
Work on file usr/src/cmd/struct/2.main.c
Work on file usr/src/cmd/struct/3.then.c
Work on file usr/src/cmd/struct/2.def.h
Work on file usr/src/cmd/struct/3.def.h
Work on file usr/src/cmd/struct/2.test.c
Work on file usr/src/cmd/struct/struct
Work on file usr/src/cmd/struct/4.def.h
Work on file usr/src/cmd/struct/b.h
Work on file usr/src/cmd/struct/4.form.c
Work on file usr/src/cmd/struct/bdef.c
Work on file usr/src/cmd/struct/lextab.l
Work on file usr/src/cmd/struct/main.c
Work on file usr/src/cmd/struct/def.h
Work on file usr/src/cmd/struct/4.main.c
Work on file usr/src/cmd/struct/tree.c
Work on file usr/src/cmd/struct/Makefile
Work on file usr/src/cmd/struct/beauty.y
Work on file usr/src/cmd/struct/4.out.c
Work on file usr/src/cmd/struct/4.brace.c
Work on file usr/src/cmd/tbl/t7.c
Work on file usr/src/cmd/tbl/t5.c
Work on file usr/src/cmd/tbl/t6.c
Work on file usr/src/cmd/tbl/t0.c
Work on file usr/src/cmd/tbl/t8.c
Work on file usr/src/cmd/tbl/t3.c
Work on file usr/src/cmd/tbl/t..c
Work on file usr/src/cmd/tbl/t2.c
Work on file usr/src/cmd/tbl/t4.c
Work on file usr/src/cmd/tbl/t9.c
Work on file usr/src/cmd/tbl/tg.c
Work on file usr/src/cmd/tbl/tm.c
Work on file usr/src/cmd/tbl/tv.c
Work on file usr/src/cmd/tbl/ts.c
Work on file usr/src/cmd/tbl/tc.c
Work on file usr/src/cmd/tbl/ti.c
Work on file usr/src/cmd/tbl/tu.c
Work on file usr/src/cmd/tbl/tb.c
Work on file usr/src/cmd/tbl/tt.c
Work on file usr/src/cmd/tbl/tf.c
Work on file usr/src/cmd/troff/term/tab300X.c
Work on file usr/src/cmd/troff/term/tab300.c
Work on file usr/src/cmd/troff/term/tab300S.c
Work on file usr/src/cmd/troff/term/tab300s.c
Work on file usr/src/cmd/troff/term/code.300
Work on file usr/src/cmd/troff/term/tab37.c
Work on file usr/src/cmd/troff/term/tab450X.c
Work on file usr/src/cmd/troff/term/tab450-12.c
Work on file usr/src/cmd/troff/term/tab450.c
Work on file usr/src/cmd/troff/term/tabtn300.c
Work on file usr/src/cmd/tp/tp3.c
Work on file usr/src/cmd/tp/tp2.c
Work on file usr/src/cmd/tp/tp.h
Work on file usr/src/cmd/tp/tp0.c
Work on file usr/src/cmd/uudiff/printable.c
Work on file usr/src/cmd/uudiff/remdiff
Work on file usr/src/cmd/uudiff/trim.c
Work on file usr/src/cmd/uudiff/run1.c
Work on file usr/src/cmd/uudiff/lenrem.c
Work on file usr/src/cmd/uudiff/locpart.c
Work on file usr/src/cmd/xsend/lib.c
Work on file usr/src/cmd/xsend/xsend.c
Work on file usr/src/cmd/xsend/xget.c
Work on file usr/src/cmd/xsend/xmail.h
Work on file usr/src/cmd/xsend/enroll.c
Work on file usr/src/cmd/yacc/yaccdiffs
Work on file usr/src/cmd/yacc/yaccpar
Work on file usr/src/cmd/yacc/y4.c
Work on file usr/src/cmd/yacc/y2.c
Work on file usr/src/cmd/yacc/dextern
Work on file usr/src/cmd/yacc/y3.c
Work on file usr/src/cmd/yacc/y1.c
Work on file usr/src/cmd/yacc/yaccnews

Synthesized-from: 3bsd

279 files changed:
usr/src/cmd/awk/awk.def [new file with mode: 0644]
usr/src/cmd/awk/awk.g.y [new file with mode: 0644]
usr/src/cmd/awk/awk.h [new file with mode: 0644]
usr/src/cmd/awk/awk.lx.l [new file with mode: 0644]
usr/src/cmd/awk/b.c [new file with mode: 0644]
usr/src/cmd/awk/dump.c [new file with mode: 0644]
usr/src/cmd/awk/parse.c [new file with mode: 0644]
usr/src/cmd/awk/proc.c [new file with mode: 0644]
usr/src/cmd/awk/token.c [new file with mode: 0644]
usr/src/cmd/awk/tokenscript [new file with mode: 0644]
usr/src/cmd/awk/tran.c [new file with mode: 0644]
usr/src/cmd/dc/dc.c [new file with mode: 0644]
usr/src/cmd/dc/dc.h [new file with mode: 0644]
usr/src/cmd/eqn/diacrit.c [new file with mode: 0644]
usr/src/cmd/eqn/e.h [new file with mode: 0644]
usr/src/cmd/eqn/e.y [new file with mode: 0644]
usr/src/cmd/eqn/eqnbox.c [new file with mode: 0644]
usr/src/cmd/eqn/font.c [new file with mode: 0644]
usr/src/cmd/eqn/fromto.c [new file with mode: 0644]
usr/src/cmd/eqn/funny.c [new file with mode: 0644]
usr/src/cmd/eqn/glob.c [new file with mode: 0644]
usr/src/cmd/eqn/integral.c [new file with mode: 0644]
usr/src/cmd/eqn/io.c [new file with mode: 0644]
usr/src/cmd/eqn/lex.c [new file with mode: 0644]
usr/src/cmd/eqn/lookup.c [new file with mode: 0644]
usr/src/cmd/eqn/mark.c [new file with mode: 0644]
usr/src/cmd/eqn/matrix.c [new file with mode: 0644]
usr/src/cmd/eqn/move.c [new file with mode: 0644]
usr/src/cmd/eqn/over.c [new file with mode: 0644]
usr/src/cmd/eqn/paren.c [new file with mode: 0644]
usr/src/cmd/eqn/pile.c [new file with mode: 0644]
usr/src/cmd/eqn/shift.c [new file with mode: 0644]
usr/src/cmd/eqn/size.c [new file with mode: 0644]
usr/src/cmd/eqn/sqrt.c [new file with mode: 0644]
usr/src/cmd/eqn/text.c [new file with mode: 0644]
usr/src/cmd/graph/graph.c [new file with mode: 0644]
usr/src/cmd/learn/README [new file with mode: 0644]
usr/src/cmd/learn/copy.c [new file with mode: 0644]
usr/src/cmd/learn/dounit.c [new file with mode: 0644]
usr/src/cmd/learn/lcount.c [new file with mode: 0644]
usr/src/cmd/learn/learn.c [new file with mode: 0644]
usr/src/cmd/learn/list.c [new file with mode: 0644]
usr/src/cmd/learn/lrndef [new file with mode: 0644]
usr/src/cmd/learn/lrnref [new file with mode: 0644]
usr/src/cmd/learn/makpipe.c [new file with mode: 0644]
usr/src/cmd/learn/maktee.c [new file with mode: 0644]
usr/src/cmd/learn/mem.c [new file with mode: 0644]
usr/src/cmd/learn/mysys.c [new file with mode: 0644]
usr/src/cmd/learn/origmakefile [new file with mode: 0644]
usr/src/cmd/learn/selsub.c [new file with mode: 0644]
usr/src/cmd/learn/selunit.c [new file with mode: 0644]
usr/src/cmd/learn/temp [new file with mode: 0644]
usr/src/cmd/learn/whatnow.c [new file with mode: 0644]
usr/src/cmd/learn/wrapup.c [new file with mode: 0644]
usr/src/cmd/lex/header.c [new file with mode: 0644]
usr/src/cmd/lex/ldefs.c [new file with mode: 0644]
usr/src/cmd/lex/lmain.c [new file with mode: 0644]
usr/src/cmd/lex/ncform [new file with mode: 0644]
usr/src/cmd/lex/once.c [new file with mode: 0644]
usr/src/cmd/lex/parser.y [new file with mode: 0644]
usr/src/cmd/lex/sub1.c [new file with mode: 0644]
usr/src/cmd/lex/sub2.c [new file with mode: 0644]
usr/src/cmd/lint/READ_ME [new file with mode: 0644]
usr/src/cmd/lint/SHELL [new file with mode: 0755]
usr/src/cmd/lint/lint.c [new file with mode: 0644]
usr/src/cmd/lint/llib-lc [new file with mode: 0644]
usr/src/cmd/lint/llib-port [new file with mode: 0644]
usr/src/cmd/lint/lmanifest [new file with mode: 0644]
usr/src/cmd/lint/lpass2.c [new file with mode: 0644]
usr/src/cmd/lint/macdefs [new file with mode: 0644]
usr/src/cmd/m4/m4.c [new file with mode: 0644]
usr/src/cmd/m4/m4y.y [new file with mode: 0644]
usr/src/cmd/neqn/diacrit.c [new file with mode: 0644]
usr/src/cmd/neqn/e.h [new file with mode: 0644]
usr/src/cmd/neqn/e.y [new file with mode: 0644]
usr/src/cmd/neqn/eqnbox.c [new file with mode: 0644]
usr/src/cmd/neqn/font.c [new file with mode: 0644]
usr/src/cmd/neqn/fromto.c [new file with mode: 0644]
usr/src/cmd/neqn/funny.c [new file with mode: 0644]
usr/src/cmd/neqn/glob.c [new file with mode: 0644]
usr/src/cmd/neqn/integral.c [new file with mode: 0644]
usr/src/cmd/neqn/io.c [new file with mode: 0644]
usr/src/cmd/neqn/lex.c [new file with mode: 0644]
usr/src/cmd/neqn/lookup.c [new file with mode: 0644]
usr/src/cmd/neqn/mark.c [new file with mode: 0644]
usr/src/cmd/neqn/matrix.c [new file with mode: 0644]
usr/src/cmd/neqn/move.c [new file with mode: 0644]
usr/src/cmd/neqn/over.c [new file with mode: 0644]
usr/src/cmd/neqn/paren.c [new file with mode: 0644]
usr/src/cmd/neqn/pile.c [new file with mode: 0644]
usr/src/cmd/neqn/shift.c [new file with mode: 0644]
usr/src/cmd/neqn/size.c [new file with mode: 0644]
usr/src/cmd/neqn/sqrt.c [new file with mode: 0644]
usr/src/cmd/neqn/text.c [new file with mode: 0644]
usr/src/cmd/plot/chrtab.c [new file with mode: 0644]
usr/src/cmd/plot/driver.c [new file with mode: 0644]
usr/src/cmd/plot/vplot.c [new file with mode: 0644]
usr/src/cmd/prof/prof.c [new file with mode: 0644]
usr/src/cmd/ratfor/r.g [new file with mode: 0644]
usr/src/cmd/ratfor/r.h [new file with mode: 0644]
usr/src/cmd/ratfor/r0.c [new file with mode: 0644]
usr/src/cmd/ratfor/r1.c [new file with mode: 0644]
usr/src/cmd/ratfor/r2.c [new file with mode: 0644]
usr/src/cmd/ratfor/rlex.c [new file with mode: 0644]
usr/src/cmd/ratfor/rlook.c [new file with mode: 0644]
usr/src/cmd/refer/Makefile [new file with mode: 0644]
usr/src/cmd/refer/deliv1.c [new file with mode: 0644]
usr/src/cmd/refer/deliv2.c [new file with mode: 0644]
usr/src/cmd/refer/flagger.c [new file with mode: 0644]
usr/src/cmd/refer/glue1.c [new file with mode: 0644]
usr/src/cmd/refer/glue2.c [new file with mode: 0644]
usr/src/cmd/refer/glue3.c [new file with mode: 0644]
usr/src/cmd/refer/glue4.c [new file with mode: 0644]
usr/src/cmd/refer/hunt1.c [new file with mode: 0644]
usr/src/cmd/refer/hunt2.c [new file with mode: 0644]
usr/src/cmd/refer/hunt3.c [new file with mode: 0644]
usr/src/cmd/refer/hunt5.c [new file with mode: 0644]
usr/src/cmd/refer/hunt6.c [new file with mode: 0644]
usr/src/cmd/refer/hunt7.c [new file with mode: 0644]
usr/src/cmd/refer/hunt9.c [new file with mode: 0644]
usr/src/cmd/refer/inv2.c [new file with mode: 0644]
usr/src/cmd/refer/inv3.c [new file with mode: 0644]
usr/src/cmd/refer/inv5.c [new file with mode: 0644]
usr/src/cmd/refer/inv6.c [new file with mode: 0644]
usr/src/cmd/refer/kaiser.c [new file with mode: 0644]
usr/src/cmd/refer/mkey2.c [new file with mode: 0644]
usr/src/cmd/refer/mkey3.c [new file with mode: 0644]
usr/src/cmd/refer/refer0.c [new file with mode: 0644]
usr/src/cmd/refer/refer1.c [new file with mode: 0644]
usr/src/cmd/refer/refer2.c [new file with mode: 0644]
usr/src/cmd/refer/refer3.c [new file with mode: 0644]
usr/src/cmd/refer/refer4.c [new file with mode: 0644]
usr/src/cmd/refer/refer5.c [new file with mode: 0644]
usr/src/cmd/refer/refer8.c [new file with mode: 0644]
usr/src/cmd/refer/sample [new file with mode: 0644]
usr/src/cmd/refer/shell.c [new file with mode: 0644]
usr/src/cmd/refer/test [new file with mode: 0644]
usr/src/cmd/refer/thash.c [new file with mode: 0644]
usr/src/cmd/refer/types.c [new file with mode: 0644]
usr/src/cmd/refer/what..c [new file with mode: 0644]
usr/src/cmd/refer/what1.c [new file with mode: 0644]
usr/src/cmd/refer/what3.c [new file with mode: 0644]
usr/src/cmd/refer/what4.c [new file with mode: 0644]
usr/src/cmd/sed/sed0.c [new file with mode: 0644]
usr/src/cmd/sh/args.c [new file with mode: 0644]
usr/src/cmd/sh/blok.c [new file with mode: 0644]
usr/src/cmd/sh/brkincr.h [new file with mode: 0644]
usr/src/cmd/sh/builtin.c [new file with mode: 0644]
usr/src/cmd/sh/cmd.c [new file with mode: 0644]
usr/src/cmd/sh/ctype.c [new file with mode: 0644]
usr/src/cmd/sh/ctype.h [new file with mode: 0644]
usr/src/cmd/sh/dup.h [new file with mode: 0644]
usr/src/cmd/sh/error.c [new file with mode: 0644]
usr/src/cmd/sh/expand.c [new file with mode: 0644]
usr/src/cmd/sh/fault.c [new file with mode: 0644]
usr/src/cmd/sh/mac.h [new file with mode: 0644]
usr/src/cmd/sh/macro.c [new file with mode: 0644]
usr/src/cmd/sh/mode.h [new file with mode: 0644]
usr/src/cmd/sh/name.c [new file with mode: 0644]
usr/src/cmd/sh/name.h [new file with mode: 0644]
usr/src/cmd/sh/print.c [new file with mode: 0644]
usr/src/cmd/sh/setbrk.c [new file with mode: 0644]
usr/src/cmd/sh/stak.c [new file with mode: 0644]
usr/src/cmd/sh/stak.h [new file with mode: 0644]
usr/src/cmd/sh/string.c [new file with mode: 0644]
usr/src/cmd/sh/sym.h [new file with mode: 0644]
usr/src/cmd/sh/word.c [new file with mode: 0644]
usr/src/cmd/spell/american [new file with mode: 0644]
usr/src/cmd/spell/british [new file with mode: 0644]
usr/src/cmd/spell/local [new file with mode: 0644]
usr/src/cmd/spell/spell.c [new file with mode: 0644]
usr/src/cmd/spell/spell.h [new file with mode: 0644]
usr/src/cmd/spell/spell.sh [new file with mode: 0755]
usr/src/cmd/spell/spellin.c [new file with mode: 0644]
usr/src/cmd/spell/spellout.c [new file with mode: 0644]
usr/src/cmd/spell/stop [new file with mode: 0644]
usr/src/cmd/struct/0.alloc.c [new file with mode: 0644]
usr/src/cmd/struct/0.args.c [new file with mode: 0644]
usr/src/cmd/struct/0.def.c [new file with mode: 0644]
usr/src/cmd/struct/0.extr.c [new file with mode: 0644]
usr/src/cmd/struct/0.graph.c [new file with mode: 0644]
usr/src/cmd/struct/0.list.c [new file with mode: 0644]
usr/src/cmd/struct/0.parts.c [new file with mode: 0644]
usr/src/cmd/struct/0.string.c [new file with mode: 0644]
usr/src/cmd/struct/1.defs.h [new file with mode: 0644]
usr/src/cmd/struct/1.finish.c [new file with mode: 0644]
usr/src/cmd/struct/1.form.c [new file with mode: 0644]
usr/src/cmd/struct/1.fort.c [new file with mode: 0644]
usr/src/cmd/struct/1.hash.c [new file with mode: 0644]
usr/src/cmd/struct/1.incl.h [new file with mode: 0644]
usr/src/cmd/struct/1.init.c [new file with mode: 0644]
usr/src/cmd/struct/1.line.c [new file with mode: 0644]
usr/src/cmd/struct/1.main.c [new file with mode: 0644]
usr/src/cmd/struct/1.node.c [new file with mode: 0644]
usr/src/cmd/struct/1.recog.c [new file with mode: 0644]
usr/src/cmd/struct/1.tables.c [new file with mode: 0644]
usr/src/cmd/struct/2.def.h [new file with mode: 0644]
usr/src/cmd/struct/2.dfs.c [new file with mode: 0644]
usr/src/cmd/struct/2.dom.c [new file with mode: 0644]
usr/src/cmd/struct/2.head.c [new file with mode: 0644]
usr/src/cmd/struct/2.inarc.c [new file with mode: 0644]
usr/src/cmd/struct/2.main.c [new file with mode: 0644]
usr/src/cmd/struct/2.test.c [new file with mode: 0644]
usr/src/cmd/struct/2.tree.c [new file with mode: 0644]
usr/src/cmd/struct/3.branch.c [new file with mode: 0644]
usr/src/cmd/struct/3.def.h [new file with mode: 0644]
usr/src/cmd/struct/3.flow.c [new file with mode: 0644]
usr/src/cmd/struct/3.loop.c [new file with mode: 0644]
usr/src/cmd/struct/3.main.c [new file with mode: 0644]
usr/src/cmd/struct/3.reach.c [new file with mode: 0644]
usr/src/cmd/struct/3.test.c [new file with mode: 0644]
usr/src/cmd/struct/3.then.c [new file with mode: 0644]
usr/src/cmd/struct/4.brace.c [new file with mode: 0644]
usr/src/cmd/struct/4.def.h [new file with mode: 0644]
usr/src/cmd/struct/4.form.c [new file with mode: 0644]
usr/src/cmd/struct/4.main.c [new file with mode: 0644]
usr/src/cmd/struct/4.out.c [new file with mode: 0644]
usr/src/cmd/struct/Makefile [new file with mode: 0644]
usr/src/cmd/struct/b.h [new file with mode: 0644]
usr/src/cmd/struct/bdef.c [new file with mode: 0644]
usr/src/cmd/struct/beauty.y [new file with mode: 0644]
usr/src/cmd/struct/def.h [new file with mode: 0644]
usr/src/cmd/struct/lextab.l [new file with mode: 0644]
usr/src/cmd/struct/main.c [new file with mode: 0644]
usr/src/cmd/struct/struct [new file with mode: 0755]
usr/src/cmd/struct/tree.c [new file with mode: 0644]
usr/src/cmd/tbl/t..c [new file with mode: 0644]
usr/src/cmd/tbl/t0.c [new file with mode: 0644]
usr/src/cmd/tbl/t2.c [new file with mode: 0644]
usr/src/cmd/tbl/t3.c [new file with mode: 0644]
usr/src/cmd/tbl/t4.c [new file with mode: 0644]
usr/src/cmd/tbl/t5.c [new file with mode: 0644]
usr/src/cmd/tbl/t6.c [new file with mode: 0644]
usr/src/cmd/tbl/t7.c [new file with mode: 0644]
usr/src/cmd/tbl/t8.c [new file with mode: 0644]
usr/src/cmd/tbl/t9.c [new file with mode: 0644]
usr/src/cmd/tbl/tb.c [new file with mode: 0644]
usr/src/cmd/tbl/tc.c [new file with mode: 0644]
usr/src/cmd/tbl/tf.c [new file with mode: 0644]
usr/src/cmd/tbl/tg.c [new file with mode: 0644]
usr/src/cmd/tbl/ti.c [new file with mode: 0644]
usr/src/cmd/tbl/tm.c [new file with mode: 0644]
usr/src/cmd/tbl/ts.c [new file with mode: 0644]
usr/src/cmd/tbl/tt.c [new file with mode: 0644]
usr/src/cmd/tbl/tu.c [new file with mode: 0644]
usr/src/cmd/tbl/tv.c [new file with mode: 0644]
usr/src/cmd/tp/tp.h [new file with mode: 0644]
usr/src/cmd/tp/tp0.c [new file with mode: 0644]
usr/src/cmd/tp/tp2.c [new file with mode: 0644]
usr/src/cmd/tp/tp3.c [new file with mode: 0644]
usr/src/cmd/troff/term/code.300 [new file with mode: 0644]
usr/src/cmd/troff/term/tab300.c [new file with mode: 0644]
usr/src/cmd/troff/term/tab300S.c [new file with mode: 0644]
usr/src/cmd/troff/term/tab300X.c [new file with mode: 0644]
usr/src/cmd/troff/term/tab300s.c [new file with mode: 0644]
usr/src/cmd/troff/term/tab37.c [new file with mode: 0644]
usr/src/cmd/troff/term/tab450-12.c [new file with mode: 0644]
usr/src/cmd/troff/term/tab450.c [new file with mode: 0644]
usr/src/cmd/troff/term/tab450X.c [new file with mode: 0644]
usr/src/cmd/troff/term/tabtn300.c [new file with mode: 0644]
usr/src/cmd/uudiff/lenrem.c [new file with mode: 0644]
usr/src/cmd/uudiff/locpart.c [new file with mode: 0644]
usr/src/cmd/uudiff/printable.c [new file with mode: 0644]
usr/src/cmd/uudiff/remdiff [new file with mode: 0755]
usr/src/cmd/uudiff/run1.c [new file with mode: 0644]
usr/src/cmd/uudiff/trim.c [new file with mode: 0644]
usr/src/cmd/xsend/enroll.c [new file with mode: 0644]
usr/src/cmd/xsend/lib.c [new file with mode: 0644]
usr/src/cmd/xsend/xget.c [new file with mode: 0644]
usr/src/cmd/xsend/xmail.h [new file with mode: 0644]
usr/src/cmd/xsend/xsend.c [new file with mode: 0644]
usr/src/cmd/yacc/dextern [new file with mode: 0644]
usr/src/cmd/yacc/y1.c [new file with mode: 0644]
usr/src/cmd/yacc/y2.c [new file with mode: 0644]
usr/src/cmd/yacc/y3.c [new file with mode: 0644]
usr/src/cmd/yacc/y4.c [new file with mode: 0644]
usr/src/cmd/yacc/yaccdiffs [new file with mode: 0644]
usr/src/cmd/yacc/yaccnews [new file with mode: 0644]
usr/src/cmd/yacc/yaccpar [new file with mode: 0644]

diff --git a/usr/src/cmd/awk/awk.def b/usr/src/cmd/awk/awk.def
new file mode 100644 (file)
index 0000000..7de49fc
--- /dev/null
@@ -0,0 +1,127 @@
+#define        xfree(a)        { if(a!=NULL) yfree(a); a=NULL;}
+#define yfree free
+#ifdef DEBUG
+#      define  dprintf if(dbg)printf
+#else
+#      define  dprintf(x1, x2, x3, x4)
+#endif
+typedef        double  awkfloat;
+
+extern char    **FS;
+extern char    **RS;
+extern char    **ORS;
+extern char    **OFS;
+extern char    **OFMT;
+extern awkfloat *NR;
+extern awkfloat *NF;
+extern char    **FILENAME;
+
+extern char    record[];
+extern int     dbg;
+extern int     lineno;
+extern int     errorflag;
+extern int     donefld;        /* 1 if record broken into fields */
+extern int     donerec;        /* 1 if record is valid (no fld has changed */
+
+typedef struct val {   /* general value during processing */
+       char    *nval;  /* name, for variables only */
+       char    *sval;  /* string value */
+       awkfloat        fval;   /* value as number */
+       unsigned        tval;   /* type info */
+       struct val      *nextval;       /* ptr to next if chained */
+} cell;
+extern cell *symtab[];
+cell   *setsymtab(), *lookup(), **makesymtab();
+
+extern cell    *recloc;        /* location of input record */
+extern cell    *nrloc;         /* NR */
+extern cell    *nfloc;         /* NF */
+
+#define        STR     01      /* string value is valid */
+#define        NUM     02      /* number value is valid */
+#define FLD    04      /* FLD means don't free string space */
+#define        CON     010     /* this is a constant */
+#define        ARR     020     /* this is an array */
+
+awkfloat setfval(), getfval();
+char   *setsval(), *getsval();
+char   *tostring(), *tokname(), *malloc();
+double log(), sqrt(), exp(), atof();
+
+/* function types */
+#define        FLENGTH 1
+#define        FSQRT   2
+#define        FEXP    3
+#define        FLOG    4
+#define        FINT    5
+
+typedef struct {
+       char otype;
+       char osub;
+       cell *optr;
+} obj;
+
+#define BOTCH  1
+struct nd {
+       char ntype;
+       char subtype;
+       struct nd *nnext;
+       int nobj;
+       struct nd *narg[BOTCH]; /* C won't take a zero length array */
+};
+typedef struct nd node;
+extern node    *winner;
+extern node    *nullstat;
+
+/* otypes */
+#define OCELL  0
+#define OEXPR  1
+#define OBOOL  2
+#define OJUMP  3
+
+/* cell subtypes */
+#define CTEMP  4
+#define CNAME  3 
+#define CVAR   2
+#define CFLD   1
+#define CCON   0
+
+/* bool subtypes */
+#define BTRUE  1
+#define BFALSE 2
+
+/* jump subtypes */
+#define JEXIT  1
+#define JNEXT  2
+#define        JBREAK  3
+#define        JCONT   4
+
+/* node types */
+#define NVALUE 1
+#define NSTAT  2
+#define NEXPR  3
+#define NPA2   4
+
+extern obj     (*proctab[])();
+extern obj     true, false;
+extern int     pairstack[], paircnt;
+
+#define cantexec(n)    (n->ntype == NVALUE)
+#define notlegal(n)    (proctab[n-FIRSTTOKEN]== nullproc)
+#define isexpr(n)      (n->ntype == NEXPR)
+#define isjump(n)      (n.otype == OJUMP)
+#define isexit(n)      (n.otype == OJUMP && n.osub == JEXIT)
+#define        isbreak(n)      (n.otype == OJUMP && n.osub == JBREAK)
+#define        iscont(n)       (n.otype == OJUMP && n.osub == JCONT)
+#define        isnext(n)       (n.otype == OJUMP && n.osub == JNEXT)
+#define isstr(n)       (n.optr->tval & STR)
+#define istrue(n)      (n.otype == OBOOL && n.osub == BTRUE)
+#define istemp(n)      (n.otype == OCELL && n.osub == CTEMP)
+#define isfld(n)       (!donefld && n.osub==CFLD && n.otype==OCELL && n.optr->nval==0)
+#define isrec(n)       (donefld && n.osub==CFLD && n.otype==OCELL && n.optr->nval!=0)
+obj    nullproc();
+obj    relop();
+
+#define MAXSYM 16
+#define        HAT     0177    /* matches ^ in regular expr */
+                       /* watch out for mach dep */
diff --git a/usr/src/cmd/awk/awk.g.y b/usr/src/cmd/awk/awk.g.y
new file mode 100644 (file)
index 0000000..3a51f76
--- /dev/null
@@ -0,0 +1,269 @@
+%token FIRSTTOKEN      /*must be first*/
+%token FINAL FATAL
+%token LT LE GT GE EQ NE
+%token MATCH NOTMATCH
+%token APPEND
+%token ADD MINUS MULT DIVIDE MOD UMINUS 
+%token ASSIGN ADDEQ SUBEQ MULTEQ DIVEQ MODEQ
+%token JUMP
+%token XBEGIN XEND
+%token NL
+%token PRINT PRINTF SPRINTF SPLIT
+%token IF ELSE WHILE FOR IN NEXT EXIT BREAK CONTINUE
+%token PROGRAM PASTAT PASTAT2
+
+%right ASGNOP
+%left  BOR
+%left  AND
+%left  NOT
+%left  NUMBER VAR ARRAY FNCN SUBSTR LSUBSTR INDEX
+%nonassoc RELOP MATCHOP
+%left  OR
+%left  STRING  DOT CCL NCCL CHAR
+%left  '(' '^' '$'
+%left  CAT
+%left  '+' '-'
+%left  '*' '/' '%'
+%left  STAR PLUS QUEST
+%left  POSTINCR PREINCR POSTDECR PREDECR INCR DECR
+%left  FIELD INDIRECT
+%token LASTTOKEN       /* has to be last */
+
+%{
+#include "awk.def"
+#ifndef        DEBUG   
+#      define  PUTS(x)
+#endif
+%}
+%%
+
+program:
+         begin pa_stats end    { if (errorflag==0) winner = stat3(PROGRAM, $1, $2, $3); }
+       | error                 { yyclearin; yyerror("bailing out"); }
+       ;
+
+begin:
+         XBEGIN '{' stat_list '}'      { PUTS("XBEGIN list"); $$ = $3; }
+       | begin NL
+       |       { PUTS("empty XBEGIN"); $$ = nullstat; }
+       ;
+
+end:
+         XEND '{' stat_list '}'        { PUTS("XEND list"); $$ = $3; }
+       | end NL
+       |       { PUTS("empty END"); $$ = nullstat; }
+       ;
+
+compound_conditional:
+         conditional BOR conditional   { PUTS("cond||cond"); $$ = op2(BOR, $1, $3); }
+       | conditional AND conditional   { PUTS("cond&&cond"); $$ = op2(AND, $1, $3); }
+       | NOT conditional               { PUTS("!cond"); $$ = op1(NOT, $2); }
+       | '(' compound_conditional ')'  { $$ = $2; }
+       ;
+
+compound_pattern:
+         pattern BOR pattern   { PUTS("pat||pat"); $$ = op2(BOR, $1, $3); }
+       | pattern AND pattern   { PUTS("pat&&pat"); $$ = op2(AND, $1, $3); }
+       | NOT pattern           { PUTS("!pat"); $$ = op1(NOT, $2); }
+       | '(' compound_pattern ')'      { $$ = $2; }
+       ;
+
+conditional:
+         expr  { PUTS("expr"); $$ = op2(NE, $1, valtonode(lookup("0", symtab), CCON)); }
+       | rel_expr              { PUTS("relexpr"); }
+       | lex_expr              { PUTS("lexexpr"); }
+       | compound_conditional  { PUTS("compcond"); }
+       ;
+
+else:
+         ELSE optNL    { PUTS("else"); }
+       ;
+
+field:
+         FIELD         { PUTS("field"); $$ = valtonode($1, CFLD); }
+       | INDIRECT term { PUTS("ind field"); $$ = op1(INDIRECT, $2); }
+       ;
+
+if:
+         IF '(' conditional ')' optNL  { PUTS("if(cond)"); $$ = $3; }
+       ;
+
+lex_expr:
+         expr MATCHOP regular_expr     { PUTS("expr~re"); $$ = op2($2, $1, makedfa($3)); }
+       | '(' lex_expr ')'      { PUTS("(lex_expr)"); $$ = $2; }
+       ;
+
+var:
+         NUMBER        {PUTS("number"); $$ = valtonode($1, CCON); }
+       | STRING        { PUTS("string"); $$ = valtonode($1, CCON); }
+       | VAR           { PUTS("var"); $$ = valtonode($1, CVAR); }
+       | VAR '[' expr ']'      { PUTS("array[]"); $$ = op2(ARRAY, $1, $3); }
+       | field
+       ;
+term:
+         var
+       | FNCN          { PUTS("func");
+                       $$ = op2(FNCN, $1, valtonode(lookup("$record", symtab), CFLD));
+                       }
+       | FNCN '(' ')'  { PUTS("func()"); 
+                       $$ = op2(FNCN, $1, valtonode(lookup("$record", symtab), CFLD));
+                       }
+       | FNCN '(' expr ')'     { PUTS("func(expr)"); $$ = op2(FNCN, $1, $3); }
+       | SPRINTF print_list    { PUTS("sprintf"); $$ = op1($1, $2); }
+       | SUBSTR '(' expr ',' expr ',' expr ')'
+                       { PUTS("substr(e,e,e)"); $$ = op3(SUBSTR, $3, $5, $7); }
+       | SUBSTR '(' expr ',' expr ')'
+                       { PUTS("substr(e,e,e)"); $$ = op3(SUBSTR, $3, $5, nullstat); }
+       | SPLIT '(' expr ',' VAR ',' expr ')'
+                       { PUTS("split(e,e,e)"); $$ = op3(SPLIT, $3, $5, $7); }
+       | SPLIT '(' expr ',' VAR ')'
+                       { PUTS("split(e,e,e)"); $$ = op3(SPLIT, $3, $5, nullstat); }
+       | INDEX '(' expr ',' expr ')'
+                       { PUTS("index(e,e)"); $$ = op2(INDEX, $3, $5); }
+       | '(' expr ')'                  {PUTS("(expr)");  $$ = $2; }
+       | term '+' term                 { PUTS("t+t"); $$ = op2(ADD, $1, $3); }
+       | term '-' term                 { PUTS("t-t"); $$ = op2(MINUS, $1, $3); }
+       | term '*' term                 { PUTS("t*t"); $$ = op2(MULT, $1, $3); }
+       | term '/' term                 { PUTS("t/t"); $$ = op2(DIVIDE, $1, $3); }
+       | term '%' term                 { PUTS("t%t"); $$ = op2(MOD, $1, $3); }
+       | '-' term %prec QUEST          { PUTS("-term"); $$ = op1(UMINUS, $2); }
+       | '+' term %prec QUEST          { PUTS("+term"); $$ = $2; }
+       | INCR var      { PUTS("++var"); $$ = op1(PREINCR, $2); }
+       | DECR var      { PUTS("--var"); $$ = op1(PREDECR, $2); }
+       | var INCR      { PUTS("var++"); $$= op1(POSTINCR, $1); }
+       | var DECR      { PUTS("var--"); $$= op1(POSTDECR, $1); }
+       ;
+
+expr:
+         term          { PUTS("term"); }
+       | expr term     { PUTS("expr term"); $$ = op2(CAT, $1, $2); }
+       | var ASGNOP expr       { PUTS("var=expr"); $$ = stat2($2, $1, $3); }
+       ;
+
+optNL:
+         NL
+       |
+       ;
+
+pa_stat:
+         pattern       { PUTS("pattern"); $$ = stat2(PASTAT, $1, genprint()); }
+       | pattern '{' stat_list '}'     { PUTS("pattern {...}"); $$ = stat2(PASTAT, $1, $3); }
+       | pattern ',' pattern           { PUTS("srch,srch"); $$ = pa2stat($1, $3, genprint()); }
+       | pattern ',' pattern '{' stat_list '}' 
+                                       { PUTS("srch, srch {...}"); $$ = pa2stat($1, $3, $5); }
+       | '{' stat_list '}'     { PUTS("null pattern {...}"); $$ = stat2(PASTAT, nullstat, $2); }
+       ;
+
+pa_stats:
+         pa_stats pa_stat st   { PUTS("pa_stats pa_stat"); $$ = linkum($1, $2); }
+       |       { PUTS("null pa_stat"); $$ = nullstat; }
+       | pa_stats pa_stat      {PUTS("pa_stats pa_stat"); $$ = linkum($1, $2); }
+       ;
+
+pattern:
+         regular_expr  { PUTS("regex");
+               $$ = op2(MATCH, valtonode(lookup("$record", symtab), CFLD), makedfa($1));
+               }
+       | rel_expr      { PUTS("relexpr"); }
+       | lex_expr      { PUTS("lexexpr"); }
+       | compound_pattern      { PUTS("comp pat"); }
+       ;
+
+print_list:
+         expr  { PUTS("expr"); }
+       | pe_list       { PUTS("pe_list"); }
+       |               { PUTS("null print_list"); $$ = valtonode(lookup("$record", symtab), CFLD); }
+       ;
+
+pe_list:
+         expr ',' expr {$$ = linkum($1, $3); }
+       | pe_list ',' expr      {$$ = linkum($1, $3); }
+       | '(' pe_list ')'               {$$ = $2; }
+       ;
+
+redir:
+         RELOP
+       | '|'
+       ;
+
+regular_expr:
+         '/'   { startreg(); }
+         r '/'
+               { PUTS("/r/"); $$ = $3; }
+       ;
+
+r:
+         CHAR          { PUTS("regex CHAR"); $$ = op2(CHAR, (node *) 0, $1); }
+       | DOT           { PUTS("regex DOT"); $$ = op2(DOT, (node *) 0, (node *) 0); }
+       | CCL           { PUTS("regex CCL"); $$ = op2(CCL, (node *) 0, cclenter($1)); }
+       | NCCL          { PUTS("regex NCCL"); $$ = op2(NCCL, (node *) 0, cclenter($1)); }
+       | '^'           { PUTS("regex ^"); $$ = op2(CHAR, (node *) 0, HAT); }
+       | '$'           { PUTS("regex $"); $$ = op2(CHAR, (node *) 0 ,(node *) 0); }
+       | r OR r        { PUTS("regex OR"); $$ = op2(OR, $1, $3); }
+       | r r   %prec CAT
+                       { PUTS("regex CAT"); $$ = op2(CAT, $1, $2); }
+       | r STAR        { PUTS("regex STAR"); $$ = op2(STAR, $1, (node *) 0); }
+       | r PLUS        { PUTS("regex PLUS"); $$ = op2(PLUS, $1, (node *) 0); }
+       | r QUEST       { PUTS("regex QUEST"); $$ = op2(QUEST, $1, (node *) 0); }
+       | '(' r ')'     { PUTS("(regex)"); $$ = $2; }
+       ;
+
+rel_expr:
+         expr RELOP expr
+               { PUTS("expr relop expr"); $$ = op2($2, $1, $3); }
+       | '(' rel_expr ')'
+               { PUTS("(relexpr)"); $$ = $2; }
+       ;
+
+st:
+         NL
+       | ';'
+       ;
+
+simple_stat:
+         PRINT print_list redir expr
+               { PUTS("print>stat"); $$ = stat3($1, $2, $3, $4); }
+       | PRINT print_list      
+               { PUTS("print list"); $$ = stat3($1, $2, nullstat, nullstat); }
+       | PRINTF print_list redir expr
+               { PUTS("printf>stat"); $$ = stat3($1, $2, $3, $4); }
+       | PRINTF print_list     
+               { PUTS("printf list"); $$ = stat3($1, $2, nullstat, nullstat); }
+       | expr  { PUTS("expr"); $$ = exptostat($1); }
+       |               { PUTS("null simple statement"); $$ = nullstat; }
+       | error         { yyclearin; yyerror("illegal statement"); }
+       ;
+
+statement:
+         simple_stat st        { PUTS("simple stat"); }
+       | if statement          { PUTS("if stat"); $$ = stat3(IF, $1, $2, nullstat); }
+       | if statement else statement
+               { PUTS("if-else stat"); $$ = stat3(IF, $1, $2, $4); }
+       | while statement       { PUTS("while stat"); $$ = stat2(WHILE, $1, $2); }
+       | for                   { PUTS("for stat"); }
+       | NEXT st               { PUTS("next"); $$ = genjump(NEXT); }
+       | EXIT st               { PUTS("exit"); $$ = genjump(EXIT); }
+       | BREAK st              { PUTS("break"); $$ = genjump(BREAK); }
+       | CONTINUE st           { PUTS("continue"); $$ = genjump(CONTINUE); }
+       | '{' stat_list '}'     { PUTS("{statlist}"); $$ = $2; }
+       ;
+
+stat_list:
+         stat_list statement   { PUTS("stat_list stat"); $$ = linkum($1, $2); }
+       |                       { PUTS("null stat list"); $$ = nullstat; }
+       ;
+
+while:
+         WHILE '(' conditional ')' optNL       { PUTS("while(cond)"); $$ = $3; }
+       ;
+
+for:
+         FOR '(' simple_stat ';' conditional ';' simple_stat ')' optNL statement
+               { PUTS("for(e;e;e)"); $$ = stat4(FOR, $3, $5, $7, $10); }
+       | FOR '(' simple_stat ';'  ';' simple_stat ')' optNL statement
+               { PUTS("for(e;e;e)"); $$ = stat4(FOR, $3, nullstat, $6, $9); }
+       | FOR '(' VAR IN VAR ')' optNL statement
+               { PUTS("for(v in v)"); $$ = stat3(IN, $3, $5, $8); }
+       ;
+
+%%
diff --git a/usr/src/cmd/awk/awk.h b/usr/src/cmd/awk/awk.h
new file mode 100644 (file)
index 0000000..5f2df5f
--- /dev/null
@@ -0,0 +1,76 @@
+# define FIRSTTOKEN 257
+# define FINAL 258
+# define FATAL 259
+# define LT 260
+# define LE 261
+# define GT 262
+# define GE 263
+# define EQ 264
+# define NE 265
+# define MATCH 266
+# define NOTMATCH 267
+# define APPEND 268
+# define ADD 269
+# define MINUS 270
+# define MULT 271
+# define DIVIDE 272
+# define MOD 273
+# define UMINUS 274
+# define ASSIGN 275
+# define ADDEQ 276
+# define SUBEQ 277
+# define MULTEQ 278
+# define DIVEQ 279
+# define MODEQ 280
+# define JUMP 281
+# define XBEGIN 282
+# define XEND 283
+# define NL 284
+# define PRINT 285
+# define PRINTF 286
+# define SPRINTF 287
+# define SPLIT 288
+# define IF 289
+# define ELSE 290
+# define WHILE 291
+# define FOR 292
+# define IN 293
+# define NEXT 294
+# define EXIT 295
+# define BREAK 296
+# define CONTINUE 297
+# define PROGRAM 298
+# define PASTAT 299
+# define PASTAT2 300
+# define ASGNOP 301
+# define BOR 302
+# define AND 303
+# define NOT 304
+# define NUMBER 305
+# define VAR 306
+# define ARRAY 307
+# define FNCN 308
+# define SUBSTR 309
+# define LSUBSTR 310
+# define INDEX 311
+# define RELOP 312
+# define MATCHOP 313
+# define OR 314
+# define STRING 315
+# define DOT 316
+# define CCL 317
+# define NCCL 318
+# define CHAR 319
+# define CAT 320
+# define STAR 321
+# define PLUS 322
+# define QUEST 323
+# define POSTINCR 324
+# define PREINCR 325
+# define POSTDECR 326
+# define PREDECR 327
+# define INCR 328
+# define DECR 329
+# define FIELD 330
+# define INDIRECT 331
+# define LASTTOKEN 332
diff --git a/usr/src/cmd/awk/awk.lx.l b/usr/src/cmd/awk/awk.lx.l
new file mode 100644 (file)
index 0000000..7e0799b
--- /dev/null
@@ -0,0 +1,168 @@
+%Start A str chc sc reg comment
+
+%{
+#include       "awk.h"
+#include       "awk.def"
+#undef input   /* defeat lex */
+extern int     yylval;
+extern int     mustfld;
+
+int    lineno  = 1;
+#ifdef DEBUG
+#      define  RETURN(x)       {if (dbg) ptoken(x); return(x); }
+#else
+#      define  RETURN(x)       return(x)
+#endif
+#define        CADD    cbuf[clen++]=yytext[0];
+char   cbuf[80];
+int    clen, cflag;
+%}
+
+A      [a-zA-Z]
+B      [a-zA-Z0-9]
+D      [0-9]
+WS     [ \t]
+
+%%
+       switch (yybgin-yysvec-1) {      /* witchcraft */
+       case 0:
+               BEGIN A;
+               break;
+       case sc:
+               BEGIN A;
+               RETURN('}');
+       }
+
+<A>^\n         lineno++;
+<A>^{WS}*#.*\n lineno++;       /* strip comment lines */
+<A>{WS}                ;
+<A,reg>"\\"\n  lineno++;
+<A>"||"                RETURN(BOR);
+<A>BEGIN       RETURN(XBEGIN);
+<A>END         RETURN(XEND);
+<A>PROGEND     RETURN(EOF);
+<A>"&&"                RETURN(AND);
+<A>"!"         RETURN(NOT);
+<A>"!="                { yylval = NE; RETURN(RELOP); }
+<A>"~"         { yylval = MATCH; RETURN(MATCHOP); }
+<A>"!~"                { yylval = NOTMATCH; RETURN(MATCHOP); }
+<A>"<"         { yylval = LT; RETURN(RELOP); }
+<A>"<="                { yylval = LE; RETURN(RELOP); }
+<A>"=="                { yylval = EQ; RETURN(RELOP); }
+<A>">="                { yylval = GE; RETURN(RELOP); }
+<A>">"         { yylval = GT; RETURN(RELOP); }
+<A>">>"                { yylval = APPEND; RETURN(RELOP); }
+<A>"++"                { yylval = INCR; RETURN(INCR); }
+<A>"--"                { yylval = DECR; RETURN(DECR); }
+<A>"+="                { yylval = ADDEQ; RETURN(ASGNOP); }
+<A>"-="                { yylval = SUBEQ; RETURN(ASGNOP); }
+<A>"*="                { yylval = MULTEQ; RETURN(ASGNOP); }
+<A>"/="                { yylval = DIVEQ; RETURN(ASGNOP); }
+<A>"%="                { yylval = MODEQ; RETURN(ASGNOP); }
+<A>"="         { yylval = ASSIGN; RETURN(ASGNOP); }
+
+<A>"$"{D}+     {       if (atoi(yytext+1)==0) {
+                               yylval = lookup("$record", symtab);
+                               RETURN(STRING);
+                       } else {
+                               yylval = fieldadr(atoi(yytext+1));
+                               RETURN(FIELD);
+                       }
+               }
+<A>"$"{WS}*    { RETURN(INDIRECT); }
+<A>NF          { mustfld=1; yylval = setsymtab(yytext, NULL, 0.0, NUM, symtab); RETURN(VAR); }
+<A>({D}+("."?){D}*|"."{D}+)((e|E)("+"|-)?{D}+)?        {
+               yylval = setsymtab(yytext, NULL, atof(yytext), CON|NUM, symtab); RETURN(NUMBER); }
+<A>"}"{WS}*\n  { BEGIN sc; lineno++; RETURN(';'); }
+<A>"}"         { BEGIN sc; RETURN(';'); }
+<A>;\n         { lineno++; RETURN(';'); }
+<A>\n          { lineno++; RETURN(NL); }
+<A>while       RETURN(WHILE);
+<A>for         RETURN(FOR);
+<A>if          RETURN(IF);
+<A>else                RETURN(ELSE);
+<A>next                RETURN(NEXT);
+<A>exit                RETURN(EXIT);
+<A>break       RETURN(BREAK);
+<A>continue    RETURN(CONTINUE);
+<A>print       { yylval = PRINT; RETURN(PRINT); }
+<A>printf      { yylval = PRINTF; RETURN(PRINTF); }
+<A>sprintf     { yylval = SPRINTF; RETURN(SPRINTF); }
+<A>split       { yylval = SPLIT; RETURN(SPLIT); }
+<A>substr      RETURN(SUBSTR);
+<A>index       RETURN(INDEX);
+<A>in          RETURN(IN);
+<A>length      { yylval = FLENGTH; RETURN(FNCN); }
+<A>log         { yylval = FLOG; RETURN(FNCN); }
+<A>int         { yylval = FINT; RETURN(FNCN); }
+<A>exp         { yylval = FEXP; RETURN(FNCN); }
+<A>sqrt                { yylval = FSQRT; RETURN(FNCN); }
+<A>{A}{B}*     { yylval = setsymtab(yytext, tostring(""), 0.0, STR, symtab); RETURN(VAR); }
+<A>\"          { BEGIN str; clen=0; }
+
+<A>#           { BEGIN comment; }
+<comment>\n    { BEGIN A; lineno++; RETURN(NL); }
+<comment>.     ;
+
+<A>.           { yylval = yytext[0]; RETURN(yytext[0]); }
+
+<reg>"["       { BEGIN chc; clen=0; cflag=0; }
+<reg>"[^"      { BEGIN chc; clen=0; cflag=1; }
+
+<reg>"?"       RETURN(QUEST);
+<reg>"+"       RETURN(PLUS);
+<reg>"*"       RETURN(STAR);
+<reg>"|"       RETURN(OR);
+<reg>"."       RETURN(DOT);
+<reg>"("       RETURN('(');
+<reg>")"       RETURN(')');
+<reg>"^"       RETURN('^');
+<reg>"$"       RETURN('$');
+<reg>\\.       {       if (yytext[1]=='n') yylval = '\n';
+                       else if (yytext[1] == 't') yylval = '\t';
+                       else yylval = yytext[1];
+                       RETURN(CHAR);
+               }
+<reg>"/"       { BEGIN A; unput('/'); }
+<reg>\n                { yyerror("newline in regular expression"); lineno++; BEGIN A; }
+<reg>.         { yylval = yytext[0]; RETURN(CHAR); }
+
+<str>\"                { BEGIN A; cbuf[clen]=0; yylval = setsymtab("", tostring(cbuf), 0.0, CON|STR, symtab); RETURN(STRING); }
+<str>\n                { yyerror("newline in string"); lineno++; BEGIN A; }
+<str>"\\\""    { cbuf[clen++]='"'; }
+<str,chc>"\\"n { cbuf[clen++]='\n'; }
+<str,chc>"\\"t { cbuf[clen++]='\t'; }
+<str,chc>"\\\\"        { cbuf[clen++]='\\'; }
+<str>.         CADD;
+
+<chc>"\\""]"   { cbuf[clen++]=']'; }
+<chc>"]"       { BEGIN reg; cbuf[clen]=0; yylval = tostring(cbuf);
+               if (cflag==0) { RETURN(CCL); }
+               else { RETURN(NCCL); } }
+<chc>\n                { yyerror("newline in character class"); lineno++; BEGIN A; }
+<chc>.         CADD;
+
+%%
+
+input()
+{
+       register c;
+       extern char *lexprog;
+
+       if (yysptr > yysbuf)
+               c = U(*--yysptr);
+       else if (yyin == NULL)
+               c = *lexprog++;
+       else
+               c = getc(yyin);
+       if (c == '\n')
+               yylineno++;
+       else if (c == EOF)
+               c = 0;
+       return(c);
+}
+
+startreg()
+{
+       BEGIN reg;
+}
diff --git a/usr/src/cmd/awk/b.c b/usr/src/cmd/awk/b.c
new file mode 100644 (file)
index 0000000..a3c6040
--- /dev/null
@@ -0,0 +1,536 @@
+#include "awk.def"
+#include "stdio.h"
+#include "awk.h"
+
+extern node *op2();
+extern struct fa *cgotofn();
+#define MAXLIN 256
+#define NCHARS 128
+#define NSTATES 256
+
+#define type(v)        v->nobj
+#define left(v)        v->narg[0]
+#define right(v)       v->narg[1]
+#define parent(v)      v->nnext
+
+#define LEAF   case CCL: case NCCL: case CHAR: case DOT:
+#define UNARY  case FINAL: case STAR: case PLUS: case QUEST:
+
+/* encoding in tree nodes:
+       leaf (CCL, NCCL, CHAR, DOT): left is index, right contains value or pointer to value
+       unary (FINAL, STAR, PLUS, QUEST): left is child, right is null
+       binary (CAT, OR): left and right are children
+       parent contains pointer to parent
+*/
+
+struct fa {
+       int cch;
+       struct fa *st;
+};
+
+int    *state[NSTATES];
+int    *foll[MAXLIN];
+char   chars[MAXLIN];
+int    setvec[MAXLIN];
+node   *point[MAXLIN];
+
+int    setcnt;
+int    line;
+
+
+struct fa *makedfa(p)  /* returns dfa for tree pointed to by p */
+node *p;
+{
+       node *p1;
+       struct fa *fap;
+       p1 = op2(CAT, op2(STAR, op2(DOT, (node *) 0, (node *) 0), (node *) 0), p);
+               /* put DOT STAR in front of reg. exp. */
+       p1 = op2(FINAL, p1, (node *) 0);                /* install FINAL node */
+
+       line = 0;
+       penter(p1);     /* enter parent pointers and leaf indices */
+       point[line] = p1;       /* FINAL node */
+       setvec[0] = 1;          /* for initial DOT STAR */
+       cfoll(p1);      /* set up follow sets */
+       fap = cgotofn();
+       freetr(p1);     /* add this when alloc works */
+       return(fap);
+}
+
+penter(p)      /* set up parent pointers and leaf indices */
+node *p;
+{
+       switch(type(p)) {
+               LEAF
+                       left(p) = (node *) line;
+                       point[line++] = p;
+                       break;
+               UNARY
+                       penter(left(p));
+                       parent(left(p)) = p;
+                       break;
+               case CAT:
+               case OR:
+                       penter(left(p));
+                       penter(right(p));
+                       parent(left(p)) = p;
+                       parent(right(p)) = p;
+                       break;
+               default:
+                       error(FATAL, "unknown type %d in penter\n", type(p));
+                       break;
+       }
+}
+
+freetr(p)      /* free parse tree and follow sets */
+node *p;
+{
+       switch(type(p)) {
+               LEAF
+                       xfree(foll[(int) left(p)]);
+                       xfree(p);
+                       break;
+               UNARY
+                       freetr(left(p));
+                       xfree(p);
+                       break;
+               case CAT:
+               case OR:
+                       freetr(left(p));
+                       freetr(right(p));
+                       xfree(p);
+                       break;
+               default:
+                       error(FATAL, "unknown type %d in freetr", type(p));
+                       break;
+       }
+}
+char *cclenter(p)
+register char *p;
+{
+       register i, c;
+       char *op;
+
+       op = p;
+       i = 0;
+       while ((c = *p++) != 0) {
+               if (c == '-' && i > 0 && chars[i-1] != 0) {
+                       if (*p != 0) {
+                               c = chars[i-1];
+                               while (c < *p) {
+                                       if (i >= MAXLIN)
+                                               overflo();
+                                       chars[i++] = ++c;
+                               }
+                               p++;
+                               continue;
+                       }
+               }
+               if (i >= MAXLIN)
+                       overflo();
+               chars[i++] = c;
+       }
+       chars[i++] = '\0';
+       dprintf("cclenter: in = |%s|, out = |%s|\n", op, chars, NULL);
+       xfree(op);
+       return(tostring(chars));
+}
+
+overflo()
+{
+       error(FATAL, "regular expression too long\n");
+}
+
+cfoll(v)               /* enter follow set of each leaf of vertex v into foll[leaf] */
+register node *v;
+{
+       register i;
+       int prev;
+       int *add();
+
+       switch(type(v)) {
+               LEAF
+                       setcnt = 0;
+                       for (i=1; i<=line; i++)
+                               setvec[i] = 0;
+                       follow(v);
+                       if (notin(foll, ( (int) left(v))-1, &prev)) {
+                               foll[(int) left(v)] = add(setcnt);
+                       }
+                       else
+                               foll[ (int) left(v)] = foll[prev];
+                       break;
+               UNARY
+                       cfoll(left(v));
+                       break;
+               case CAT:
+               case OR:
+                       cfoll(left(v));
+                       cfoll(right(v));
+                       break;
+               default:
+                       error(FATAL, "unknown type %d in cfoll", type(v));
+       }
+}
+
+first(p)                       /* collects initially active leaves of p into setvec */
+register node *p;              /* returns 0 or 1 depending on whether p matches empty string */
+{
+       register b;
+
+       switch(type(p)) {
+               LEAF
+                       if (setvec[(int) left(p)] != 1) {
+                               setvec[(int) left(p)] = 1;
+                               setcnt++;
+                       }
+                       if (type(p) == CCL && (*(char *) right(p)) == '\0')
+                               return(0);              /* empty CCL */
+                       else return(1);
+               case FINAL:
+               case PLUS:
+                       if (first(left(p)) == 0) return(0);
+                       return(1);
+               case STAR:
+               case QUEST:
+                       first(left(p));
+                       return(0);
+               case CAT:
+                       if (first(left(p)) == 0 && first(right(p)) == 0) return(0);
+                       return(1);
+               case OR:
+                       b = first(right(p));
+                       if (first(left(p)) == 0 || b == 0) return(0);
+                       return(1);
+       }
+       error(FATAL, "unknown type %d in first\n", type(p));
+       return(-1);
+}
+
+follow(v)
+node *v;               /* collects leaves that can follow v into setvec */
+{
+       node *p;
+
+       if (type(v) == FINAL)
+               return;
+       p = parent(v);
+       switch (type(p)) {
+               case STAR:
+               case PLUS:      first(v);
+                               follow(p);
+                               return;
+
+               case OR:
+               case QUEST:     follow(p);
+                               return;
+
+               case CAT:       if (v == left(p)) {     /* v is left child of p */
+                                       if (first(right(p)) == 0) {
+                                               follow(p);
+                                               return;
+                                       }
+                               }
+                               else            /* v is right child */
+                                       follow(p);
+                               return;
+               case FINAL:     if (setvec[line] != 1) {
+                                       setvec[line] = 1;
+                                       setcnt++;
+                               }
+                               return;
+       }
+}
+
+member(c, s)   /* is c in s? */
+register char c, *s;
+{
+       while (*s)
+               if (c == *s++)
+                       return(1);
+       return(0);
+}
+
+notin(array, n, prev)          /* is setvec in array[0] thru array[n]? */
+int **array;
+int *prev; {
+       register i, j;
+       int *ptr;
+       for (i=0; i<=n; i++) {
+               ptr = array[i];
+               if (*ptr == setcnt) {
+                       for (j=0; j < setcnt; j++)
+                               if (setvec[*(++ptr)] != 1) goto nxt;
+                       *prev = i;
+                       return(0);
+               }
+               nxt: ;
+       }
+       return(1);
+}
+
+int *add(n) {          /* remember setvec */
+       int *ptr, *p;
+       register i;
+       if ((p = ptr = (int *) malloc((n+1)*sizeof(int))) == NULL)
+               overflo();
+       *ptr = n;
+       dprintf("add(%d)\n", n, NULL, NULL);
+       for (i=1; i <= line; i++)
+               if (setvec[i] == 1) {
+                       *(++ptr) = i;
+                       dprintf("  ptr = %o, *ptr = %d, i = %d\n", ptr, *ptr, i);
+               }
+       dprintf("\n", NULL, NULL, NULL);
+       return(p);
+}
+
+struct fa *cgotofn()
+{
+       register i, k;
+       register int *ptr;
+       char c;
+       char *p;
+       node *cp;
+       int j, n, s, ind, numtrans;
+       int finflg;
+       int curpos, num, prev;
+       struct fa *where[NSTATES];
+
+       int fatab[257];
+       struct fa *pfa;
+
+       char index[MAXLIN];
+       char iposns[MAXLIN];
+       int sposns[MAXLIN];
+       int spmax, spinit;
+
+       char symbol[NCHARS];
+       char isyms[NCHARS];
+       char ssyms[NCHARS];
+       int ssmax, ssinit;
+
+       for (i=0; i<=line; i++) index[i] = iposns[i] = setvec[i] = 0;
+       for (i=0; i<NCHARS; i++)  isyms[i] = symbol[i] = 0;
+       setcnt = 0;
+       state[0] = add(0);
+       /* compute initial positions and symbols of state 0 */
+       ssmax = 0;
+       ptr = foll[0];
+       spinit = *ptr;
+       for (i=0; i<spinit; i++) {
+               curpos = *(++ptr);
+               sposns[i] = curpos;
+               iposns[curpos] = 1;
+               cp = point[curpos];
+               dprintf("i = %d, spinit = %d, curpos = %d\n", i, spinit, curpos);
+               switch (type(cp)) {
+                       case CHAR:
+                               k = (int) right(cp);
+                               if (isyms[k] != 1) {
+                                       isyms[k] = 1;
+                                       ssyms[ssmax++] = k;
+                               }
+                               break;
+                       case DOT:
+                               for (k=1; k<NCHARS; k++) {
+                                       if (k != HAT) {
+                                               if (isyms[k] != 1) {
+                                                       isyms[k] = 1;
+                                                       ssyms[ssmax++] = k;
+                                               }
+                                       }
+                               }
+                               break;
+                       case CCL:
+                               for (p = (char *) right(cp); *p; p++) {
+                                       if (*p != HAT) {
+                                               if (isyms[*p] != 1) {
+                                                       isyms[*p] = 1;
+                                                       ssyms[ssmax++] = *p;
+                                               }
+                                       }
+                               }
+                               break;
+                       case NCCL:
+                               for (k=1; k<NCHARS; k++) {
+                                       if (k != HAT && !member(k, (char *) right(cp))) {
+                                               if (isyms[k] != 1) {
+                                                       isyms[k] = 1;
+                                                       ssyms[ssmax++] = k;
+                                               }
+                                       }
+                               }
+               }
+       }
+       ssinit = ssmax;
+       n = 0;
+       for (s=0; s<=n; s++)  {
+       dprintf("s = %d\n", s, NULL, NULL);
+               ind = 0;
+               numtrans = 0;
+               finflg = 0;
+               if (*(state[s] + *state[s]) == line) {          /* s final? */
+                       finflg = 1;
+                       goto tenter;
+               }
+               spmax = spinit;
+               ssmax = ssinit;
+               ptr = state[s];
+               num = *ptr;
+               for (i=0; i<num; i++) {
+                       curpos = *(++ptr);
+                       if (iposns[curpos] != 1 && index[curpos] != 1) {
+                               index[curpos] = 1;
+                               sposns[spmax++] = curpos;
+                       }
+                       cp = point[curpos];
+                       switch (type(cp)) {
+                               case CHAR:
+                                       k = (int) right(cp);
+                                       if (isyms[k] == 0 && symbol[k] == 0) {
+                                               symbol[k] = 1;
+                                               ssyms[ssmax++] = k;
+                                       }
+                                       break;
+                               case DOT:
+                                       for (k=1; k<NCHARS; k++) {
+                                               if (k != HAT) {
+                                                       if (isyms[k] == 0 && symbol[k] == 0) {
+                                                               symbol[k] = 1;
+                                                               ssyms[ssmax++] = k;
+                                                       }
+                                               }
+                                       }
+                                       break;
+                               case CCL:
+                                       for (p = (char *) right(cp); *p; p++) {
+                                               if (*p != HAT) {
+                                                       if (isyms[*p] == 0 && symbol[*p] == 0) {
+                                                               symbol[*p] = 1;
+                                                               ssyms[ssmax++] = *p;
+                                                       }
+                                               }
+                                       }
+                                       break;
+                               case NCCL:
+                                       for (k=1; k<NCHARS; k++) {
+                                               if (k != HAT && !member(k, (char *) right(cp))) {
+                                                       if (isyms[k] == 0 && symbol[k] == 0) {
+                                                               symbol[k] = 1;
+                                                               ssyms[ssmax++] = k;
+                                                       }
+                                               }
+                                       }
+                       }
+               }
+               for (j=0; j<ssmax; j++) {       /* nextstate(s, ssyms[j]) */
+                       c = ssyms[j];
+                       symbol[c] = 0;
+                       setcnt = 0;
+                       for (k=0; k<=line; k++) setvec[k] = 0;
+                       for (i=0; i<spmax; i++) {
+                               index[sposns[i]] = 0;
+                               cp = point[sposns[i]];
+                               if ((k = type(cp)) != FINAL)
+                                       if (k == CHAR && c == (int) right(cp)
+                                        || k == DOT
+                                        || k == CCL && member(c, (char *) right(cp))
+                                        || k == NCCL && !member(c, (char *) right(cp))) {
+                                               ptr = foll[sposns[i]];
+                                               num = *ptr;
+                                               for (k=0; k<num; k++) {
+                                                       if (setvec[*(++ptr)] != 1
+                                                               && iposns[*ptr] != 1) {
+                                                               setvec[*ptr] = 1;
+                                                               setcnt++;
+                                                       }
+                                               }
+                                       }
+                       } /* end nextstate */
+                       if (notin(state, n, &prev)) {
+                               if (n >= NSTATES) {
+                                       dprintf("cgotofn: notin; state = %d, n = %d\n", state, n, NULL);
+                                       overflo();
+                               }
+                               state[++n] = add(setcnt);
+                               dprintf("       delta(%d,%o) = %d", s,c,n);
+                               dprintf(", ind = %d\n", ind+1, NULL, NULL);
+                               fatab[++ind] = c;
+                               fatab[++ind] = n;
+                               numtrans++;
+                       }
+                       else {
+                               if (prev != 0) {
+                                       dprintf("       delta(%d,%o) = %d", s,c,prev);
+                                       dprintf(", ind = %d\n", ind+1, NULL, NULL);
+                                       fatab[++ind] = c;
+                                       fatab[++ind] = prev;
+                                       numtrans++;
+                               }
+                       }
+               }
+       tenter:
+               if ((pfa = (struct fa *) malloc((numtrans + 1) * sizeof(struct fa))) == NULL)
+                       overflo();
+               where[s] = pfa;
+               if (finflg)
+                       pfa->cch = -1;          /* s is a final state */
+               else
+                       pfa->cch = numtrans;
+               pfa->st = 0;
+               for (i=1, pfa += 1; i<=numtrans; i++, pfa++) {
+                       pfa->cch = fatab[2*i-1];
+                       pfa->st = (struct fa *) fatab[2*i];
+               }
+       }
+       for (i=0; i<=n; i++) {
+               xfree(state[i]);        /* free state[i] */
+               pfa = where[i];
+               pfa->st = where[0];
+               dprintf("state %d: (%o)\n", i, pfa, NULL);
+               dprintf("       numtrans = %d,  default = %o\n", pfa->cch, pfa->st, NULL);
+               for (k=1; k<=pfa->cch; k++) {
+                       (pfa+k)->st = where[ (int) (pfa+k)->st];
+                       dprintf("       char = %o,      nextstate = %o\n",(pfa+k)->cch, (pfa+k)->st, NULL);
+               }
+       }
+       pfa = where[0];
+       if ((num = pfa->cch) < 0)
+               return(where[0]);
+       for (pfa += num; num; num--, pfa--)
+               if (pfa->cch == HAT) {
+                       return(pfa->st);
+               }
+       return(where[0]);
+}
+
+match(pfa, p)
+register struct fa *pfa;
+register char *p;
+{
+       register count;
+       char c;
+       if (p == 0) return(0);
+       if (pfa->cch == 1) {            /* fast test for first character, if possible */
+               c = (++pfa)->cch;
+               do
+                       if (c == *p) {
+                               p++;
+                               pfa = pfa->st;
+                               goto adv;
+                       }
+               while (*p++ != 0);
+               return(0);
+       }
+   adv: if ((count = pfa->cch) < 0) return(1);
+       do {
+               for (pfa += count; count; count--, pfa--)
+                       if (pfa->cch == *p) {
+                               break;
+                       }
+               pfa = pfa->st;
+               if ((count = pfa->cch) < 0) return(1);
+       } while(*p++ != 0);
+       return(0);
+}
diff --git a/usr/src/cmd/awk/dump.c b/usr/src/cmd/awk/dump.c
new file mode 100644 (file)
index 0000000..5319cee
--- /dev/null
@@ -0,0 +1,135 @@
+#include "awk.def"
+#include "stdio.h"
+#include "awk.h"
+#define printit(n) printf(printname[n-FIRSTTOKEN]);
+extern char *printname[];
+extern cell fldtab[];
+
+dump(a,b) node *a, *b;
+{
+#ifdef DEBUG
+       node *x;
+       if(a==nullstat) return;
+       for(x=a;x!=NULL;x=x->nnext)
+       {
+       if(x==b) printf(" *** ");
+               if(x->ntype==NVALUE)
+               {       switch(x->subtype)
+                       {
+                       default: runerror();
+                       case CCON: case CVAR:
+                               printf("%s",x->nobj->nval);
+                               continue;
+                       case CFLD:
+                               if(x->nobj->nval==0) printf("$%d",x->nobj - fldtab);
+                               else printf("$0");
+                               continue;
+                       }
+               }
+               else if(x->ntype==PASTAT2)
+               {       pa2dump(x,b);
+                       continue;
+               }
+               switch(x->nobj)
+               {
+               default: runerror();
+               case LE: case LT: case EQ:
+               case NE: case GT: case GE:
+               case MATCH: case NOTMATCH:
+               case ADD: case MINUS: case MULT:
+               case DIVIDE: case MOD: case ASGNOP:
+               case BOR: case AND: case CAT:
+                       dump(x->narg[0], b);
+                       printit(x->nobj);
+                       if(x->nobj!=MATCH && x->nobj!=NOTMATCH)
+                               dump(x->narg[1]);
+                       else    printf("regex");
+                       break;
+               case UMINUS: case FNCN: case INCR:
+               case DECR: case INDIRECT:
+                       printit(x->nobj);
+                       dump(x->narg[0], b);
+                       break;
+               case PRINT: case PRINTF: case SPRINTF:
+               case SPLIT:
+                       printit(x->nobj);
+                       dump(x->narg[0], b);
+                       if(x->nobj==SPLIT || x->nobj==SPRINTF) break;
+                       if(x->narg[1]==0) break;
+                       printit((int)x->narg[1]);
+                       dump(x->narg[2], b);
+                       break;
+               case IF: case WHILE:
+                       printit(x->nobj);
+                       dump(x->narg[0], b);
+                       printf(") ");
+                       dump(x->narg[1], b);
+                       if(x->narg[2]==NULL) break;
+                       printit(ELSE);
+                       dump(x->narg[2], b);
+                       break;
+               case FOR:
+                       printit(x->nobj);
+                       dump(x->narg[0], b);
+                       putchar(';');
+                       dump(x->narg[1], b);
+                       putchar(';');
+                       dump(x->narg[2], b);
+                       printf(") ");
+                       dump(x->narg[3], b);
+                       break;
+               case NEXT: case EXIT: case BREAK: case CONTINUE:
+                       printit(x->nobj);
+                       break;
+               case PROGRAM:
+                       if(x->narg[0]!=NULL)
+                       {       printf("BEGIN {");
+                               dump(x->narg[0], b);
+                               printf("}\n");
+                       }
+                       dump(x->narg[1], b);
+                       if(x->narg[2]!=NULL)
+                       {       printf("END {");
+                               dump(x->narg[2], b);
+                               printf("}\n");
+                       }
+                       break;
+               case PASTAT:
+                       dump(x->narg[0], b);
+                       printf("{");
+                       dump(x->narg[1], b);
+                       printf("}\n");
+                       break;
+               case ARRAY:
+                       printf(x->nval);
+                       printf("[");
+                       dump(x->narg[1], b);
+                       printf("]");
+                       break;
+               case SUBSTR:
+                       printit(x->nobj);
+                       dump(x->narg[0], b);
+                       putchar(',');
+                       dump(x->narg[1], b);
+                       if(x->narg[2]!=NULL)
+                       {       putchar(',');
+                               dump(x->narg[2], b);
+                       }
+                       putchar(')');
+                       break;
+               }
+               if(x->ntype == NSTAT) putchar('\n');
+       }
+#endif
+}
+pa2dump(a, b) node *a, *b;
+{
+#ifdef DEBUG
+       dump(a->narg[0], b);
+       printf(", ");
+       dump(a->narg[1], b);
+       printf(" {");
+       dump(a->narg[2], b);
+       printf("}\n");
+#endif
+}
diff --git a/usr/src/cmd/awk/parse.c b/usr/src/cmd/awk/parse.c
new file mode 100644 (file)
index 0000000..24ef508
--- /dev/null
@@ -0,0 +1,135 @@
+#include "awk.def"
+#include "awk.h"
+#include "stdio.h"
+node *ALLOC(n)
+{      node *x;
+       x = (node *)malloc(sizeof(node)+n*sizeof(node *));
+       if (x == NULL)
+               error(FATAL, "out of space in ALLOC");
+       return(x);
+}
+node *exptostat(a) node *a;
+{
+       a->ntype = NSTAT;
+       return(a);
+}
+node   *nullstat;
+node *node0(a)
+{      node *x;
+       x=ALLOC(0);
+       x->nnext = NULL;
+       x->nobj=a;
+       return(x);
+}
+node *node1(a,b) node *b;
+{      node *x;
+       x=ALLOC(1);
+       x->nnext = NULL;
+       x->nobj=a;
+       x->narg[0]=b;
+       return(x);
+}
+node *node2(a,b,c) node *b, *c;
+{      node *x;
+       x = ALLOC(2);
+       x->nnext = NULL;
+       x->nobj = a;
+       x->narg[0] = b;
+       x->narg[1] = c;
+       return(x);
+}
+node *node3(a,b,c,d) node *b, *c, *d;
+{      node *x;
+       x = ALLOC(3);
+       x->nnext = NULL;
+       x->nobj = a;
+       x->narg[0] = b;
+       x->narg[1] = c;
+       x->narg[2] = d;
+       return(x);
+}
+node *node4(a,b,c,d,e) node *b, *c, *d, *e;
+{      node *x;
+       x = ALLOC(4);
+       x->nnext = NULL;
+       x->nobj = a;
+       x->narg[0] = b;
+       x->narg[1] = c;
+       x->narg[2] = d;
+       x->narg[3] = e;
+       return(x);
+}
+node *stat3(a,b,c,d) node *b, *c, *d;
+{      node *x;
+       x = node3(a,b,c,d);
+       x->ntype = NSTAT;
+       return(x);
+}
+node *op2(a,b,c) node *b, *c;
+{      node *x;
+       x = node2(a,b,c);
+       x->ntype = NEXPR;
+       return(x);
+}
+node *op1(a,b) node *b;
+{      node *x;
+       x = node1(a,b);
+       x->ntype = NEXPR;
+       return(x);
+}
+node *stat1(a,b) node *b;
+{      node *x;
+       x = node1(a,b);
+       x->ntype = NSTAT;
+       return(x);
+}
+node *op3(a,b,c,d) node *b, *c, *d;
+{      node *x;
+       x = node3(a,b,c,d);
+       x->ntype = NEXPR;
+       return(x);
+}
+node *stat2(a,b,c) node *b, *c;
+{      node *x;
+       x = node2(a,b,c);
+       x->ntype = NSTAT;
+       return(x);
+}
+node *stat4(a,b,c,d,e) node *b, *c, *d, *e;
+{      node *x;
+       x = node4(a,b,c,d,e);
+       x->ntype = NSTAT;
+       return(x);
+}
+node *valtonode(a, b) cell *a;
+{      node *x;
+       x = node0(a);
+       x->ntype = NVALUE;
+       x->subtype = b;
+       return(x);
+}
+node *genjump(a)
+{      node *x;
+       x = node0(a);
+       x->ntype = NSTAT;
+       return(x);
+}
+node *pa2stat(a,b,c) node *a, *b, *c;
+{      node *x;
+       x = node3(paircnt++, a, b, c);
+       x->ntype = NPA2;
+       return(x);
+}
+node *linkum(a,b) node *a, *b;
+{      node *c;
+       if(a == NULL) return(b);
+       else if(b == NULL) return(a);
+       for(c=a; c->nnext != NULL; c=c->nnext);
+       c->nnext = b;
+       return(a);
+}
+node *genprint()
+{      node *x;
+       x = stat2(PRINT,valtonode(lookup("$record", symtab), CFLD), nullstat);
+       return(x);
+}
diff --git a/usr/src/cmd/awk/proc.c b/usr/src/cmd/awk/proc.c
new file mode 100644 (file)
index 0000000..a64aee9
--- /dev/null
@@ -0,0 +1,82 @@
+#include "awk.h"
+#define NULL 0
+struct xx
+{      int token;
+       char *name;
+       char *pname;
+} proc[] = {
+       { PROGRAM, "program", NULL},
+       { BOR, "boolop", " || "},
+       { AND, "boolop", " && "},
+       { NOT, "boolop", " !"},
+       { NE, "relop", " != "},
+       { EQ, "relop", " == "},
+       { LE, "relop", " <= "},
+       { LT, "relop", " < "},
+       { GE, "relop", " >= "},
+       { GT, "relop", " > "},
+       { ARRAY, "array", NULL},
+       { INDIRECT, "indirect", "$("},
+       { SUBSTR, "substr", "substr"},
+       { INDEX, "index", "index"},
+       { SPRINTF, "asprintf", "sprintf "},
+       { ADD, "arith", " + "},
+       { MINUS, "arith", " - "},
+       { MULT, "arith", " * "},
+       { DIVIDE, "arith", " / "},
+       { MOD, "arith", " % "},
+       { UMINUS, "arith", " -"},
+       { PREINCR, "incrdecr", "++"},
+       { POSTINCR, "incrdecr", "++"},
+       { PREDECR, "incrdecr", "--"},
+       { POSTDECR, "incrdecr", "--"},
+       { CAT, "cat", " "},
+       { PASTAT, "pastat", NULL},
+       { PASTAT2, "dopa2", NULL},
+       { MATCH, "matchop", " ~ "},
+       { NOTMATCH, "matchop", " !~ "},
+       { PRINTF, "aprintf", "printf"},
+       { PRINT, "print", "print"},
+       { SPLIT, "split", "split"},
+       { ASSIGN, "assign", " = "},
+       { ADDEQ, "assign", " += "},
+       { SUBEQ, "assign", " -= "},
+       { MULTEQ, "assign", " *= "},
+       { DIVEQ, "assign", " /= "},
+       { MODEQ, "assign", " %= "},
+       { IF, "ifstat", "if("},
+       { WHILE, "whilestat", "while("},
+       { FOR, "forstat", "for("},
+       { IN, "instat", "instat"},
+       { NEXT, "jump", "next"},
+       { EXIT, "jump", "exit"},
+       { BREAK, "jump", "break"},
+       { CONTINUE, "jump", "continue"},
+       { FNCN, "fncn", "fncn"},
+       { 0, ""},
+};
+#define SIZE   LASTTOKEN - FIRSTTOKEN
+char *table[SIZE];
+char *names[SIZE];
+main()
+{      struct xx *p;
+       int i;
+       printf("#include \"awk.def\"\n");
+       printf("obj nullproc();\n");
+       for(p=proc;p->token!=0;p++)
+               if(p==proc || strcmp(p->name, (p-1)->name))
+                       printf("extern obj %s();\n",p->name);
+       for(p=proc;p->token!=0;p++)
+               table[p->token-FIRSTTOKEN]=p->name;
+       printf("obj (*proctab[%d])() = {\n", SIZE);
+       for(i=0;i<SIZE;i++)
+               if(table[i]==0) printf("/*%s*/\tnullproc,\n",tokname(i+FIRSTTOKEN));
+               else printf("/*%s*/\t%s,\n",tokname(i+FIRSTTOKEN),table[i]);
+       printf("};\n");
+       printf("char *printname[%d] = {\n", SIZE);
+       for(p=proc; p->token!=0; p++)
+               names[p->token-FIRSTTOKEN] = p->pname;
+       for(i=0; i<SIZE; i++)
+               printf("/*%s*/\t\"%s\",\n",tokname(i+FIRSTTOKEN),names[i]);
+       printf("};\n");
+}
diff --git a/usr/src/cmd/awk/token.c b/usr/src/cmd/awk/token.c
new file mode 100644 (file)
index 0000000..3b559e5
--- /dev/null
@@ -0,0 +1,97 @@
+#include "awk.h"
+struct tok
+{      char *tnm;
+       int yval;
+} tok[]        = {
+"FIRSTTOKEN", 257,
+"FINAL", 258,
+"FATAL", 259,
+"LT", 260,
+"LE", 261,
+"GT", 262,
+"GE", 263,
+"EQ", 264,
+"NE", 265,
+"MATCH", 266,
+"NOTMATCH", 267,
+"APPEND", 268,
+"ADD", 269,
+"MINUS", 270,
+"MULT", 271,
+"DIVIDE", 272,
+"MOD", 273,
+"UMINUS", 274,
+"ASSIGN", 275,
+"ADDEQ", 276,
+"SUBEQ", 277,
+"MULTEQ", 278,
+"DIVEQ", 279,
+"MODEQ", 280,
+"JUMP", 281,
+"XBEGIN", 282,
+"XEND", 283,
+"NL", 284,
+"PRINT", 285,
+"PRINTF", 286,
+"SPRINTF", 287,
+"SPLIT", 288,
+"IF", 289,
+"ELSE", 290,
+"WHILE", 291,
+"FOR", 292,
+"IN", 293,
+"NEXT", 294,
+"EXIT", 295,
+"BREAK", 296,
+"CONTINUE", 297,
+"PROGRAM", 298,
+"PASTAT", 299,
+"PASTAT2", 300,
+"ASGNOP", 301,
+"BOR", 302,
+"AND", 303,
+"NOT", 304,
+"NUMBER", 305,
+"VAR", 306,
+"ARRAY", 307,
+"FNCN", 308,
+"SUBSTR", 309,
+"LSUBSTR", 310,
+"INDEX", 311,
+"RELOP", 312,
+"MATCHOP", 313,
+"OR", 314,
+"STRING", 315,
+"DOT", 316,
+"CCL", 317,
+"NCCL", 318,
+"CHAR", 319,
+"CAT", 320,
+"STAR", 321,
+"PLUS", 322,
+"QUEST", 323,
+"POSTINCR", 324,
+"PREINCR", 325,
+"POSTDECR", 326,
+"PREDECR", 327,
+"INCR", 328,
+"DECR", 329,
+"FIELD", 330,
+"INDIRECT", 331,
+"LASTTOKEN", 332,
+};
+ptoken(n)
+{
+       if(n<128) printf("lex: %c\n",n);
+       else    if(n<=256) printf("lex:? %o\n",n);
+       else    if(n<LASTTOKEN) printf("lex: %s\n",tok[n-257].tnm);
+       else    printf("lex:? %o\n",n);
+       return;
+}
+
+char *tokname(n)
+{
+       if (n<=256 || n >= LASTTOKEN)
+               n = 257;
+       return(tok[n-257].tnm);
+}
diff --git a/usr/src/cmd/awk/tokenscript b/usr/src/cmd/awk/tokenscript
new file mode 100644 (file)
index 0000000..809784c
--- /dev/null
@@ -0,0 +1,11 @@
+e y.tab.h
+1,$s/# *define *//
+1,$s/^/"/
+1,$s/ /", /
+1,$s/$/,/
+w temp
+e token.c
+/= *{$/+1,/^};$/-1d
+-r temp
+w token.c
+q
diff --git a/usr/src/cmd/awk/tran.c b/usr/src/cmd/awk/tran.c
new file mode 100644 (file)
index 0000000..769e8df
--- /dev/null
@@ -0,0 +1,237 @@
+#include "stdio.h"
+#include "awk.def"
+#include "awk.h"
+
+cell *symtab[MAXSYM];  /* symbol table pointers */
+
+char   **FS;   /* initial field sep */
+char   **RS;   /* initial record sep */
+char   **OFS;  /* output field sep */
+char   **ORS;  /* output record sep */
+char   **OFMT; /*output format for numbers*/
+awkfloat *NF;  /* number of fields in current record */
+awkfloat *NR;  /* number of current record */
+char   **FILENAME;     /* current filename argument */
+
+cell   *recloc;        /* location of record */
+cell   *nrloc;         /* NR */
+cell   *nfloc;         /* NF */
+
+syminit()
+{
+       setsymtab("0", tostring("0"), 0.0, NUM|STR|CON|FLD, symtab);
+       recloc = setsymtab("$record", record, 0.0, STR|FLD, symtab);
+       dprintf("recloc %o lookup %o\n", recloc, lookup("$record", symtab), NULL);
+       FS = &setsymtab("FS", tostring(" "), 0.0, STR|FLD, symtab)->sval;
+       RS = &setsymtab("RS", tostring("\n"), 0.0, STR|FLD, symtab)->sval;
+       OFS = &setsymtab("OFS", tostring(" "), 0.0, STR|FLD, symtab)->sval;
+       ORS = &setsymtab("ORS", tostring("\n"), 0.0, STR|FLD, symtab)->sval;
+       OFMT = &setsymtab("OFMT", tostring("%.6g"), 0.0, STR|FLD, symtab)->sval;
+       FILENAME = &setsymtab("FILENAME", NULL, 0.0, STR|FLD, symtab)->sval;
+       nfloc = setsymtab("NF", NULL, 0.0, NUM, symtab);
+       NF = &nfloc->fval;
+       nrloc = setsymtab("NR", NULL, 0.0, NUM, symtab);
+       NR = &nrloc->fval;
+}
+
+cell **makesymtab()
+{
+       int i;
+       cell **cp;
+
+       cp = (char *) malloc(MAXSYM * sizeof(cell *));
+       if (cp == NULL)
+               error(FATAL, "out of space in makesymtab");
+       for (i = 0; i < MAXSYM; i++)
+               *((cell **) cp + i) = 0;
+       return(cp);
+}
+
+freesymtab(ap) /* free symbol table */
+cell *ap;
+{
+       cell *cp, **tp;
+       int i;
+
+       if (!(ap->tval & ARR))
+               return;
+       tp = (cell **) ap->sval;
+       for (i = 0; i < MAXSYM; i++) {
+               for (cp = tp[i]; cp != NULL; cp = cp->nextval) {
+                       xfree(cp->nval);
+                       xfree(cp->sval);
+                       free(cp);
+               }
+       }
+       xfree(tp);
+}
+
+cell *setsymtab(n, s, f, t, tab)
+char *n, *s;
+awkfloat f;
+unsigned t;
+cell **tab;
+{
+       register h;
+       register cell *p;
+       cell *lookup();
+
+       if (n != NULL && *n != '\0' && (p = lookup(n, tab)) != NULL) {
+               xfree(s);
+               dprintf("setsymtab found %o: %s", p, p->nval, NULL);
+               dprintf(" %s %g %o\n", p->sval, p->fval, p->tval);
+               return(p);
+       }
+       p = (cell *) malloc(sizeof(cell));
+       if (p == NULL)
+               error(FATAL, "symbol table overflow at %s", n);
+       p->nval = tostring(n);
+       p->sval = s;
+       p->fval = f;
+       p->tval = t;
+       h = hash(n);
+       p->nextval = tab[h];
+       tab[h] = p;
+       dprintf("setsymtab set %o: %s", p, p->nval, NULL);
+       dprintf(" %s %g %o\n", p->sval, p->fval, p->tval);
+       return(p);
+}
+
+hash(s)        /* form hash value for string s */
+register char *s;
+{
+       register int hashval;
+
+       for (hashval = 0; *s != '\0'; )
+               hashval += *s++;
+       return(hashval % MAXSYM);
+}
+
+cell *lookup(s, tab)   /* look for s in tab */
+register char *s;
+cell **tab;
+{
+       register cell *p;
+
+       for (p = tab[hash(s)]; p != NULL; p = p->nextval)
+               if (strcmp(s, p->nval) == 0)
+                       return(p);      /* found it */
+       return(NULL);   /* not found */
+}
+
+awkfloat setfval(vp, f)
+register cell *vp;
+awkfloat f;
+{
+       dprintf("setfval: %o %g\n", vp, f, NULL);
+       checkval(vp);
+       if (vp == recloc)
+               error(FATAL, "can't set $0");
+       vp->tval &= ~STR;       /* mark string invalid */
+       vp->tval |= NUM;        /* mark number ok */
+       if ((vp->tval & FLD) && vp->nval == 0)
+               donerec = 0;
+       return(vp->fval = f);
+}
+
+char *setsval(vp, s)
+register cell *vp;
+char *s;
+{
+       dprintf("setsval: %o %s\n", vp, s, NULL);
+       checkval(vp);
+       if (vp == recloc)
+               error(FATAL, "can't set $0");
+       vp->tval &= ~NUM;
+       vp->tval |= STR;
+       if ((vp->tval & FLD) && vp->nval == 0)
+               donerec = 0;
+       if (!(vp->tval&FLD))
+               xfree(vp->sval);
+       vp->tval &= ~FLD;
+       return(vp->sval = tostring(s));
+}
+
+awkfloat getfval(vp)
+register cell *vp;
+{
+       awkfloat atof();
+
+       if (vp->sval == record && donerec == 0)
+               recbld();
+       dprintf("getfval: %o", vp, NULL, NULL);
+       checkval(vp);
+       if ((vp->tval & NUM) == 0) {
+               vp->fval = atof(vp->sval);
+               vp->tval |= NUM;
+               if (*vp->sval == '\0') {        /* "" is not equal to "0" */
+                       vp->tval &= ~STR;
+                       if (!(vp->tval&FLD))
+                               xfree(vp->sval);
+               }
+       }
+       dprintf("  %g\n", vp->fval, NULL, NULL);
+       return(vp->fval);
+}
+
+char *getsval(vp)
+register cell *vp;
+{
+       char s[100];
+
+       if (vp->sval == record && donerec == 0)
+               recbld();
+       dprintf("getsval: %o", vp, NULL, NULL);
+       checkval(vp);
+       if ((vp->tval & STR) == 0) {
+               if (!(vp->tval&FLD))
+                       xfree(vp->sval);
+               if ((long)vp->fval==vp->fval)
+                       sprintf(s, "%.20g", vp->fval);
+               else
+                       sprintf(s, *OFMT, vp->fval);
+               vp->sval = tostring(s);
+               vp->tval &= ~FLD;
+               vp->tval |= STR;
+       }
+       dprintf("  %s\n", vp->sval, NULL, NULL);
+       return(vp->sval);
+}
+
+checkval(vp)
+register cell *vp;
+{
+       if (vp->tval & ARR)
+               error(FATAL, "illegal reference to array %s", vp->nval);
+       if ((vp->tval & (NUM | STR)) == 0)
+               error(FATAL, "funny variable %o: %s %s %g %o", vp, vp->nval,
+                       vp->sval, vp->fval, vp->tval);
+}
+
+char *tostring(s)
+register char *s;
+{
+       register char *p;
+
+       p = malloc(strlen(s)+1);
+       if (p == NULL)
+               error(FATAL, "out of space in tostring on %s", s);
+       strcpy(p, s);
+       return(p);
+}
+#ifndef yfree
+yfree(a) char *a;
+{
+       printf("%o\n", a);
+       free(a);
+}
+#endif
+#ifdef malloc
+#undef malloc
+char *ymalloc(u) unsigned u;
+{      char *p;
+       p = malloc(u);
+       printf("%o %o\n", u, p);
+       return(p);
+}
+#endif
diff --git a/usr/src/cmd/dc/dc.c b/usr/src/cmd/dc/dc.c
new file mode 100644 (file)
index 0000000..e1c8a41
--- /dev/null
@@ -0,0 +1,1940 @@
+#include <stdio.h>
+#include <signal.h>
+#include "dc.h"
+main(argc,argv)
+int argc;
+char *argv[];
+{
+       init(argc,argv);
+       commnds();
+}
+commnds(){
+       register int c;
+       register struct blk *p,*q;
+       long l;
+       int sign;
+       struct blk **ptr,*s,*t;
+       struct sym *sp;
+       int sk,sk1,sk2;
+       int n,d;
+
+       while(1){
+               if(((c = readc())>='0' && c <= '9')|| (c>='A' && c <='F') || c == '.'){
+                       unreadc(c);
+                       p = readin();
+                       pushp(p);
+                       continue;
+               }
+               switch(c){
+               case ' ':
+               case '\n':
+               case 0377:
+               case EOF:
+                       continue;
+               case 'Y':
+                       sdump("stk",*stkptr);
+                       printf("all %ld rel %ld headmor %ld\n",all,rel,headmor);
+                       printf("nbytes %ld\n",nbytes);
+                       continue;
+               case '_':
+                       p = readin();
+                       savk = sunputc(p);
+                       chsign(p);
+                       sputc(p,savk);
+                       pushp(p);
+                       continue;
+               case '-':
+                       subt();
+                       continue;
+               case '+':
+                       if(eqk() != 0)continue;
+                       binop('+');
+                       continue;
+               case '*':
+                       arg1 = pop();
+                       EMPTY;
+                       arg2 = pop();
+                       EMPTYR(arg1);
+                       sk1 = sunputc(arg1);
+                       sk2 = sunputc(arg2);
+                       binop('*');
+                       p = pop();
+                       sunputc(p);
+                       savk = sk1+sk2;
+                       if(savk>k && savk>sk1 && savk>sk2){
+                               sk = sk1;
+                               if(sk<sk2)sk = sk2;
+                               if(sk<k)sk = k;
+                               p = removc(p,savk-sk);
+                               savk = sk;
+                       }
+                       sputc(p,savk);
+                       pushp(p);
+                       continue;
+               case '/':
+casediv:
+                       if(dscale() != 0)continue;
+                       binop('/');
+                       if(irem != 0)release(irem);
+                       release(rem);
+                       continue;
+               case '%':
+                       if(dscale() != 0)continue;
+                       binop('/');
+                       p = pop();
+                       release(p);
+                       if(irem == 0){
+                               sputc(rem,skr+k);
+                               pushp(rem);
+                               continue;
+                       }
+                       p = add0(rem,skd-(skr+k));
+                       q = add(p,irem);
+                       release(p);
+                       release(irem);
+                       sputc(q,skd);
+                       pushp(q);
+                       continue;
+               case 'v':
+                       p = pop();
+                       EMPTY;
+                       savk = sunputc(p);
+                       if(length(p) == 0){
+                               sputc(p,savk);
+                               pushp(p);
+                               continue;
+                       }
+                       if((c = sbackc(p))<0){
+                               error("sqrt of neg number\n");
+                       }
+                       if(k<savk)n = savk;
+                       else{
+                               n = k*2-savk;
+                               savk = k;
+                       }
+                       arg1 = add0(p,n);
+                       arg2 = sqrt(arg1);
+                       sputc(arg2,savk);
+                       pushp(arg2);
+                       continue;
+               case '^':
+                       neg = 0;
+                       arg1 = pop();
+                       EMPTY;
+                       if(sunputc(arg1) != 0)error("exp not an integer\n");
+                       arg2 = pop();
+                       EMPTYR(arg1);
+                       if(sfbeg(arg1) == 0 && sbackc(arg1)<0){
+                               neg++;
+                               chsign(arg1);
+                       }
+                       if(length(arg1)>=3){
+                               error("exp too big\n");
+                       }
+                       savk = sunputc(arg2);
+                       p = exp(arg2,arg1);
+                       release(arg2);
+                       rewind(arg1);
+                       c = sgetc(arg1);
+                       if(sfeof(arg1) == 0)
+                               c = sgetc(arg1)*100 + c;
+                       d = c*savk;
+                       release(arg1);
+                       if(neg == 0){
+                               if(k>=savk)n = k;
+                               else n = savk;
+                               if(n<d){
+                                       q = removc(p,d-n);
+                                       sputc(q,n);
+                                       pushp(q);
+                               }
+                               else {
+                                       sputc(p,d);
+                                       pushp(p);
+                               }
+                       }
+                       else {
+                               sputc(p,d);
+                               pushp(p);
+                       }
+                       if(neg == 0)continue;
+                       p = pop();
+                       q = salloc(2);
+                       sputc(q,1);
+                       sputc(q,0);
+                       pushp(q);
+                       pushp(p);
+                       goto casediv;
+               case 'z':
+                       p = salloc(2);
+                       n = stkptr - stkbeg;
+                       if(n >= 100){
+                               sputc(p,n/100);
+                               n %= 100;
+                       }
+                       sputc(p,n);
+                       sputc(p,0);
+                       pushp(p);
+                       continue;
+               case 'Z':
+                       p = pop();
+                       EMPTY;
+                       n = (length(p)-1)<<1;
+                       fsfile(p);
+                       sbackc(p);
+                       if(sfbeg(p) == 0){
+                               if((c = sbackc(p))<0){
+                                       n -= 2;
+                                       if(sfbeg(p) == 1)n += 1;
+                                       else {
+                                               if((c = sbackc(p)) == 0)n += 1;
+                                               else if(c > 90)n -= 1;
+                                       }
+                               }
+                               else if(c < 10) n -= 1;
+                       }
+                       release(p);
+                       q = salloc(1);
+                       if(n >= 100){
+                               sputc(q,n%100);
+                               n /= 100;
+                       }
+                       sputc(q,n);
+                       sputc(q,0);
+                       pushp(q);
+                       continue;
+               case 'i':
+                       p = pop();
+                       EMPTY;
+                       p = scalint(p);
+                       release(inbas);
+                       inbas = p;
+                       continue;
+               case 'I':
+                       p = copy(inbas,length(inbas)+1);
+                       sputc(p,0);
+                       pushp(p);
+                       continue;
+               case 'o':
+                       p = pop();
+                       EMPTY;
+                       p = scalint(p);
+                       sign = 0;
+                       n = length(p);
+                       q = copy(p,n);
+                       fsfile(q);
+                       l = c = sbackc(q);
+                       if(n != 1){
+                               if(c<0){
+                                       sign = 1;
+                                       chsign(q);
+                                       n = length(q);
+                                       fsfile(q);
+                                       l = c = sbackc(q);
+                               }
+                               if(n != 1){
+                                       while(sfbeg(q) == 0)l = l*100+sbackc(q);
+                               }
+                       }
+                       logo = log2(l);
+                       obase = l;
+                       release(basptr);
+                       if(sign == 1)obase = -l;
+                       basptr = p;
+                       outdit = bigot;
+                       if(n == 1 && sign == 0){
+                               if(c <= 16){
+                                       outdit = hexot;
+                                       fw = 1;
+                                       fw1 = 0;
+                                       ll = 70;
+                                       release(q);
+                                       continue;
+                               }
+                       }
+                       n = 0;
+                       if(sign == 1)n++;
+                       p = salloc(1);
+                       sputc(p,-1);
+                       t = add(p,q);
+                       n += length(t)*2;
+                       fsfile(t);
+                       if((c = sbackc(t))>9)n++;
+                       release(t);
+                       release(q);
+                       release(p);
+                       fw = n;
+                       fw1 = n-1;
+                       ll = 70;
+                       if(fw>=ll)continue;
+                       ll = (70/fw)*fw;
+                       continue;
+               case 'O':
+                       p = copy(basptr,length(basptr)+1);
+                       sputc(p,0);
+                       pushp(p);
+                       continue;
+               case '[':
+                       n = 0;
+                       p = salloc(0);
+                       while(1){
+                               if((c = readc()) == ']'){
+                                       if(n == 0)break;
+                                       n--;
+                               }
+                               sputc(p,c);
+                               if(c == '[')n++;
+                       }
+                       pushp(p);
+                       continue;
+               case 'k':
+                       p = pop();
+                       EMPTY;
+                       p = scalint(p);
+                       if(length(p)>1){
+                               error("scale too big\n");
+                       }
+                       rewind(p);
+                       k = sfeof(p)?0:sgetc(p);
+                       release(scalptr);
+                       scalptr = p;
+                       continue;
+               case 'K':
+                       p = copy(scalptr,length(scalptr)+1);
+                       sputc(p,0);
+                       pushp(p);
+                       continue;
+               case 'X':
+                       p = pop();
+                       EMPTY;
+                       fsfile(p);
+                       n = sbackc(p);
+                       release(p);
+                       p = salloc(2);
+                       sputc(p,n);
+                       sputc(p,0);
+                       pushp(p);
+                       continue;
+               case 'Q':
+                       p = pop();
+                       EMPTY;
+                       if(length(p)>2){
+                               error("Q?\n");
+                       }
+                       rewind(p);
+                       if((c =  sgetc(p))<0){
+                               error("neg Q\n");
+                       }
+                       release(p);
+                       while(c-- > 0){
+                               if(readptr == &readstk[0]){
+                                       error("readstk?\n");
+                               }
+                               if(*readptr != 0)release(*readptr);
+                               readptr--;
+                       }
+                       continue;
+               case 'q':
+                       if(readptr <= &readstk[1])exit(0);
+                       if(*readptr != 0)release(*readptr);
+                       readptr--;
+                       if(*readptr != 0)release(*readptr);
+                       readptr--;
+                       continue;
+               case 'f':
+                       if(stkptr == &stack[0])printf("empty stack\n");
+                       else {
+                               for(ptr = stkptr; ptr > &stack[0];){
+                                       print(*ptr--);
+                               }
+                       }
+                       continue;
+               case 'p':
+                       if(stkptr == &stack[0])printf("empty stack\n");
+                       else{
+                               print(*stkptr);
+                       }
+                       continue;
+               case 'P':
+                       p = pop();
+                       EMPTY;
+                       sputc(p,0);
+                       printf("%s",p->beg);
+                       release(p);
+                       continue;
+               case 'd':
+                       if(stkptr == &stack[0]){
+                               printf("empty stack\n");
+                               continue;
+                       }
+                       q = *stkptr;
+                       n = length(q);
+                       p = copy(*stkptr,n);
+                       pushp(p);
+                       continue;
+               case 'c':
+                       while(stkerr == 0){
+                               p = pop();
+                               if(stkerr == 0)release(p);
+                       }
+                       continue;
+               case 'S':
+                       if(stkptr == &stack[0]){
+                               error("save: args\n");
+                       }
+                       c = readc() & 0377;
+                       sptr = stable[c];
+                       sp = stable[c] = sfree;
+                       sfree = sfree->next;
+                       if(sfree == 0)goto sempty;
+                       sp->next = sptr;
+                       p = pop();
+                       EMPTY;
+                       if(c >= ARRAYST){
+                               q = copy(p,PTRSZ);
+                               for(n = 0;n < PTRSZ-1;n++)sputc(q,0);
+                               release(p);
+                               p = q;
+                       }
+                       sp->val = p;
+                       continue;
+sempty:
+                       error("symbol table overflow\n");
+               case 's':
+                       if(stkptr == &stack[0]){
+                               error("save:args\n");
+                       }
+                       c = readc() & 0377;
+                       sptr = stable[c];
+                       if(sptr != 0){
+                               p = sptr->val;
+                               if(c >= ARRAYST){
+                                       rewind(p);
+                                       while(sfeof(p) == 0)release(getwd(p));
+                               }
+                               release(p);
+                       }
+                       else{
+                               sptr = stable[c] = sfree;
+                               sfree = sfree->next;
+                               if(sfree == 0)goto sempty;
+                               sptr->next = 0;
+                       }
+                       p = pop();
+                       sptr->val = p;
+                       continue;
+               case 'l':
+                       load();
+                       continue;
+               case 'L':
+                       c = readc() & 0377;
+                       sptr = stable[c];
+                       if(sptr == 0){
+                               error("L?\n");
+                       }
+                       stable[c] = sptr->next;
+                       sptr->next = sfree;
+                       sfree = sptr;
+                       p = sptr->val;
+                       if(c >= ARRAYST){
+                               rewind(p);
+                               while(sfeof(p) == 0){
+                                       q = getwd(p);
+                                       if(q != 0)release(q);
+                               }
+                       }
+                       pushp(p);
+                       continue;
+               case ':':
+                       p = pop();
+                       EMPTY;
+                       q = scalint(p);
+                       fsfile(q);
+                       c = 0;
+                       if((sfbeg(q) == 0) && ((c = sbackc(q))<0)){
+                               error("neg index\n");
+                       }
+                       if(length(q)>2){
+                               error("index too big\n");
+                       }
+                       if(sfbeg(q) == 0)c = c*100+sbackc(q);
+                       if(c >= MAXIND){
+                               error("index too big\n");
+                       }
+                       release(q);
+                       n = readc() & 0377;
+                       sptr = stable[n];
+                       if(sptr == 0){
+                               sptr = stable[n] = sfree;
+                               sfree = sfree->next;
+                               if(sfree == 0)goto sempty;
+                               sptr->next = 0;
+                               p = salloc((c+PTRSZ)*PTRSZ);
+                               zero(p);
+                       }
+                       else{
+                               p = sptr->val;
+                               if(length(p)-PTRSZ < c*PTRSZ){
+                                       q = copy(p,(c+PTRSZ)*PTRSZ);
+                                       release(p);
+                                       p = q;
+                               }
+                       }
+                       seekc(p,c*PTRSZ);
+                       q = lookwd(p);
+                       if (q!=NULL) release(q);
+                       s = pop();
+                       EMPTY;
+                       salterwd(p,s);
+                       sptr->val = p;
+                       continue;
+               case ';':
+                       p = pop();
+                       EMPTY;
+                       q = scalint(p);
+                       fsfile(q);
+                       c = 0;
+                       if((sfbeg(q) == 0) && ((c = sbackc(q))<0)){
+                               error("neg index\n");
+                       }
+                       if(length(q)>2){
+                               error("index too big\n");
+                       }
+                       if(sfbeg(q) == 0)c = c*100+sbackc(q);
+                       if(c >= MAXIND){
+                               error("index too big\n");
+                       }
+                       release(q);
+                       n = readc() & 0377;
+                       sptr = stable[n];
+                       if(sptr != 0){
+                               p = sptr->val;
+                               if(length(p)-PTRSZ >= c*PTRSZ){
+                                       seekc(p,c*PTRSZ);
+                                       s = getwd(p);
+                                       if(s != 0){
+                                               q = copy(s,length(s));
+                                               pushp(q);
+                                               continue;
+                                       }
+                               }
+                       }
+                       q = salloc(PTRSZ);
+                       putwd(q, (struct blk *)0);
+                       pushp(q);
+                       continue;
+               case 'x':
+execute:
+                       p = pop();
+                       EMPTY;
+                       if((readptr != &readstk[0]) && (*readptr != 0)){
+                               if((*readptr)->rd == (*readptr)->wt)
+                                       release(*readptr);
+                               else{
+                                       if(readptr++ == &readstk[RDSKSZ]){
+                                               error("nesting depth\n");
+                                       }
+                               }
+                       }
+                       else readptr++;
+                       *readptr = p;
+                       if(p != 0)rewind(p);
+                       else{
+                               if((c = readc()) != '\n')unreadc(c);
+                       }
+                       continue;
+               case '?':
+                       if(++readptr == &readstk[RDSKSZ]){
+                               error("nesting depth\n");
+                       }
+                       *readptr = 0;
+                       fsave = curfile;
+                       curfile = stdin;
+                       while((c = readc()) == '!')command();
+                       p = salloc(0);
+                       sputc(p,c);
+                       while((c = readc()) != '\n'){
+                               sputc(p,c);
+                               if(c == '\\')sputc(p,readc());
+                       }
+                       curfile = fsave;
+                       *readptr = p;
+                       continue;
+               case '!':
+                       if(command() == 1)goto execute;
+                       continue;
+               case '<':
+               case '>':
+               case '=':
+                       if(cond(c) == 1)goto execute;
+                       continue;
+               default:
+                       printf("%o is unimplemented\n",c);
+               }
+       }
+}
+struct blk *
+div(ddivd,ddivr)
+struct blk *ddivd,*ddivr;
+{
+       int divsign,remsign,offset,divcarry;
+       int carry, dig,magic,d,dd;
+       long c,td,cc;
+       struct blk *ps;
+       register struct blk *p,*divd,*divr;
+
+       rem = 0;
+       p = salloc(0);
+       if(length(ddivr) == 0){
+               pushp(ddivr);
+               errorrt("divide by 0\n");
+       }
+       divsign = remsign = 0;
+       divr = ddivr;
+       fsfile(divr);
+       if(sbackc(divr) == -1){
+               divr = copy(ddivr,length(ddivr));
+               chsign(divr);
+               divsign = ~divsign;
+       }
+       divd = copy(ddivd,length(ddivd));
+       fsfile(divd);
+       if(sfbeg(divd) == 0 && sbackc(divd) == -1){
+               chsign(divd);
+               divsign = ~divsign;
+               remsign = ~remsign;
+       }
+       offset = length(divd) - length(divr);
+       if(offset < 0)goto ddone;
+       seekc(p,offset+1);
+       sputc(divd,0);
+       magic = 0;
+       fsfile(divr);
+       c = sbackc(divr);
+       if(c<10)magic++;
+       c = c*100 + (sfbeg(divr)?0:sbackc(divr));
+       if(magic>0){
+               c = (c*100 +(sfbeg(divr)?0:sbackc(divr)))*2;
+               c /= 25;
+       }
+       while(offset >= 0){
+               fsfile(divd);
+               td = sbackc(divd)*100;
+               dd = sfbeg(divd)?0:sbackc(divd);
+               td = (td+dd)*100;
+               dd = sfbeg(divd)?0:sbackc(divd);
+               td = td+dd;
+               cc = c;
+               if(offset == 0)td += 1;
+               else cc += 1;
+               if(magic != 0)td = td<<3;
+               dig = td/cc;
+               rewind(divr);
+               rewind(divxyz);
+               carry = 0;
+               while(sfeof(divr) == 0){
+                       d = sgetc(divr)*dig+carry;
+                       carry = d / 100;
+                       salterc(divxyz,d%100);
+               }
+               salterc(divxyz,carry);
+               rewind(divxyz);
+               seekc(divd,offset);
+               carry = 0;
+               while(sfeof(divd) == 0){
+                       d = slookc(divd);
+                       d = d-(sfeof(divxyz)?0:sgetc(divxyz))-carry;
+                       carry = 0;
+                       if(d < 0){
+                               d += 100;
+                               carry = 1;
+                       }
+                       salterc(divd,d);
+               }
+               divcarry = carry;
+               sbackc(p);
+               salterc(p,dig);
+               sbackc(p);
+               if(--offset >= 0)divd->wt--;
+       }
+       if(divcarry != 0){
+               salterc(p,dig-1);
+               salterc(divd,-1);
+               ps = add(divr,divd);
+               release(divd);
+               divd = ps;
+       }
+
+       rewind(p);
+       divcarry = 0;
+       while(sfeof(p) == 0){
+               d = slookc(p)+divcarry;
+               divcarry = 0;
+               if(d >= 100){
+                       d -= 100;
+                       divcarry = 1;
+               }
+               salterc(p,d);
+       }
+       if(divcarry != 0)salterc(p,divcarry);
+       fsfile(p);
+       while(sfbeg(p) == 0){
+               if(sbackc(p) == 0)truncate(p);
+               else break;
+       }
+       if(divsign < 0)chsign(p);
+       fsfile(divd);
+       while(sfbeg(divd) == 0){
+               if(sbackc(divd) == 0)truncate(divd);
+               else break;
+       }
+ddone:
+       if(remsign<0)chsign(divd);
+       if(divr != ddivr)release(divr);
+       rem = divd;
+       return(p);
+}
+dscale(){
+       register struct blk *dd,*dr;
+       register struct blk *r;
+       int c;
+
+       dr = pop();
+       EMPTYS;
+       dd = pop();
+       EMPTYSR(dr);
+       fsfile(dd);
+       skd = sunputc(dd);
+       fsfile(dr);
+       skr = sunputc(dr);
+       if(sfbeg(dr) == 1 || (sfbeg(dr) == 0 && sbackc(dr) == 0)){
+               sputc(dr,skr);
+               pushp(dr);
+               errorrt("divide by 0\n");
+       }
+       c = k-skd+skr;
+       if(c < 0)r = removr(dd,-c);
+       else {
+               r = add0(dd,c);
+               irem = 0;
+       }
+       arg1 = r;
+       arg2 = dr;
+       savk = k;
+       return(0);
+}
+struct blk *
+removr(p,n)
+struct blk *p;
+{
+       int nn;
+       register struct blk *q,*s,*r;
+
+       rewind(p);
+       nn = (n+1)/2;
+       q = salloc(nn);
+       while(n>1){
+               sputc(q,sgetc(p));
+               n -= 2;
+       }
+       r = salloc(2);
+       while(sfeof(p) == 0)sputc(r,sgetc(p));
+       release(p);
+       if(n == 1){
+               s = div(r,tenptr);
+               release(r);
+               rewind(rem);
+               if(sfeof(rem) == 0)sputc(q,sgetc(rem));
+               release(rem);
+               irem = q;
+               return(s);
+       }
+       irem = q;
+       return(r);
+}
+struct blk *
+sqrt(p)
+struct blk *p;
+{
+       struct blk *t;
+       struct blk *r,*q,*s;
+       int c,n,nn;
+
+       n = length(p);
+       fsfile(p);
+       c = sbackc(p);
+       if((n&1) != 1)c = c*100+(sfbeg(p)?0:sbackc(p));
+       n = (n+1)>>1;
+       r = salloc(n);
+       zero(r);
+       seekc(r,n);
+       nn=1;
+       while((c -= nn)>=0)nn+=2;
+       c=(nn+1)>>1;
+       fsfile(r);
+       sbackc(r);
+       if(c>=100){
+               c -= 100;
+               salterc(r,c);
+               sputc(r,1);
+       }
+       else salterc(r,c);
+       while(1){
+               q = div(p,r);
+               s = add(q,r);
+               release(q);
+               release(rem);
+               q = div(s,sqtemp);
+               release(s);
+               release(rem);
+               s = copy(r,length(r));
+               chsign(s);
+               t = add(s,q);
+               release(s);
+               fsfile(t);
+               nn = sfbeg(t)?0:sbackc(t);
+               if(nn>=0)break;
+               release(r);
+               release(t);
+               r = q;
+       }
+       release(t);
+       release(q);
+       release(p);
+       return(r);
+}
+struct blk *
+exp(base,ex)
+struct blk *base,*ex;
+{
+       register struct blk *r,*e,*p;
+       struct blk *e1,*t,*cp;
+       int temp,c,n;
+       r = salloc(1);
+       sputc(r,1);
+       p = copy(base,length(base));
+       e = copy(ex,length(ex));
+       fsfile(e);
+       if(sfbeg(e) != 0)goto edone;
+       temp=0;
+       c = sbackc(e);
+       if(c<0){
+               temp++;
+               chsign(e);
+       }
+       while(length(e) != 0){
+               e1=div(e,sqtemp);
+               release(e);
+               e = e1;
+               n = length(rem);
+               release(rem);
+               if(n != 0){
+                       e1=mult(p,r);
+                       release(r);
+                       r = e1;
+               }
+               t = copy(p,length(p));
+               cp = mult(p,t);
+               release(p);
+               release(t);
+               p = cp;
+       }
+       if(temp != 0){
+               if((c = length(base)) == 0){
+                       goto edone;
+               }
+               if(c>1)create(r);
+               else{
+                       rewind(base);
+                       if((c = sgetc(base))<=1){
+                               create(r);
+                               sputc(r,c);
+                       }
+                       else create(r);
+               }
+       }
+edone:
+       release(p);
+       release(e);
+       return(r);
+}
+init(argc,argv)
+int argc;
+char *argv[];
+{
+       register struct sym *sp;
+
+       if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+               signal(SIGINT,onintr);
+       setbuf(stdout,(char *)NULL);
+       svargc = --argc;
+       svargv = argv;
+       while(svargc>0 && svargv[1][0] == '-'){
+               switch(svargv[1][1]){
+               default:
+                       dbg=1;
+               }
+               svargc--;
+               svargv++;
+       }
+       ifile=1;
+       if(svargc<=0)curfile = stdin;
+       else if((curfile = fopen(svargv[1],"r")) == NULL){
+               printf("can't open file %s\n",svargv[1]);
+               exit(1);
+               }
+       dummy = malloc(1);
+       scalptr = salloc(1);
+       sputc(scalptr,0);
+       basptr = salloc(1);
+       sputc(basptr,10);
+       obase=10;
+       log10=log2(10L);
+       ll=70;
+       fw=1;
+       fw1=0;
+       tenptr = salloc(1);
+       sputc(tenptr,10);
+       obase=10;
+       inbas = salloc(1);
+       sputc(inbas,10);
+       sqtemp = salloc(1);
+       sputc(sqtemp,2);
+       chptr = salloc(0);
+       strptr = salloc(0);
+       divxyz = salloc(0);
+       stkbeg = stkptr = &stack[0];
+       stkend = &stack[STKSZ];
+       stkerr = 0;
+       readptr = &readstk[0];
+       k=0;
+       sp = sptr = &symlst[0];
+       while(sptr < &symlst[TBLSZ]){
+               sptr->next = ++sp;
+               sptr++;
+       }
+       sptr->next=0;
+       sfree = &symlst[0];
+       return;
+}
+onintr(){
+
+       signal(SIGINT,onintr);
+       while(readptr != &readstk[0]){
+               if(*readptr != 0){release(*readptr);}
+               readptr--;
+       }
+       curfile = stdin;
+       commnds();
+}
+pushp(p)
+struct blk *p;
+{
+       if(stkptr == stkend){
+               printf("out of stack space\n");
+               return;
+       }
+       stkerr=0;
+       *++stkptr = p;
+       return;
+}
+struct blk *
+pop(){
+       if(stkptr == stack){
+               stkerr=1;
+               return(0);
+       }
+       return(*stkptr--);
+}
+struct blk *
+readin(){
+       register struct blk *p,*q;
+       int dp,dpct;
+       register int c;
+
+       dp = dpct=0;
+       p = salloc(0);
+       while(1){
+               c = readc();
+               switch(c){
+               case '.':
+                       if(dp != 0){
+                               unreadc(c);
+                               break;
+                       }
+                       dp++;
+                       continue;
+               case '\\':
+                       readc();
+                       continue;
+               default:
+                       if(c >= 'A' && c <= 'F')c = c - 'A' + 10;
+                       else if(c >= '0' && c <= '9')c -= '0';
+                       else goto gotnum;
+                       if(dp != 0){
+                               if(dpct >= 99)continue;
+                               dpct++;
+                       }
+                       create(chptr);
+                       if(c != 0)sputc(chptr,c);
+                       q = mult(p,inbas);
+                       release(p);
+                       p = add(chptr,q);
+                       release(q);
+               }
+       }
+gotnum:
+       unreadc(c);
+       if(dp == 0){
+               sputc(p,0);
+               return(p);
+       }
+       else{
+               q = scale(p,dpct);
+               return(q);
+       }
+}
+struct blk *
+add0(p,ct)
+int ct;
+struct blk *p;
+{
+               /* returns pointer to struct with ct 0's & p */
+       register struct blk *q,*t;
+
+       q = salloc(length(p)+(ct+1)/2);
+       while(ct>1){
+               sputc(q,0);
+               ct -= 2;
+       }
+       rewind(p);
+       while(sfeof(p) == 0){
+               sputc(q,sgetc(p));
+       }
+       release(p);
+       if(ct == 1){
+               t = mult(tenptr,q);
+               release(q);
+               return(t);
+       }
+       return(q);
+}
+struct blk *
+mult(p,q)
+struct blk *p,*q;
+{
+       register struct blk *mp,*mq,*mr;
+       int sign,offset,carry;
+       int cq,cp,mt,mcr;
+
+       offset = sign = 0;
+       fsfile(p);
+       mp = p;
+       if(sfbeg(p) == 0){
+               if(sbackc(p)<0){
+                       mp = copy(p,length(p));
+                       chsign(mp);
+                       sign = ~sign;
+               }
+       }
+       fsfile(q);
+       mq = q;
+       if(sfbeg(q) == 0){
+               if(sbackc(q)<0){
+                       mq = copy(q,length(q));
+                       chsign(mq);
+                       sign = ~sign;
+               }
+       }
+       mr = salloc(length(mp)+length(mq));
+       zero(mr);
+       rewind(mq);
+       while(sfeof(mq) == 0){
+               cq = sgetc(mq);
+               rewind(mp);
+               rewind(mr);
+               mr->rd += offset;
+               carry=0;
+               while(sfeof(mp) == 0){
+                       cp = sgetc(mp);
+                       mcr = sfeof(mr)?0:slookc(mr);
+                       mt = cp*cq + carry + mcr;
+                       carry = mt/100;
+                       salterc(mr,mt%100);
+               }
+               offset++;
+               if(carry != 0){
+                       mcr = sfeof(mr)?0:slookc(mr);
+                       salterc(mr,mcr+carry);
+               }
+       }
+       if(sign < 0){
+               chsign(mr);
+       }
+       if(mp != p)release(mp);
+       if(mq != q)release(mq);
+       return(mr);
+}
+chsign(p)
+struct blk *p;
+{
+       register int carry;
+       register char ct;
+
+       carry=0;
+       rewind(p);
+       while(sfeof(p) == 0){
+               ct=100-slookc(p)-carry;
+               carry=1;
+               if(ct>=100){
+                       ct -= 100;
+                       carry=0;
+               }
+               salterc(p,ct);
+       }
+       if(carry != 0){
+               sputc(p,-1);
+               fsfile(p);
+               sbackc(p);
+               ct = sbackc(p);
+               if(ct == 99){
+                       truncate(p);
+                       sputc(p,-1);
+               }
+       }
+       else{
+               fsfile(p);
+               ct = sbackc(p);
+               if(ct == 0)truncate(p);
+       }
+       return;
+}
+readc(){
+loop:
+       if((readptr != &readstk[0]) && (*readptr != 0)){
+               if(sfeof(*readptr) == 0)return(lastchar = sgetc(*readptr));
+               release(*readptr);
+               readptr--;
+               goto loop;
+       }
+       lastchar = getc(curfile);
+       if(lastchar != EOF)return(lastchar);
+       if(readptr != &readptr[0]){
+               readptr--;
+               if(*readptr == 0)curfile = stdin;
+               goto loop;
+       }
+       if(curfile != stdin){
+               fclose(curfile);
+               curfile = stdin;
+               goto loop;
+       }
+       exit(0);
+}
+unreadc(c)
+char c;
+{
+
+       if((readptr != &readstk[0]) && (*readptr != 0)){
+               sungetc(*readptr,c);
+       }
+       else ungetc(c,curfile);
+       return;
+}
+binop(c)
+char c;
+{
+       register struct blk *r;
+
+       switch(c){
+       case '+':
+               r = add(arg1,arg2);
+               break;
+       case '*':
+               r = mult(arg1,arg2);
+               break;
+       case '/':
+               r = div(arg1,arg2);
+               break;
+       }
+       release(arg1);
+       release(arg2);
+       sputc(r,savk);
+       pushp(r);
+       return;
+}
+print(hptr)
+struct blk *hptr;
+{
+       int sc;
+       register struct blk *p,*q,*dec;
+       int dig,dout,ct;
+
+       rewind(hptr);
+       while(sfeof(hptr) == 0){
+               if(sgetc(hptr)>99){
+                       rewind(hptr);
+                       while(sfeof(hptr) == 0){
+                               printf("%c",sgetc(hptr));
+                       }
+                       printf("\n");
+                       return;
+               }
+       }
+       fsfile(hptr);
+       sc = sbackc(hptr);
+       if(sfbeg(hptr) != 0){
+               printf("0\n");
+               return;
+       }
+       count = ll;
+       p = copy(hptr,length(hptr));
+       sunputc(p);
+       fsfile(p);
+       if(sbackc(p)<0){
+               chsign(p);
+               OUTC('-');
+       }
+       if((obase == 0) || (obase == -1)){
+               oneot(p,sc,'d');
+               return;
+       }
+       if(obase == 1){
+               oneot(p,sc,'1');
+               return;
+       }
+       if(obase == 10){
+               tenot(p,sc);
+               return;
+       }
+       create(strptr);
+       dig = log10*sc;
+       dout = ((dig/10) + dig) /logo;
+       dec = getdec(p,sc);
+       p = removc(p,sc);
+       while(length(p) != 0){
+               q = div(p,basptr);
+               release(p);
+               p = q;
+               (*outdit)(rem,0);
+       }
+       release(p);
+       fsfile(strptr);
+       while(sfbeg(strptr) == 0)OUTC(sbackc(strptr));
+       if(sc == 0){
+               release(dec);
+               printf("\n");
+               return;
+       }
+       create(strptr);
+       OUTC('.');
+       ct=0;
+       do{
+               q = mult(basptr,dec);
+               release(dec);
+               dec = getdec(q,sc);
+               p = removc(q,sc);
+               (*outdit)(p,1);
+       }while(++ct < dout);
+       release(dec);
+       rewind(strptr);
+       while(sfeof(strptr) == 0)OUTC(sgetc(strptr));
+       printf("\n");
+       return;
+}
+
+struct blk *
+getdec(p,sc)
+struct blk *p;
+{
+       int cc;
+       register struct blk *q,*t,*s;
+
+       rewind(p);
+       if(length(p)*2 < sc){
+               q = copy(p,length(p));
+               return(q);
+       }
+       q = salloc(length(p));
+       while(sc >= 1){
+               sputc(q,sgetc(p));
+               sc -= 2;
+       }
+       if(sc != 0){
+               t = mult(q,tenptr);
+               s = salloc(cc = length(q));
+               release(q);
+               rewind(t);
+               while(cc-- > 0)sputc(s,sgetc(t));
+               sputc(s,0);
+               release(t);
+               t = div(s,tenptr);
+               release(s);
+               release(rem);
+               return(t);
+       }
+       return(q);
+}
+tenot(p,sc)
+struct blk *p;
+{
+       register int c,f;
+
+       fsfile(p);
+       f=0;
+       while((sfbeg(p) == 0) && ((p->rd-p->beg-1)*2 >= sc)){
+               c = sbackc(p);
+               if((c<10) && (f == 1))printf("0%d",c);
+               else printf("%d",c);
+               f=1;
+               TEST2;
+       }
+       if(sc == 0){
+               printf("\n");
+               release(p);
+               return;
+       }
+       if((p->rd-p->beg)*2 > sc){
+               c = sbackc(p);
+               printf("%d.",c/10);
+               TEST2;
+               OUTC(c%10 +'0');
+               sc--;
+       }
+       else {
+               OUTC('.');
+       }
+       if(sc > (p->rd-p->beg)*2){
+               while(sc>(p->rd-p->beg)*2){
+                       OUTC('0');
+                       sc--;
+               }
+       }
+       while(sc > 1){
+               c = sbackc(p);
+               if(c<10)printf("0%d",c);
+               else printf("%d",c);
+               sc -= 2;
+               TEST2;
+       }
+       if(sc == 1){
+               OUTC(sbackc(p)/10 +'0');
+       }
+       printf("\n");
+       release(p);
+       return;
+}
+oneot(p,sc,ch)
+struct blk *p;
+char ch;
+{
+       register struct blk *q;
+
+       q = removc(p,sc);
+       create(strptr);
+       sputc(strptr,-1);
+       while(length(q)>0){
+               p = add(strptr,q);
+               release(q);
+               q = p;
+               OUTC(ch);
+       }
+       release(q);
+       printf("\n");
+       return;
+}
+hexot(p,flg)
+struct blk *p;
+{
+       register int c;
+       rewind(p);
+       if(sfeof(p) != 0){
+               sputc(strptr,'0');
+               release(p);
+               return;
+       }
+       c = sgetc(p);
+       release(p);
+       if(c >= 16){
+               printf("hex digit > 16");
+               return;
+       }
+       sputc(strptr,c<10?c+'0':c-10+'A');
+       return;
+}
+bigot(p,flg)
+struct blk *p;
+{
+       register struct blk *t,*q;
+       register int l;
+       int neg;
+
+       if(flg == 1)t = salloc(0);
+       else{
+               t = strptr;
+               l = length(strptr)+fw-1;
+       }
+       neg=0;
+       if(length(p) != 0){
+               fsfile(p);
+               if(sbackc(p)<0){
+                       neg=1;
+                       chsign(p);
+               }
+               while(length(p) != 0){
+                       q = div(p,tenptr);
+                       release(p);
+                       p = q;
+                       rewind(rem);
+                       sputc(t,sfeof(rem)?'0':sgetc(rem)+'0');
+                       release(rem);
+               }
+       }
+       release(p);
+       if(flg == 1){
+               l = fw1-length(t);
+               if(neg != 0){
+                       l--;
+                       sputc(strptr,'-');
+               }
+               fsfile(t);
+               while(l-- > 0)sputc(strptr,'0');
+               while(sfbeg(t) == 0)sputc(strptr,sbackc(t));
+               release(t);
+       }
+       else{
+               l -= length(strptr);
+               while(l-- > 0)sputc(strptr,'0');
+               if(neg != 0){
+                       sunputc(strptr);
+                       sputc(strptr,'-');
+               }
+       }
+       sputc(strptr,' ');
+       return;
+}
+struct blk *
+add(a1,a2)
+struct blk *a1,*a2;
+{
+       register struct blk *p;
+       register int carry,n;
+       int size;
+       int c,n1,n2;
+
+       size = length(a1)>length(a2)?length(a1):length(a2);
+       p = salloc(size);
+       rewind(a1);
+       rewind(a2);
+       carry=0;
+       while(--size >= 0){
+               n1 = sfeof(a1)?0:sgetc(a1);
+               n2 = sfeof(a2)?0:sgetc(a2);
+               n = n1 + n2 + carry;
+               if(n>=100){
+                       carry=1;
+                       n -= 100;
+               }
+               else if(n<0){
+                       carry = -1;
+                       n += 100;
+               }
+               else carry = 0;
+               sputc(p,n);
+       }
+       if(carry != 0)sputc(p,carry);
+       fsfile(p);
+       if(sfbeg(p) == 0){
+               while(sfbeg(p) == 0 && (c = sbackc(p)) == 0);
+               if(c != 0)salterc(p,c);
+               truncate(p);
+       }
+       fsfile(p);
+       if(sfbeg(p) == 0 && sbackc(p) == -1){
+               while((c = sbackc(p)) == 99){
+                       if(c == EOF)break;
+               }
+               sgetc(p);
+               salterc(p,-1);
+               truncate(p);
+       }
+       return(p);
+}
+eqk(){
+       register struct blk *p,*q;
+       register int skp;
+       int skq;
+
+       p = pop();
+       EMPTYS;
+       q = pop();
+       EMPTYSR(p);
+       skp = sunputc(p);
+       skq = sunputc(q);
+       if(skp == skq){
+               arg1=p;
+               arg2=q;
+               savk = skp;
+               return(0);
+       }
+       else if(skp < skq){
+               savk = skq;
+               p = add0(p,skq-skp);
+       }
+       else {
+               savk = skp;
+               q = add0(q,skp-skq);
+       }
+       arg1=p;
+       arg2=q;
+       return(0);
+}
+struct blk *
+removc(p,n)
+struct blk *p;
+{
+       register struct blk *q,*r;
+
+       rewind(p);
+       while(n>1){
+               sgetc(p);
+               n -= 2;
+       }
+       q = salloc(2);
+       while(sfeof(p) == 0)sputc(q,sgetc(p));
+       if(n == 1){
+               r = div(q,tenptr);
+               release(q);
+               release(rem);
+               q = r;
+       }
+       release(p);
+       return(q);
+}
+struct blk *
+scalint(p)
+struct blk *p;
+{
+       register int n;
+       n = sunputc(p);
+       p = removc(p,n);
+       return(p);
+}
+struct blk *
+scale(p,n)
+struct blk *p;
+{
+       register struct blk *q,*s,*t;
+
+       t = add0(p,n);
+       q = salloc(1);
+       sputc(q,n);
+       s = exp(inbas,q);
+       release(q);
+       q = div(t,s);
+       release(t);
+       release(s);
+       release(rem);
+       sputc(q,n);
+       return(q);
+}
+subt(){
+       arg1=pop();
+       savk = sunputc(arg1);
+       chsign(arg1);
+       sputc(arg1,savk);
+       pushp(arg1);
+       if(eqk() != 0)return(1);
+       binop('+');
+       return(0);
+}
+command(){
+       int c;
+       char line[100],*sl;
+       register (*savint)(),pid,rpid;
+       int retcode;
+
+       switch(c = readc()){
+       case '<':
+               return(cond(NL));
+       case '>':
+               return(cond(NG));
+       case '=':
+               return(cond(NE));
+       default:
+               sl = line;
+               *sl++ = c;
+               while((c = readc()) != '\n')*sl++ = c;
+               *sl = 0;
+               if((pid = fork()) == 0){
+                       execl("/bin/sh","sh","-c",line,0);
+                       exit(0100);
+               }
+               savint = signal(SIGINT, SIG_IGN);
+               while((rpid = wait(&retcode)) != pid && rpid != -1);
+               signal(SIGINT,savint);
+               printf("!\n");
+               return(0);
+       }
+}
+cond(c)
+char c;
+{
+       register struct blk *p;
+       register char cc;
+
+       if(subt() != 0)return(1);
+       p = pop();
+       sunputc(p);
+       if(length(p) == 0){
+               release(p);
+               if(c == '<' || c == '>' || c == NE){
+                       readc();
+                       return(0);
+               }
+               load();
+               return(1);
+       }
+       else {
+               if(c == '='){
+                       release(p);
+                       readc();
+                       return(0);
+               }
+       }
+       if(c == NE){
+               release(p);
+               load();
+               return(1);
+       }
+       fsfile(p);
+       cc = sbackc(p);
+       release(p);
+       if((cc<0 && (c == '<' || c == NG)) ||
+               (cc >0) && (c == '>' || c == NL)){
+               readc();
+               return(0);
+       }
+       load();
+       return(1);
+}
+load(){
+       register int c;
+       register struct blk *p,*q;
+       struct blk *t,*s;
+       c = readc() & 0377;
+       sptr = stable[c];
+       if(sptr != 0){
+               p = sptr->val;
+               if(c >= ARRAYST){
+                       q = salloc(length(p));
+                       rewind(p);
+                       while(sfeof(p) == 0){
+                               s = getwd(p);
+                               if(s == 0){putwd(q, (struct blk *)NULL);}
+                               else{
+                                       t = copy(s,length(s));
+                                       putwd(q,t);
+                               }
+                       }
+                       pushp(q);
+               }
+               else{
+                       q = copy(p,length(p));
+                       pushp(q);
+               }
+       }
+       else{
+               q = salloc(1);
+               sputc(q,0);
+               pushp(q);
+       }
+       return;
+}
+log2(n)
+long n;
+{
+       register int i;
+
+       if(n == 0)return(0);
+       i=31;
+       if(n<0)return(i);
+       while((n= n<<1) >0)i--;
+       return(--i);
+}
+
+struct blk *
+salloc(size)
+int size;
+{
+       register struct blk *hdr;
+       register char *ptr;
+       all++;
+       nbytes += size;
+       ptr = malloc((unsigned)size);
+       if(ptr == 0){
+               garbage("salloc");
+               if((ptr = malloc((unsigned)size)) == 0)
+                       ospace("salloc");
+       }
+       if((hdr = hfree) == 0)hdr = morehd();
+       hfree = (struct blk *)hdr->rd;
+       hdr->rd = hdr->wt = hdr->beg = ptr;
+       hdr->last = ptr+size;
+       return(hdr);
+}
+struct blk *
+morehd(){
+       register struct blk *h,*kk;
+       headmor++;
+       nbytes += HEADSZ;
+       hfree = h = (struct blk *)malloc(HEADSZ);
+       if(hfree == 0){
+               garbage("morehd");
+               if((hfree = h = (struct blk *)malloc(HEADSZ)) == 0)
+                       ospace("headers");
+       }
+       kk = h;
+       while(h<hfree+(HEADSZ/BLK))(h++)->rd = (char *)++kk;
+       (--h)->rd=0;
+       return(hfree);
+}
+/*
+sunputc(hptr)
+struct blk *hptr;
+{
+       hptr->wt--;
+       hptr->rd = hptr->wt;
+       return(*hptr->wt);
+}
+*/
+struct blk *
+copy(hptr,size)
+struct blk *hptr;
+int size;
+{
+       register struct blk *hdr;
+       register unsigned sz;
+       register char *ptr;
+
+       all++;
+       nbytes += size;
+       sz = length(hptr);
+       ptr = nalloc(hptr->beg, (unsigned)size);
+       if(ptr == 0){
+               garbage("copy");
+               if((ptr = nalloc(hptr->beg, (unsigned)size)) == NULL){
+                       printf("copy size %d\n",size);
+                       ospace("copy");
+               }
+       }
+       if((hdr = hfree) == 0)hdr = morehd();
+       hfree = (struct blk *)hdr->rd;
+       hdr->rd = hdr->beg = ptr;
+       hdr->last = ptr+size;
+       hdr->wt = ptr+sz;
+       ptr = hdr->wt;
+       while(ptr<hdr->last)*ptr++ = '\0';
+       return(hdr);
+}
+sdump(s1,hptr)
+char *s1;
+struct blk *hptr;
+{
+       char *p;
+       printf("%s %o rd %o wt %o beg %o last %o\n",s1,hptr,hptr->rd,hptr->wt,hptr->beg,hptr->last);
+       p = hptr->beg;
+       while(p < hptr->wt)printf("%d ",*p++);
+       printf("\n");
+}
+seekc(hptr,n)
+struct blk *hptr;
+{
+       register char *nn,*p;
+
+       nn = hptr->beg+n;
+       if(nn > hptr->last){
+               nbytes += nn - hptr->last;
+               free(hptr->beg);
+               p = realloc(hptr->beg, (unsigned)n);
+               if(p == 0){
+                       hptr->beg = realloc(hptr->beg, (unsigned)(hptr->last-hptr->beg));
+                       garbage("seekc");
+                       if((p = realloc(hptr->beg, (unsigned)n)) == 0)
+                               ospace("seekc");
+               }
+               hptr->beg = p;
+               hptr->wt = hptr->last = hptr->rd = p+n;
+               return;
+       }
+       hptr->rd = nn;
+       if(nn>hptr->wt)hptr->wt = nn;
+       return;
+}
+salterwd(hptr,n)
+struct wblk *hptr;
+struct blk *n;
+{
+       if(hptr->rdw == hptr->lastw)more(hptr);
+       *hptr->rdw++ = n;
+       if(hptr->rdw > hptr->wtw)hptr->wtw = hptr->rdw;
+       return;
+}
+more(hptr)
+struct blk *hptr;
+{
+       register unsigned size;
+       register char *p;
+
+       if((size=(hptr->last-hptr->beg)*2) == 0)size=1;
+       nbytes += size/2;
+       free(hptr->beg);
+       p = realloc(hptr->beg, (unsigned)size);
+       if(p == 0){
+               hptr->beg = realloc(hptr->beg, (unsigned)(hptr->last-hptr->beg));
+               garbage("more");
+               if((p = realloc(hptr->beg,size)) == 0)
+                       ospace("more");
+       }
+       hptr->rd = hptr->rd-hptr->beg+p;
+       hptr->wt = hptr->wt-hptr->beg+p;
+       hptr->beg = p;
+       hptr->last = p+size;
+       return;
+}
+ospace(s)
+char *s;
+{
+       printf("out of space: %s\n",s);
+       printf("all %ld rel %ld headmor %ld\n",all,rel,headmor);
+       printf("nbytes %ld\n",nbytes);
+       sdump("stk",*stkptr);
+       abort();
+}
+garbage(s)
+char *s;
+{
+       int i;
+       struct blk *p, *q;
+       struct sym *tmps;
+       int ct;
+
+/*     printf("got to garbage %s\n",s);        */
+       for(i=0;i<TBLSZ;i++){
+               tmps = stable[i];
+               if(tmps != 0){
+                       if(i < ARRAYST){
+                               do {
+                                       p = tmps->val;
+                                       if(((int)p->beg & 01)  != 0){
+                                               printf("string %o\n",i);
+                                               sdump("odd beg",p);
+                                       }
+                                       redef(p);
+                                       tmps = tmps->next;
+                               } while(tmps != 0);
+                               continue;
+                       }
+                       else {
+                               do {
+                                       p = tmps->val;
+                                       rewind(p);
+                                       ct = 0;
+                                       while((q = getwd(p)) != NULL){
+                                               ct++;
+                                               if(q != 0){
+                                                       if(((int)q->beg & 01) != 0){
+                                                               printf("array %o elt %d odd\n",i-ARRAYST,ct);
+printf("tmps %o p %o\n",tmps,p);
+                                                               sdump("elt",q);
+                                                       }
+                                                       redef(q);
+                                               }
+                                       }
+                                       tmps = tmps->next;
+                               } while(tmps != 0);
+                       }
+               }
+       }
+}
+redef(p)
+struct blk *p;
+{
+       register offset;
+       register char *newp;
+
+       if ((int)p->beg&01) {
+               printf("odd ptr %o hdr %o\n",p->beg,p);
+               ospace("redef-bad");
+       }
+       free(p->beg);
+       free(dummy);
+       dummy = malloc(1);
+       if(dummy == NULL)ospace("dummy");
+       newp = realloc(p->beg, (unsigned)(p->last-p->beg));
+       if(newp == NULL)ospace("redef");
+       offset = newp - p->beg;
+       p->beg = newp;
+       p->rd += offset;
+       p->wt += offset;
+       p->last += offset;
+}
+
+release(p)
+register struct blk *p;
+{
+       rel++;
+       nbytes -= p->last - p->beg;
+       p->rd = (char *)hfree;
+       hfree = p;
+       free(p->beg);
+}
+
+struct blk *
+getwd(p)
+struct blk *p;
+{
+       register struct wblk *wp;
+
+       wp = (struct wblk *)p;
+       if (wp->rdw == wp->wtw)
+               return(NULL);
+       return(*wp->rdw++);
+}
+
+putwd(p, c)
+struct blk *p, *c;
+{
+       register struct wblk *wp;
+
+       wp = (struct wblk *)p;
+       if (wp->wtw == wp->lastw)
+               more(p);
+       *wp->wtw++ = c;
+}
+
+struct blk *
+lookwd(p)
+struct blk *p;
+{
+       register struct wblk *wp;
+
+       wp = (struct wblk *)p;
+       if (wp->rdw == wp->wtw)
+               return(NULL);
+       return(*wp->rdw);
+}
+char *
+nalloc(p,nbytes)
+register char *p;
+unsigned nbytes;
+{
+       char *malloc();
+       register char *q, *r;
+       q = r = malloc(nbytes);
+       if(q==0)
+               return(0);
+       while(nbytes--)
+               *q++ = *p++;
+       return(r);
+}
diff --git a/usr/src/cmd/dc/dc.h b/usr/src/cmd/dc/dc.h
new file mode 100644 (file)
index 0000000..eaea5af
--- /dev/null
@@ -0,0 +1,117 @@
+#define FATAL 0
+#define NFATAL 1
+#define BLK sizeof(struct blk)
+#define PTRSZ sizeof(int *)
+#define HEADSZ 1024
+#define STKSZ 100
+#define RDSKSZ 100
+#define TBLSZ 256
+#define ARRAYST 0241
+#define MAXIND 2048
+#define NL 1
+#define NG 2
+#define NE 3
+#define length(p) ((p)->wt-(p)->beg)
+#define rewind(p) (p)->rd=(p)->beg
+#define create(p)      (p)->rd = (p)->wt = (p)->beg
+#define fsfile(p)      (p)->rd = (p)->wt
+#define truncate(p)    (p)->wt = (p)->rd
+#define sfeof(p)       (((p)->rd==(p)->wt)?1:0)
+#define sfbeg(p)       (((p)->rd==(p)->beg)?1:0)
+#define sungetc(p,c)   *(--(p)->rd)=c
+#ifdef interdata
+#define NEGBYTE 0200
+#define MASK (-1 & ~0377)
+#define sgetc(p)       ( ((p)->rd==(p)->wt) ? EOF :( ((*(p)->rd & NEGBYTE) != 0) ? ( *(p)->rd++ | MASK): *(p)->rd++ ))
+#define slookc(p)      ( ((p)->rd==(p)->wt) ? EOF :( ((*(p)->rd & NEGBYTE) != 0) ? (*(p)->rd | MASK) : *(p)->rd ))
+#define sbackc(p)      ( ((p)->rd==(p)->beg) ? EOF :( ((*(--(p)->rd) & NEGBYTE) != 0) ? (*(p)->rd | MASK): *(p)->rd ))
+#endif
+#ifndef interdata
+#define sgetc(p)       (((p)->rd==(p)->wt)?EOF:*(p)->rd++)
+#define slookc(p)      (((p)->rd==(p)->wt)?EOF:*(p)->rd)
+#define sbackc(p)      (((p)->rd==(p)->beg)?EOF:*(--(p)->rd))
+#endif
+#define sputc(p,c)     {if((p)->wt==(p)->last)more(p); *(p)->wt++ = c; }
+#define salterc(p,c)   {if((p)->rd==(p)->last)more(p); *(p)->rd++ = c; if((p)->rd>(p)->wt)(p)->wt=(p)->rd;}
+#define sunputc(p)     (*( (p)->rd = --(p)->wt))
+#define zero(p)        for(pp=(p)->beg;pp<(p)->last;)*pp++='\0'
+#define OUTC(x) {printf("%c",x); if(--count == 0){printf("\\\n"); count=ll;} }
+#define TEST2  {if((count -= 2) <=0){printf("\\\n");count=ll;}}
+#define EMPTY if(stkerr != 0){printf("stack empty\n"); continue; }
+#define EMPTYR(x) if(stkerr!=0){pushp(x);printf("stack empty\n");continue;}
+#define EMPTYS if(stkerr != 0){printf("stack empty\n"); return(1);}
+#define EMPTYSR(x) if(stkerr !=0){printf("stack empty\n");pushp(x);return(1);}
+#define error(p)       {printf(p); continue; }
+#define errorrt(p)     {printf(p); return(1); }
+struct blk {
+       char    *rd;
+       char    *wt;
+       char    *beg;
+       char    *last;
+};
+struct blk *hfree;
+struct blk *getwd();
+struct blk *lookwd();
+struct blk *getdec();
+struct blk *morehd();
+
+struct blk *arg1, *arg2;
+int    svargc;
+char   savk;
+char   **svargv;
+int    dbg;
+int    ifile;
+FILE   *curfile;
+struct blk *scalptr, *basptr, *tenptr, *inbas;
+struct blk *sqtemp, *chptr, *strptr, *divxyz;
+struct blk *stack[STKSZ];
+struct blk **stkptr,**stkbeg;
+struct blk **stkend;
+int    stkerr;
+int    lastchar;
+struct blk *readstk[RDSKSZ];
+struct blk **readptr;
+struct blk *rem;
+int    k;
+struct blk *irem;
+int    skd,skr;
+struct blk *pop(),*readin(),*add0(),*mult();
+struct blk *scalint();
+struct blk *removc();
+struct blk *add(),*div(),*removr();
+struct blk *exp();
+struct blk *sqrt();
+struct blk *salloc(),*copy();
+struct blk *scale();
+int    neg;
+struct sym {
+       struct  sym *next;
+       struct  blk *val;
+} symlst[TBLSZ];
+struct sym *stable[TBLSZ];
+struct sym *sptr,*sfree;
+struct wblk {
+       struct blk **rdw;
+       struct blk **wtw;
+       struct blk **begw;
+       struct blk **lastw;
+};
+FILE   *fsave;
+long   rel;
+long   nbytes;
+long   all;
+long   headmor;
+long   obase;
+int    fw,fw1,ll;
+int    (*outdit)();
+int    bigot(),hexot();
+int    logo;
+int    log10;
+int    count;
+char   *pp;
+int    (*signal())();
+int    onintr();
+char   *malloc();
+char   *nalloc();
+char   *realloc();
+char   *dummy;
diff --git a/usr/src/cmd/eqn/diacrit.c b/usr/src/cmd/eqn/diacrit.c
new file mode 100644 (file)
index 0000000..236868f
--- /dev/null
@@ -0,0 +1,56 @@
+# include "e.h"
+# include "e.def"
+
+diacrit(p1, type) int p1, type; {
+       int c, t, effps;
+
+       c = oalloc();
+       t = oalloc();
+       effps = EFFPS(ps);
+       nrwid(p1, effps, p1);
+       printf(".nr 10 %du\n", VERT(max(eht[p1]-ebase[p1]-6*ps,0)));    /* vertical shift if high */
+       printf(".if \\n(ct>1 .nr 10 \\n(10+\\s%d.25m\\s0\n", effps);
+       printf(".nr %d \\s%d.1m\\s0\n", t, effps);      /* horiz shift if high */
+       printf(".if \\n(ct>1 .nr %d \\s%d.15m\\s0\n", t, effps);
+       switch(type) {
+               case VEC:
+                       printf(".ds %d \\v'-.4m'\\s%d\\(->\\s0\\v'.4m'\n", c, max(effps-3, 6));
+                       break;
+               case DYAD:
+                       printf(".ds %d \\v'-.4m'\\s%d\\z\\(<-\\(->\\s0\\v'.4m'\n", c, max(effps-3, 6));
+                       break;
+               case HAT:
+                       printf(".ds %d ^\n", c);
+                       break;
+               case TILDE:
+                       printf(".ds %d ~\n", c);
+                       break;
+               case DOT:
+                       printf(".ds %d \\s%d\\v'-.67m'.\\v'.67m'\\s0\n", c, effps);
+                       break;
+               case DOTDOT:
+                       printf(".ds %d \\s%d\\v'-.67m'..\\v'.67m\\s0'\n", c, effps);
+                       break;
+               case BAR:
+                       printf(".ds %d \\s%d\\v'.18m'\\h'.05m'\\l'\\n(%du-.1m\\(rn'\\h'.05m'\\v'-.18m'\\s0\n",
+                               c, effps, p1);
+                       break;
+               case UNDER:
+                       printf(".ds %d \\l'\\n(%du\\(ul'\n", c, p1);
+                       printf(".nr %d 0\n", t);
+                       printf(".nr 10 0-%d\n", ebase[p1]);
+                       break;
+               }
+       nrwid(c, ps, c);
+       if (lfont[p1] != ITAL)
+               printf(".nr %d 0\n", t);
+       printf(".as %d \\h'-\\n(%du-\\n(%du/2u+\\n(%du'\\v'0-\\n(10u'\\*(%d", 
+               p1, p1, c, t, c);
+       printf("\\v'\\n(10u'\\h'-\\n(%du+\\n(%du/2u-\\n(%du'\n", c, p1, t);
+       /* BUG - should go to right end of widest */
+       if (type != UNDER)
+               eht[p1] += VERT( (6*ps*15) / 100);      /* 0.15m */
+       if(dbg)printf(".\tdiacrit: %c over S%d, lf=%c, rf=%c, h=%d,b=%d\n",
+               type, p1, lfont[p1], rfont[p1], eht[p1], ebase[p1]);
+       ofree(c); ofree(t);
+}
diff --git a/usr/src/cmd/eqn/e.h b/usr/src/cmd/eqn/e.h
new file mode 100644 (file)
index 0000000..54fa047
--- /dev/null
@@ -0,0 +1,42 @@
+#include <stdio.h>
+
+#define        FATAL   1
+#define        ROM     '1'
+#define        ITAL    '2'
+#define        BLD     '3'
+
+#define        VERT(n) ((((n)+1)/3)*3)
+#define        EFFPS(p)        ((p) >= 6 ? (p) : 6)
+
+extern int     dbg;
+extern int     ct;
+extern int     lp[];
+extern int     used[]; /* available registers */
+extern int     ps;     /* dflt init pt size */
+extern int     deltaps;        /* default change in ps */
+extern int     gsize;  /* global size */
+extern int     gfont;  /* global font */
+extern int     ft;     /* dflt font */
+extern FILE    *curfile;       /* current input file */
+extern int     ifile;  /* input file number */
+extern int     linect; /* line number in current file */
+extern int     eqline; /* line where eqn started */
+extern int     svargc;
+extern char    **svargv;
+extern int     eht[];
+extern int     ebase[];
+extern int     lfont[];
+extern int     rfont[];
+extern int     yyval;
+extern int     *yypv;
+extern int     yylval;
+extern int     eqnreg, eqnht;
+extern int     lefteq, righteq;
+extern int     lastchar;       /* last character read by lex */
+extern int     markline;       /* 1 if this EQ/EN contains mark or lineup */
+
+typedef struct s_tbl {
+       char    *name;
+       char    *defn;
+       struct s_tbl *next;
+} tbl;
diff --git a/usr/src/cmd/eqn/e.y b/usr/src/cmd/eqn/e.y
new file mode 100644 (file)
index 0000000..f294e59
--- /dev/null
@@ -0,0 +1,166 @@
+%{#
+#include "e.h"
+#
+int    fromflg;
+%}
+%term  CONTIG QTEXT SPACE THIN TAB
+%term  MATRIX LCOL CCOL RCOL COL
+%term  MARK LINEUP
+%term  SUM INT PROD UNION INTER
+%term  LPILE PILE CPILE RPILE ABOVE
+%term  DEFINE TDEFINE NDEFINE DELIM GSIZE GFONT INCLUDE
+%right FROM TO
+%left  OVER SQRT
+%right SUP SUB
+%right SIZE FONT ROMAN ITALIC BOLD FAT
+%right UP DOWN BACK FWD
+%left  LEFT RIGHT
+%right DOT DOTDOT HAT TILDE BAR UNDER VEC DYAD
+
+%%
+
+stuff  : eqn   { putout($1); }
+       | error { error(!FATAL, "syntax error"); }
+       |       { eqnreg = 0; }
+       ;
+
+eqn    : box
+       | eqn box       { eqnbox($1, $2, 0); }
+       | eqn lineupbox { eqnbox($1, $2, 1); }
+       | LINEUP        { lineup(0); }
+       ;
+
+lineupbox: LINEUP box  { $$ = $2; lineup(1); }
+       ;
+
+matrix : MATRIX        { $$ = ct; } ;
+
+collist        : column
+       | collist column
+       ;
+
+column : lcol '{' list '}'     { column('L', $1); }
+       | ccol '{' list '}'     { column('C', $1); }
+       | rcol '{' list '}'     { column('R', $1); }
+       | col '{' list '}'      { column('-', $1); }
+       ;
+
+lcol   : LCOL          { $$ = ct++; } ;
+ccol   : CCOL          { $$ = ct++; } ;
+rcol   : RCOL          { $$ = ct++; } ;
+col    : COL           { $$ = ct++; } ;
+
+sbox   : sup box       %prec SUP       { $$ = $2; }
+       ;
+
+tbox   : to box        %prec TO        { $$ = $2; }
+       |               %prec FROM      { $$ = 0; }
+       ;
+
+box    : box OVER box  { boverb($1, $3); }
+       | MARK box      { mark($2); }
+       | size box      %prec SIZE      { size($1, $2); }
+       | font box      %prec FONT      { font($1, $2); }
+       | FAT box       { fatbox($2); }
+       | SQRT box      { sqrt($2); }
+       | lpile '{' list '}'    { lpile('L', $1, ct); ct = $1; }
+       | cpile '{' list '}'    { lpile('C', $1, ct); ct = $1; }
+       | rpile '{' list '}'    { lpile('R', $1, ct); ct = $1; }
+       | pile '{' list '}'     { lpile('-', $1, ct); ct = $1; }
+       | box sub box sbox      %prec SUB       { shift2($1, $3, $4); }
+       | box sub box           %prec SUB       { bshiftb($1, $2, $3); }
+       | box sup box           %prec SUP       { bshiftb($1, $2, $3); }
+       | int sub box sbox      %prec SUB       { integral($1, $3, $4); }
+       | int sub box           %prec SUB       { integral($1, $3, 0); }
+       | int sup box           %prec SUP       { integral($1, 0, $3); }
+       | int                                   { integral($1, 0, 0); }
+       | left eqn right        { paren($1, $2, $3); }
+       | pbox
+       | box from box tbox     %prec FROM      { fromto($1, $3, $4); fromflg=0; }
+       | box to box    %prec TO        { fromto($1, 0, $3); }
+       | box diacrit   { diacrit($1, $2); }
+       | fwd box       %prec UP        { move(FWD, $1, $2); }
+       | up box        %prec UP        { move(UP, $1, $2); }
+       | back box      %prec UP        { move(BACK, $1, $2); }
+       | down box      %prec UP        { move(DOWN, $1, $2); }
+       | matrix '{' collist '}'        { matrix($1); }
+       ;
+
+int    : INT   { setintegral(); }
+       ;
+
+fwd    : FWD text      { $$ = atoi((char *) $1); } ;
+up     : UP text       { $$ = atoi((char *) $1); } ;
+back   : BACK text     { $$ = atoi((char *) $1); } ;
+down   : DOWN text     { $$ = atoi((char *) $1); } ;
+
+diacrit        : HAT   { $$ = HAT; }
+       | VEC   { $$ = VEC; }
+       | DYAD  { $$ = DYAD; }
+       | BAR   { $$ = BAR; }
+       | UNDER { $$ = UNDER; } /* under bar */
+       | DOT   { $$ = DOT; }
+       | TILDE { $$ = TILDE; }
+       | DOTDOT        { $$ = DOTDOT; } /* umlaut = double dot */
+       ;
+
+from   : FROM  { $$=ps; ps -= 3; fromflg = 1;
+               if(dbg)printf(".\tfrom: old ps %d, new ps %d, fflg %d\n", $$, ps, fromflg);
+               }
+       ;
+
+to     : TO    { $$=ps; if(fromflg==0)ps -= 3; 
+                       if(dbg)printf(".\tto: old ps %d, new ps %d\n", $$, ps);
+               }
+       ;
+
+left   : LEFT text     { $$ = ((char *)$2)[0]; }
+       | LEFT '{'      { $$ = '{'; }
+       ;
+
+right  : RIGHT text    { $$ = ((char *)$2)[0]; }
+       | RIGHT '}'     { $$ = '}'; }
+       |               { $$ = 0; }
+       ;
+
+list   : eqn   { lp[ct++] = $1; }
+       | list ABOVE eqn        { lp[ct++] = $3; }
+       ;
+
+lpile  : LPILE { $$ = ct; } ;
+cpile  : CPILE { $$ = ct; } ;
+pile   : PILE  { $$ = ct; } ;
+rpile  : RPILE { $$ = ct; } ;
+
+size   : SIZE text     { $$ = ps; setsize((char *) $2); }
+       ;
+
+font   : ROMAN         { setfont(ROM); }
+       | ITALIC        { setfont(ITAL); }
+       | BOLD          { setfont(BLD); }
+       | FONT text     { setfont(((char *)$2)[0]); }
+       ;
+
+sub    : SUB   { shift(SUB); }
+       ;
+
+sup    : SUP   { shift(SUP); }
+       ;
+
+pbox   : '{' eqn '}'   { $$ = $2; }
+       | QTEXT         { text(QTEXT, (char *) $1); }
+       | CONTIG        { text(CONTIG, (char *) $1); }
+       | SPACE         { text(SPACE, 0); }
+       | THIN          { text(THIN, 0); }
+       | TAB           { text(TAB, 0); }
+       | SUM           { funny(SUM); }
+       | PROD          { funny(PROD); }
+       | UNION         { funny(UNION); }
+       | INTER         { funny(INTER); }       /* intersection */
+       ;
+
+text   : CONTIG
+       | QTEXT
+       ;
+
+%%
diff --git a/usr/src/cmd/eqn/eqnbox.c b/usr/src/cmd/eqn/eqnbox.c
new file mode 100644 (file)
index 0000000..2aea8da
--- /dev/null
@@ -0,0 +1,25 @@
+# include "e.h"
+
+eqnbox(p1, p2, lu) {
+       int b, h;
+       char *sh;
+
+       yyval = p1;
+       b = max(ebase[p1], ebase[p2]);
+       eht[yyval] = h = b + max(eht[p1]-ebase[p1], 
+               eht[p2]-ebase[p2]);
+       ebase[yyval] = b;
+       if(dbg)printf(".\te:eb: S%d <- S%d S%d; b=%d, h=%d\n", 
+               yyval, p1, p2, b, h);
+       if (rfont[p1] == ITAL && lfont[p2] == ROM)
+               sh = "\\|";
+       else
+               sh = "";
+       if (lu) {
+               printf(".nr %d \\w'\\s%d\\*(%d%s'\n", p1, ps, p1, sh);
+               printf(".ds %d \\h'|\\n(97u-\\n(%du'\\*(%d\n", p1, p1, p1);
+       }
+       printf(".as %d \"%s\\*(%d\n", yyval, sh, p2);
+       rfont[p1] = rfont[p2];
+       ofree(p2);
+}
diff --git a/usr/src/cmd/eqn/font.c b/usr/src/cmd/eqn/font.c
new file mode 100644 (file)
index 0000000..3ef0e85
--- /dev/null
@@ -0,0 +1,59 @@
+# include "e.h"
+
+setfont(ch1) char ch1; {
+       /* use number '1', '2', '3' for roman, italic, bold */
+       yyval = ft;
+       if (ch1 == 'r' || ch1 == 'R')
+               ft = ROM;
+       else if (ch1 == 'i' || ch1 == 'I')
+               ft = ITAL;
+       else if (ch1 == 'b' || ch1 == 'B')
+               ft = BLD;
+       else
+               ft = ch1;
+       printf(".ft %c\n", ft);
+       if(dbg)printf(".\tsetfont %c %c\n", ch1, ft);
+}
+
+font(p1, p2) int p1, p2; {
+               /* old font in p1, new in ft */
+       yyval = p2;
+       lfont[yyval] = rfont[yyval] = ft==ITAL ? ITAL : ROM;
+       if(dbg)printf(".\tb:fb: S%d <- \\f%c S%d \\f%c b=%d,h=%d,lf=%c,rf=%c\n", 
+               yyval, ft, p2, p1, ebase[yyval], eht[yyval], lfont[yyval], rfont[yyval]);
+       printf(".ds %d \\f%c\\*(%d\\f%c\n", 
+               yyval, ft, p2, p1);
+       ft = p1;
+       printf(".ft %c\n", ft);
+}
+
+fatbox(p) int p; {
+       int sh;
+
+       yyval = p;
+       sh = ps / 4;
+       nrwid(p, ps, p);
+       printf(".ds %d \\*(%d\\h'-\\n(%du+%du'\\*(%d\n", p, p, p, sh, p);
+       if(dbg)printf(".\tfat %d, sh=%d\n", p, sh);
+}
+
+globfont() {
+       char temp[20];
+
+       getstr(temp, 20);
+       yyval = eqnreg = 0;
+       gfont = temp[0];
+       switch (gfont) {
+       case 'r': case 'R':
+               gfont = '1';
+               break;
+       case 'i': case 'I':
+               gfont = '2';
+               break;
+       case 'b': case 'B':
+               gfont = '3';
+               break;
+       }
+       printf(".ft %c\n", gfont);
+       ft = gfont;
+}
diff --git a/usr/src/cmd/eqn/fromto.c b/usr/src/cmd/eqn/fromto.c
new file mode 100644 (file)
index 0000000..d973b15
--- /dev/null
@@ -0,0 +1,45 @@
+# include "e.h"
+
+fromto(p1, p2, p3) int p1, p2, p3; {
+       int b, h1, b1, pss;
+       yyval = oalloc();
+       lfont[yyval] = rfont[yyval] = 0;
+       h1 = eht[yyval] = eht[p1];
+       b1 = ebase[p1];
+       b = 0;
+       pss = EFFPS(ps);
+       ps += 3;
+       nrwid(p1, ps, p1);
+       printf(".nr %d \\n(%d\n", yyval, p1);
+       if( p2>0 ) {
+               nrwid(p2, pss, p2);
+               printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, yyval, yyval, p2);
+               eht[yyval] += eht[p2];
+               b = eht[p2];
+       }
+       if( p3>0 ) {
+               nrwid(p3, pss, p3);
+               printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p3, yyval, yyval, p3);
+               eht[yyval] += eht[p3];
+       }
+       printf(".ds %d ", yyval);       /* bottom of middle box */
+       if( p2>0 ) {
+               printf("\\v'%du'\\h'\\n(%du-\\n(%du/2u'\\s%d\\*(%d\\s%d", 
+                       eht[p2]-ebase[p2]+b1, yyval, p2, pss, p2, EFFPS(ps));
+               printf("\\h'-\\n(%du-\\n(%du/2u'\\v'%du'\\\n", 
+                       yyval, p2, -(eht[p2]-ebase[p2]+b1));
+       }
+       printf("\\h'\\n(%du-\\n(%du/2u'\\*(%d\\h'\\n(%du-\\n(%du/2u'\\\n", 
+               yyval, p1, p1, yyval, p1);
+       if( p3>0 ) {
+               printf("\\v'%du'\\h'-\\n(%du-\\n(%du/2u'\\s%d\\*(%d\\s%d\\h'\\n(%du-\\n(%du/2u'\\v'%du'\\\n", 
+                       -(h1-b1+ebase[p3]), yyval, p3, pss, p3, EFFPS(ps), yyval, p3, (h1-b1+ebase[p3]));
+       }
+       printf("\n");
+       ebase[yyval] = b + b1;
+       if(dbg)printf(".\tfrom to: S%d <- %d f %d t %d; h=%d b=%d\n", 
+               yyval, p1, p2, p3, eht[yyval], ebase[yyval]);
+       ofree(p1);
+       if( p2>0 ) ofree(p2);
+       if( p3>0 ) ofree(p3);
+}
diff --git a/usr/src/cmd/eqn/funny.c b/usr/src/cmd/eqn/funny.c
new file mode 100644 (file)
index 0000000..a041d14
--- /dev/null
@@ -0,0 +1,26 @@
+# include "e.h"
+# include "e.def"
+
+funny(n) int n; {
+       char *f;
+
+       yyval = oalloc();
+       switch(n) {
+       case SUM:
+               f = "\\(*S"; break;
+       case UNION:
+               f = "\\(cu"; break;
+       case INTER:     /* intersection */
+               f = "\\(ca"; break;
+       case PROD:
+               f = "\\(*P"; break;
+       default:
+               error(FATAL, "funny type %d in funny", n);
+       }
+       printf(".ds %d \\s%d\\v'.3m'\\s+5%s\\s-5\\v'-.3m'\\s%d\n", yyval, ps, f, ps);
+       eht[yyval] = VERT( (ps+5)*6 -(ps*6*2)/10 );
+       ebase[yyval] = VERT( (ps*6*3)/10 );
+       if(dbg)printf(".\tfunny: S%d <- %s; h=%d b=%d\n", 
+               yyval, f, eht[yyval], ebase[yyval]);
+       lfont[yyval] = rfont[yyval] = ROM;
+}
diff --git a/usr/src/cmd/eqn/glob.c b/usr/src/cmd/eqn/glob.c
new file mode 100644 (file)
index 0000000..834a33f
--- /dev/null
@@ -0,0 +1,27 @@
+#include "e.h"
+
+int    dbg;    /* debugging print if non-zero */
+int    lp[80]; /* stack for things like piles and matrices */
+int    ct;     /* pointer to lp */
+int    used[100];      /* available registers */
+int    ps;     /* default init point size */
+int    deltaps = 3;    /* default change in ps */
+int    gsize   = 10;   /* default initial point size */
+int    gfont   = ITAL; /* italic */
+int    ft;     /* default font */
+FILE   *curfile;       /* current input file */
+int    ifile;
+int    linect; /* line number in file */
+int    eqline; /* line where eqn started */
+int    svargc;
+char   **svargv;
+int    eht[100];
+int    ebase[100];
+int    lfont[100];
+int    rfont[100];
+int    eqnreg; /* register where final string appears */
+int    eqnht;  /* inal height of equation */
+int    lefteq  = '\0'; /* left in-line delimiter */
+int    righteq = '\0'; /* right in-line delimiter */
+int    lastchar;       /* last character read by lex */
+int    markline        = 0;    /* 1 if this EQ/EN contains mark or lineup */
diff --git a/usr/src/cmd/eqn/integral.c b/usr/src/cmd/eqn/integral.c
new file mode 100644 (file)
index 0000000..6e4bcb7
--- /dev/null
@@ -0,0 +1,30 @@
+# include "e.h"
+# include "e.def"
+
+integral(p, p1, p2) {
+       if (p1 != 0)
+               printf(".ds %d \\h'-0.4m'\\v'0.4m'\\*(%d\\v'-0.4m'\n", p1, p1);
+       if (p2 != 0)
+               printf(".ds %d \\v'-0.3m'\\*(%d\\v'0.3m'\n", p2, p2);
+       if (p1 != 0 && p2 != 0)
+               shift2(p, p1, p2);
+       else if (p1 != 0)
+               bshiftb(p, SUB, p1);
+       else if (p2 != 0)
+               bshiftb(p, SUP, p2);
+       if(dbg)printf(".\tintegral: S%d; h=%d b=%d\n", 
+               p, eht[p], ebase[p]);
+       lfont[p] = ROM;
+}
+
+setintegral() {
+       char *f;
+
+       yyval = oalloc();
+       f = "\\(is";
+       printf(".ds %d \\s%d\\v'.1m'\\s+4%s\\s-4\\v'-.1m'\\s%d\n", 
+               yyval, ps, f, ps);
+       eht[yyval] = VERT( (((ps+4)*12)/10)*6 );
+       ebase[yyval] = VERT( (ps*6*3)/10 );
+       lfont[yyval] = rfont[yyval] = ROM;
+}
diff --git a/usr/src/cmd/eqn/io.c b/usr/src/cmd/eqn/io.c
new file mode 100644 (file)
index 0000000..776bac7
--- /dev/null
@@ -0,0 +1,195 @@
+# include "e.h"
+#define        MAXLINE 1200    /* maximum input line */
+
+char   in[MAXLINE];    /* input buffer */
+int    eqnexit();
+int noeqn;
+
+main(argc,argv) int argc; char *argv[];{
+
+       eqnexit(eqn(argc, argv));
+}
+
+eqnexit(n) {
+#ifdef gcos
+       if (n)
+               fprintf(stderr, "run terminated due to eqn error\n");
+       exit(0);
+#endif
+       exit(n);
+}
+
+eqn(argc,argv) int argc; char *argv[];{
+       int i, type;
+
+       setfile(argc,argv);
+       init_tbl();     /* install keywords in tables */
+       while ((type=getline(in)) != EOF) {
+               eqline = linect;
+               if (in[0]=='.' && in[1]=='E' && in[2]=='Q') {
+                       for (i=11; i<100; used[i++]=0);
+                       printf("%s",in);
+                       printf(".nr 99 \\n(.s\n.nr 98 \\n(.f\n");
+                       markline = 0;
+                       init();
+                       yyparse();
+                       if (eqnreg>0) {
+                               printf(".nr %d \\w'\\*(%d'\n", eqnreg, eqnreg);
+                               /* printf(".if \\n(%d>\\n(.l .tm too-long eqn, file %s, between lines %d-%d\n", */
+                               /*      eqnreg, svargv[ifile], eqline, linect); */
+                               printf(".nr MK %d\n", markline);        /* for -ms macros */
+                               printf(".if %d>\\n(.v .ne %du\n", eqnht, eqnht);
+                               printf(".rn %d 10\n", eqnreg);
+                               if(!noeqn)printf("\\*(10\n");
+                       }
+                       printf(".ps \\n(99\n.ft \\n(98\n");
+                       printf(".EN");
+                       if (lastchar == EOF) {
+                               putchar('\n');
+                               break;
+                       }
+                       if (putchar(lastchar) != '\n')
+                               while (putchar(gtc()) != '\n');
+               }
+               else if (type == lefteq)
+                       inline();
+               else
+                       printf("%s",in);
+       }
+       return(0);
+}
+
+getline(s) register char *s; {
+       register c;
+       while((*s++=c=gtc())!='\n' && c!=EOF && c!=lefteq)
+               if (s >= in+MAXLINE) {
+                       error( !FATAL, "input line too long: %.20s\n", in);
+                       in[MAXLINE] = '\0';
+                       break;
+               }
+       if (c==lefteq)
+               s--;
+       *s++ = '\0';
+       return(c);
+}
+
+inline() {
+       int ds;
+
+       printf(".nr 99 \\n(.s\n.nr 98 \\n(.f\n");
+       ds = oalloc();
+       printf(".rm %d \n", ds);
+       do{
+               if (*in)
+                       printf(".as %d \"%s\n", ds, in);
+               init();
+               yyparse();
+               if (eqnreg > 0) {
+                       printf(".as %d \\*(%d\n", ds, eqnreg);
+                       ofree(eqnreg);
+               }
+               printf(".ps \\n(99\n.ft \\n(98\n");
+       } while (getline(in) == lefteq);
+       if (*in)
+               printf(".as %d \"%s", ds, in);
+       printf(".ps \\n(99\n.ft \\n(98\n");
+       printf("\\*(%d\n", ds);
+       ofree(ds);
+}
+
+putout(p1) int p1; {
+       extern int gsize, gfont;
+       int before, after;
+       if(dbg)printf(".\tanswer <- S%d, h=%d,b=%d\n",p1, eht[p1], ebase[p1]);
+       eqnht = eht[p1];
+       printf(".ds %d \\x'0'", p1);
+       /* suppposed to leave room for a subscript or superscript */
+       before = eht[p1] - ebase[p1] - VERT((ps*6*12)/10);
+       if (before > 0)
+               printf("\\x'0-%du'", before);
+       printf("\\f%c\\s%d\\*(%d%s\\s\\n(99\\f\\n(98",
+               gfont, gsize, p1, rfont[p1] == ITAL ? "\\|" : "");
+       after = ebase[p1] - VERT((ps*6*2)/10);
+       if (after > 0)
+               printf("\\x'%du'", after);
+       putchar('\n');
+       eqnreg = p1;
+}
+
+max(i,j) int i,j; {
+       return (i>j ? i : j);
+}
+
+oalloc() {
+       int i;
+       for (i=11; i<100; i++)
+               if (used[i]++ == 0) return(i);
+       error( FATAL, "no eqn strings left", i);
+       return(0);
+}
+
+ofree(n) int n; {
+       used[n] = 0;
+}
+
+setps(p) int p; {
+       printf(".ps %d\n", EFFPS(p));
+}
+
+nrwid(n1, p, n2) int n1, p, n2; {
+       printf(".nr %d \\w'\\s%d\\*(%d'\n", n1, EFFPS(p), n2);
+}
+
+setfile(argc, argv) int argc; char *argv[]; {
+       static char *nullstr = "-";
+
+       svargc = --argc;
+       svargv = argv;
+       while (svargc > 0 && svargv[1][0] == '-') {
+               switch (svargv[1][1]) {
+
+               case 'd': lefteq=svargv[1][2]; righteq=svargv[1][3]; break;
+               case 's': gsize = atoi(&svargv[1][2]); break;
+               case 'p': deltaps = atoi(&svargv[1][2]); break;
+               case 'f': gfont = svargv[1][2]; break;
+               case 'e': noeqn++; break;
+               default: dbg = 1;
+               }
+               svargc--;
+               svargv++;
+       }
+       ifile = 1;
+       linect = 1;
+       if (svargc <= 0) {
+               curfile = stdin;
+               svargv[1] = nullstr;
+       }
+       else if ((curfile = fopen(svargv[1], "r")) == NULL)
+               error( FATAL,"can't open file %s", svargv[1]);
+}
+
+yyerror() {;}
+
+init() {
+       ct = 0;
+       ps = gsize;
+       ft = gfont;
+       setps(ps);
+       printf(".ft %c\n", ft);
+}
+
+error(fatal, s1, s2) int fatal; char *s1, *s2; {
+       if (fatal>0)
+               printf("eqn fatal error: ");
+       printf(s1,s2);
+       printf("\nfile %s, between lines %d and %d\n",
+                svargv[ifile], eqline, linect);
+       fprintf(stderr, "eqn: ");
+       if (fatal>0)
+               fprintf(stderr, "fatal error: ");
+       fprintf(stderr, s1, s2);
+       fprintf(stderr, "\nfile %s, between lines %d and %d\n",
+                svargv[ifile], eqline, linect);
+       if (fatal > 0)
+               eqnexit(1);
+}
diff --git a/usr/src/cmd/eqn/lex.c b/usr/src/cmd/eqn/lex.c
new file mode 100644 (file)
index 0000000..19860a2
--- /dev/null
@@ -0,0 +1,211 @@
+#include "e.h"
+#include "e.def"
+
+#define        SSIZE   400
+char   token[SSIZE];
+int    sp;
+#define        putbak(c)       *ip++ = c;
+#define        PUSHBACK        300     /* maximum pushback characters */
+char   ibuf[PUSHBACK+SSIZE];   /* pushback buffer for definitions, etc. */
+char   *ip     = ibuf;
+
+gtc() {
+  loop:
+       if (ip > ibuf)
+               return(*--ip);  /* already present */
+       lastchar = getc(curfile);
+       if (lastchar=='\n')
+               linect++;
+       if (lastchar != EOF)
+               return(lastchar);
+       if (++ifile > svargc) {
+               return(EOF);
+       }
+       fclose(curfile);
+       linect = 1;
+       if ((curfile=fopen(svargv[ifile], "r")) != NULL)
+               goto loop;
+       error(FATAL, "can't open file %s", svargv[ifile]);
+       return(EOF);
+}
+
+pbstr(str)
+register char *str;
+{
+       register char *p;
+
+       p = str;
+       while (*p++);
+       --p;
+       if (ip >= &ibuf[PUSHBACK])
+               error( FATAL, "pushback overflow");
+       while (p > str)
+               putbak(*--p);
+}
+
+yylex() {
+       register int c;
+       tbl *tp, *lookup();
+       extern tbl **keytbl, **deftbl;
+
+  beg:
+       while ((c=gtc())==' ' || c=='\n')
+               ;
+       yylval=c;
+       switch(c) {
+
+       case EOF:
+               return(EOF);
+       case '~':
+               return(SPACE);
+       case '^':
+               return(THIN);
+       case '\t':
+               return(TAB);
+       case '{':
+               return('{');
+       case '}':
+               return('}');
+       case '"':
+               for (sp=0; (c=gtc())!='"' && c != '\n'; ) {
+                       if (c == '\\')
+                               if ((c = gtc()) != '"')
+                                       token[sp++] = '\\';
+                       token[sp++] = c;
+                       if (sp>=SSIZE)
+                               error(FATAL, "quoted string %.20s... too long", token);
+               }
+               token[sp]='\0';
+               yylval = (int) &token[0];
+               if (c == '\n')
+                       error(!FATAL, "missing \" in %.20s", token);
+               return(QTEXT);
+       }
+       if (c==righteq)
+               return(EOF);
+
+       putbak(c);
+       getstr(token, SSIZE);
+       if (dbg)printf(".\tlex token = |%s|\n", token);
+       if ((tp = lookup(&deftbl, token, NULL)) != NULL) {
+               putbak(' ');
+               pbstr(tp->defn);
+               putbak(' ');
+               if (dbg)
+                       printf(".\tfound %s|=%s|\n", token, tp->defn);
+       }
+       else if ((tp = lookup(&keytbl, token, NULL)) == NULL) {
+               if(dbg)printf(".\t%s is not a keyword\n", token);
+               return(CONTIG);
+       }
+       else if (tp->defn == (char *) DEFINE || tp->defn == (char *) NDEFINE || tp->defn == (char *) TDEFINE)
+               define(tp->defn);
+       else if (tp->defn == (char *) DELIM)
+               delim();
+       else if (tp->defn == (char *) GSIZE)
+               globsize();
+       else if (tp->defn == (char *) GFONT)
+               globfont();
+       else if (tp->defn == (char *) INCLUDE)
+               include();
+       else {
+               return((int) tp->defn);
+       }
+       goto beg;
+}
+
+getstr(s, n) char *s; register int n; {
+       register int c;
+       register char *p;
+
+       p = s;
+       while ((c = gtc()) == ' ' || c == '\n')
+               ;
+       if (c == EOF) {
+               *s = 0;
+               return;
+       }
+       while (c != ' ' && c != '\t' && c != '\n' && c != '{' && c != '}'
+         && c != '"' && c != '~' && c != '^' && c != righteq) {
+               if (c == '\\')
+                       if ((c = gtc()) != '"')
+                               *p++ = '\\';
+               *p++ = c;
+               if (--n <= 0)
+                       error(FATAL, "token %.20s... too long", s);
+               c = gtc();
+       }
+       if (c=='{' || c=='}' || c=='"' || c=='~' || c=='^' || c=='\t' || c==righteq)
+               putbak(c);
+       *p = '\0';
+       yylval = (int) s;
+}
+
+cstr(s, quote, maxs) char *s; int quote; {
+       int del, c, i;
+
+       while((del=gtc()) == ' ' || del == '\t' || del == '\n');
+       if (quote)
+               for (i=0; (c=gtc()) != del && c != EOF;) {
+                       s[i++] = c;
+                       if (i >= maxs)
+                               return(1);      /* disaster */
+               }
+       else {
+               s[0] = del;
+               for (i=1; (c=gtc())!=' ' && c!= '\t' && c!='\n' && c!=EOF;) {
+                       s[i++]=c;
+                       if (i >= maxs)
+                               return(1);      /* disaster */
+               }
+       }
+       s[i] = '\0';
+       if (c == EOF)
+               error(FATAL, "Unexpected end of input at %.20s", s);
+       return(0);
+}
+
+define(type) int type; {
+       char *strsave(), *p1, *p2;
+       tbl *lookup();
+       extern tbl **deftbl;
+
+       getstr(token, SSIZE);   /* get name */
+       if (type != DEFINE) {
+               cstr(token, 1, SSIZE);  /* skip the definition too */
+               return;
+       }
+       p1 = strsave(token);
+       if (cstr(token, 1, SSIZE))
+               error(FATAL, "Unterminated definition at %.20s", token);
+       p2 = strsave(token);
+       lookup(&deftbl, p1, p2);
+       if (dbg)printf(".\tname %s defined as %s\n", p1, p2);
+}
+
+char *strsave(s)
+char *s;
+{
+       char *malloc();
+       register char *q;
+
+       q = malloc(strlen(s)+1);
+       if (q == NULL)
+               error(FATAL, "out of space in strsave on %s", s);
+       strcpy(q, s);
+       return(q);
+}
+
+include() {
+       error(!FATAL, "Include not yet implemented");
+}
+
+delim() {
+       yyval = eqnreg = 0;
+       if (cstr(token, 0, SSIZE))
+               error(FATAL, "Bizarre delimiters at %.20s", token);
+       lefteq = token[0];
+       righteq = token[1];
+       if (lefteq == 'o' && righteq == 'f')
+               lefteq = righteq = '\0';
+}
diff --git a/usr/src/cmd/eqn/lookup.c b/usr/src/cmd/eqn/lookup.c
new file mode 100644 (file)
index 0000000..aa6ea92
--- /dev/null
@@ -0,0 +1,217 @@
+# include "e.h"
+#include "e.def"
+
+#define        TBLSIZE 100
+
+tbl    *keytbl[TBLSIZE];       /* key words */
+tbl    *restbl[TBLSIZE];       /* reserved words */
+tbl    *deftbl[TBLSIZE];       /* user-defined names */
+
+struct {
+       char    *key;
+       int     keyval;
+} keyword[]    ={
+       "sub",  SUB, 
+       "sup",  SUP, 
+       ".EN",  EOF, 
+       "from",         FROM, 
+       "to",   TO, 
+       "sum",  SUM, 
+       "hat",  HAT, 
+       "vec", VEC, 
+       "dyad", DYAD, 
+       "dot",  DOT, 
+       "dotdot",       DOTDOT, 
+       "bar",  BAR, 
+       "tilde",        TILDE, 
+       "under",        UNDER, 
+       "prod",         PROD, 
+       "int",  INT, 
+       "integral",     INT, 
+       "union",        UNION, 
+       "inter",        INTER, 
+       "pile",         PILE, 
+       "lpile",        LPILE, 
+       "cpile",        CPILE, 
+       "rpile",        RPILE, 
+       "over",         OVER, 
+       "sqrt",         SQRT, 
+       "above",        ABOVE, 
+       "size",         SIZE, 
+       "font",         FONT, 
+       "fat", FAT, 
+       "roman",        ROMAN, 
+       "italic",       ITALIC, 
+       "bold",         BOLD, 
+       "left",         LEFT, 
+       "right",        RIGHT, 
+       "delim",        DELIM, 
+       "define",       DEFINE, 
+
+#ifdef NEQN    /* make ndefine synonym for define, tdefine a no-op */
+
+       "tdefine",      TDEFINE,
+       "ndefine",      DEFINE,
+
+#else          /* tdefine = define, ndefine = no-op */
+
+       "tdefine",      DEFINE, 
+       "ndefine",      NDEFINE, 
+
+#endif
+
+       "gsize",        GSIZE, 
+       ".gsize",       GSIZE, 
+       "gfont",        GFONT, 
+       "include",      INCLUDE, 
+       "up",   UP, 
+       "down",         DOWN, 
+       "fwd",  FWD, 
+       "back",         BACK, 
+       "mark",         MARK, 
+       "lineup",       LINEUP, 
+       "matrix",       MATRIX, 
+       "col",  COL, 
+       "lcol",         LCOL, 
+       "ccol",         CCOL, 
+       "rcol",         RCOL, 
+       0,      0
+};
+
+struct {
+       char    *res;
+       char    *resval;
+} resword[]    ={
+       ">=",   "\\(>=",
+       "<=",   "\\(<=",
+       "==",   "\\(==",
+       "!=",   "\\(!=",
+       "+-",   "\\(+-",
+       "->",   "\\(->",
+       "<-",   "\\(<-",
+       "inf",  "\\(if",
+       "infinity",     "\\(if",
+       "partial",      "\\(pd",
+       "half", "\\f1\\(12\\fP",
+       "prime",        "\\f1\\(fm\\fP",
+       "dollar",       "\\f1$\\fP",
+       "nothing",      "",
+       "times",        "\\(mu",
+       "del",  "\\(gr",
+       "grad", "\\(gr",
+#ifdef NEQN
+       "<<",   "<<",
+       ">>",   ">>",
+       "approx",       "~\b\\d~\\u",
+       "cdot", "\\v'-.5'.\\v'.5'",
+       "...",  "...",
+       ",...,",        ",...,",
+#else
+       "<<",   "<\\h'-.3m'<",
+       ">>",   ">\\h'-.3m'>",
+       "approx",       "\\v'-.2m'\\z\\(ap\\v'.25m'\\(ap\\v'-.05m'",
+       "cdot", "\\v'-.3m'.\\v'.3m'",
+       "...",  "\\v'-.3m'\\ .\\ .\\ .\\ \\v'.3m'",
+       ",...,",        ",\\ .\\ .\\ .\\ ,\\|",
+#endif
+
+       "alpha",        "\\(*a",
+       "beta", "\\(*b",
+       "gamma",        "\\(*g",
+       "GAMMA",        "\\(*G",
+       "delta",        "\\(*d",
+       "DELTA",        "\\(*D",
+       "epsilon",      "\\(*e",
+       "EPSILON",      "\\f1E\\fP",
+       "omega",        "\\(*w",
+       "OMEGA",        "\\(*W",
+       "lambda",       "\\(*l",
+       "LAMBDA",       "\\(*L",
+       "mu",   "\\(*m",
+       "nu",   "\\(*n",
+       "theta",        "\\(*h",
+       "THETA",        "\\(*H",
+       "phi",  "\\(*f",
+       "PHI",  "\\(*F",
+       "pi",   "\\(*p",
+       "PI",   "\\(*P",
+       "sigma",        "\\(*s",
+       "SIGMA",        "\\(*S",
+       "xi",   "\\(*c",
+       "XI",   "\\(*C",
+       "zeta", "\\(*z",
+       "iota", "\\(*i",
+       "eta",  "\\(*y",
+       "kappa",        "\\(*k",
+       "rho",  "\\(*r",
+       "tau",  "\\(*t",
+       "omicron",      "\\(*o",
+       "upsilon",      "\\(*u",
+       "UPSILON",      "\\(*U",
+       "psi",  "\\(*q",
+       "PSI",  "\\(*Q",
+       "chi",  "\\(*x",
+       "and",  "\\f1and\\fP",
+       "for",  "\\f1for\\fP",
+       "if",   "\\f1if\\fP",
+       "Re",   "\\f1Re\\fP",
+       "Im",   "\\f1Im\\fP",
+       "sin",  "\\f1sin\\fP",
+       "cos",  "\\f1cos\\fP",
+       "tan",  "\\f1tan\\fP",
+       "arc",  "\\f1arc\\fP",
+       "sinh", "\\f1sinh\\fP",
+       "coth", "\\f1coth\\fP",
+       "tanh", "\\f1tanh\\fP",
+       "cosh", "\\f1cosh\\fP",
+       "lim",  "\\f1lim\\fP",
+       "log",  "\\f1log\\fP",
+       "max",  "\\f1max\\fP",
+       "min",  "\\f1min\\fP",
+       "ln",   "\\f1ln\\fP",
+       "exp",  "\\f1exp\\fP",
+       "det",  "\\f1det\\fP",
+       0,      0
+};
+
+tbl *lookup(tblp, name, defn)  /* find name in tbl. if defn non-null, install */
+tbl **tblp;
+char *name, *defn;
+{
+       register tbl *p;
+       register int h;
+       register char *s = name;
+       char *malloc();
+
+       for (h = 0; *s != '\0'; )
+               h += *s++;
+       h %= TBLSIZE;
+
+       for (p = tblp[h]; p != NULL; p = p->next)
+               if (strcmp(name, p->name) == 0) {       /* found it */
+                       if (defn != NULL)
+                               p->defn = defn;
+                       return(p);
+               }
+       /* didn't find it */
+       if (defn == NULL)
+               return(NULL);
+       p = (tbl *) malloc(sizeof (tbl));
+       if (p == NULL)
+               error(FATAL, "out of space in lookup");
+       p->name = name;
+       p->defn = defn;
+       p->next = tblp[h];
+       tblp[h] = p;
+       return(p);
+}
+
+init_tbl()     /* initialize all tables */
+{
+       int i;
+
+       for (i = 0; keyword[i].key != NULL; i++)
+               lookup(keytbl, keyword[i].key, keyword[i].keyval);
+       for (i = 0; resword[i].res != NULL; i++)
+               lookup(restbl, resword[i].res, resword[i].resval);
+}
diff --git a/usr/src/cmd/eqn/mark.c b/usr/src/cmd/eqn/mark.c
new file mode 100644 (file)
index 0000000..6e03156
--- /dev/null
@@ -0,0 +1,17 @@
+#include "e.h"
+
+mark(p1) int p1; {
+       markline = 1;
+       printf(".ds %d \\k(97\\*(%d\n", p1, p1);
+       yyval = p1;
+       if(dbg)printf(".\tmark %d\n", p1);
+}
+
+lineup(p1) {
+       markline = 1;
+       if (p1 == 0) {
+               yyval = oalloc();
+               printf(".ds %d \\h'|\\n(97u'\n", yyval);
+       }
+       if(dbg)printf(".\tlineup %d\n", p1);
+}
diff --git a/usr/src/cmd/eqn/matrix.c b/usr/src/cmd/eqn/matrix.c
new file mode 100644 (file)
index 0000000..209e37b
--- /dev/null
@@ -0,0 +1,62 @@
+#include "e.h"
+
+column(type, p1) int type, p1; {
+       int i;
+
+       lp[p1] = ct - p1 - 1;
+       if( dbg ){
+               printf(".\t%d column of", type);
+               for( i=p1+1; i<ct; i++ )
+                       printf(" S%d", lp[i]);
+               printf(", rows=%d\n",lp[p1]);
+       }
+       lp[ct++] = type;
+}
+
+matrix(p1) int p1; {
+       int nrow, ncol, i, j, k, hb, b, val[100];
+       char *space;
+
+       space = "\\ \\ ";
+       nrow = lp[p1];  /* disaster if rows inconsistent */
+       ncol = 0;
+       for( i=p1; i<ct; i += lp[i]+2 ){
+               ncol++;
+               if(dbg)printf(".\tcolct=%d\n",lp[i]);
+       }
+       for( k=1; k<=nrow; k++ ) {
+               hb = b = 0;
+               j = p1 + k;
+               for( i=0; i<ncol; i++ ) {
+                       hb = max(hb, eht[lp[j]]-ebase[lp[j]]);
+                       b = max(b, ebase[lp[j]]);
+                       j += nrow + 2;
+               }
+               if(dbg)printf(".\trow %d: b=%d, hb=%d\n", k, b, hb);
+               j = p1 + k;
+               for( i=0; i<ncol; i++ ) {
+                       ebase[lp[j]] = b;
+                       eht[lp[j]] = b + hb;
+                       j += nrow + 2;
+               }
+       }
+       j = p1;
+       for( i=0; i<ncol; i++ ) {
+               lpile(lp[j+lp[j]+1], j+1, j+lp[j]+1);
+               val[i] = yyval;
+               j += nrow + 2;
+       }
+       yyval = oalloc();
+       eht[yyval] = eht[val[0]];
+       ebase[yyval] = ebase[val[0]];
+       lfont[yyval] = rfont[yyval] = 0;
+       if(dbg)printf(".\tmatrix S%d: r=%d, c=%d, h=%d, b=%d\n",
+               yyval,nrow,ncol,eht[yyval],ebase[yyval]);
+       printf(".ds %d \"", yyval);
+       for( i=0; i<ncol; i++ )  {
+               printf("\\*(%d%s", val[i], i==ncol-1 ? "" : space);
+               ofree(val[i]);
+       }
+       printf("\n");
+       ct = p1;
+}
diff --git a/usr/src/cmd/eqn/move.c b/usr/src/cmd/eqn/move.c
new file mode 100644 (file)
index 0000000..c4d30fa
--- /dev/null
@@ -0,0 +1,18 @@
+# include "e.h"
+# include "e.def"
+
+move(dir, amt, p) int dir, amt, p; {
+       int a;
+
+       yyval = p;
+       a = VERT( (EFFPS(ps) * 6 * amt) / 100);
+       printf(".ds %d ", yyval);
+       if( dir == FWD || dir == BACK ) /* fwd, back */
+               printf("\\h'%s%du'\\*(%d\n", (dir==BACK) ? "-" : "", a, p);
+       else if (dir == UP)
+               printf("\\v'-%du'\\*(%d\\v'%du'\n", a, p, a);
+       else if (dir == DOWN)
+               printf("\\v'%du'\\*(%d\\v'-%du'\n", a, p, a);
+       if(dbg)printf(".\tmove %d dir %d amt %d; h=%d b=%d\n", 
+               p, dir, a, eht[yyval], ebase[yyval]);
+}
diff --git a/usr/src/cmd/eqn/over.c b/usr/src/cmd/eqn/over.c
new file mode 100644 (file)
index 0000000..feadac3
--- /dev/null
@@ -0,0 +1,29 @@
+# include "e.h"
+
+boverb(p1, p2) int p1, p2; {
+       int h, b, treg, d;
+
+       treg = oalloc();
+       yyval = p1;
+       d = VERT((ps*6*3) / 10);        /* 0.3m */
+       h = eht[p1] + eht[p2] + d;
+       b = eht[p2] - d;
+       if(dbg)printf(".\tb:bob: S%d <- S%d over S%d; b=%d, h=%d\n", 
+               yyval, p1, p2, b, h);
+       nrwid(p1, ps, p1);
+       nrwid(p2, ps, p2);
+       printf(".nr %d \\n(%d\n", treg, p1);
+       printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, treg, treg, p2);
+       printf(".nr %d \\n(%d+\\s%d.5m\\s0\n", treg, treg, EFFPS(ps));
+       printf(".ds %d \\v'%du'\\h'\\n(%du-\\n(%du/2u'\\*(%d\\\n", 
+               yyval, eht[p2]-ebase[p2]-d, treg, p2, p2);
+       printf("\\h'-\\n(%du-\\n(%du/2u'\\v'%du'\\*(%d\\\n", 
+               p2, p1, -(eht[p2]-ebase[p2]+d+ebase[p1]), p1);
+       printf("\\h'-\\n(%du-\\n(%du/2u+.1m'\\v'%du'\\l'\\n(%du-.2m'\\h'.1m'\\v'%du'\n", 
+                treg, p1, ebase[p1]+d, treg, d);
+       ebase[yyval] = b;
+       eht[yyval] = h;
+       lfont[yyval] = rfont[yyval] = 0;
+       ofree(p2);
+       ofree(treg);
+}
diff --git a/usr/src/cmd/eqn/paren.c b/usr/src/cmd/eqn/paren.c
new file mode 100644 (file)
index 0000000..f789581
--- /dev/null
@@ -0,0 +1,105 @@
+# include "e.h"
+
+paren(leftc, p1, rightc) int p1, leftc, rightc; {
+       int n, m, h1, j, b1, v;
+       h1 = eht[p1]; b1 = ebase[p1];
+       yyval = p1;
+       lfont[yyval] = rfont[yyval] = 0;
+       n = (h1+(6*EFFPS(ps)-1))/(6*EFFPS(ps));
+       if( n<2 ) n = 1;
+       m = n-2;
+       if (leftc=='{' || rightc == '}') {
+               n = n%2 ? n : ++n;
+               if( n<3 ) n=3;
+               m = n-3;
+       }
+       eht[yyval] = VERT(6 * ps * n);
+       ebase[yyval] = b1 + (eht[yyval]-h1)/2;
+       v = b1 - h1/2 + VERT( (ps*6*4)/10 );
+       printf(".ds %d \\|\\v'%du'", yyval, v);
+       switch( leftc ) {
+               case 'n':       /* nothing */
+               case '\0':
+                       break;
+               case 'f':       /* floor */
+                       if (n <= 1)
+                               printf("\\(lf");
+                       else
+                               brack(m, "\\(bv", "\\(bv", "\\(lf");
+                       break;
+               case 'c':       /* ceiling */
+                       if (n <= 1)
+                               printf("\\(lc");
+                       else
+                               brack(m, "\\(lc", "\\(bv", "\\(bv");
+                       break;
+               case '{':
+                       printf("\\b'\\(lt");
+                       for(j = 0; j < m; j += 2) printf("\\(bv");
+                       printf("\\(lk");
+                       for(j = 0; j < m; j += 2) printf("\\(bv");
+                       printf("\\(lb'");
+                       break;
+               case '(':
+                       brack(m, "\\(lt", "\\(bv", "\\(lb");
+                       break;
+               case '[':
+                       brack(m, "\\(lc", "\\(bv", "\\(lf");
+                       break;
+               case '|':
+                       brack(m, "|", "|", "|");
+                       break;
+               default:
+                       brack(m, (char *) &leftc, (char *) &leftc, (char *) &leftc);
+                       break;
+               }
+       printf("\\v'%du'\\*(%d", -v, p1);
+       if( rightc ) {
+               printf("\\|\\v'%du'", v);
+               switch( rightc ) {
+                       case 'f':       /* floor */
+                               if (n <= 1)
+                                       printf("\\(rf");
+                               else
+                                       brack(m, "\\(bv", "\\(bv", "\\(rf");
+                               break;
+                       case 'c':       /* ceiling */
+                               if (n <= 1)
+                                       printf("\\(rc");
+                               else
+                                       brack(m, "\\(rc", "\\(bv", "\\(bv");
+                               break;
+                       case '}':
+                               printf("\\b'\\(rt");
+                               for(j = 0; j< m; j += 2)printf("\\(bv");
+                               printf("\\(rk");
+                               for(j = 0; j< m; j += 2) printf("\\(bv");
+                               printf("\\(rb'");
+                               break;
+                       case ']':
+                               brack(m, "\\(rc", "\\(bv", "\\(rf");
+                               break;
+                       case ')':
+                               brack(m, "\\(rt", "\\(bv", "\\(rb");
+                               break;
+                       case '|':
+                               brack(m, "|", "|", "|");
+                               break;
+                       default:
+                               brack(m, (char *) &rightc, (char *) &rightc, (char *) &rightc);
+                               break;
+               }
+               printf("\\v'%du'", -v);
+       }
+       printf("\n");
+       if(dbg)printf(".\tcurly: h=%d b=%d n=%d v=%d l=%c, r=%c\n", 
+               eht[yyval], ebase[yyval], n, v, leftc, rightc);
+}
+
+brack(m, t, c, b) int m; char *t, *c, *b; {
+       int j;
+       printf("\\b'%s", t);
+       for( j=0; j<m; j++)
+               printf("%s", c);
+       printf("%s'", b);
+}
diff --git a/usr/src/cmd/eqn/pile.c b/usr/src/cmd/eqn/pile.c
new file mode 100644 (file)
index 0000000..c2873d2
--- /dev/null
@@ -0,0 +1,62 @@
+# include "e.h"
+
+lpile(type, p1, p2) int type, p1, p2; {
+       int bi, hi, i, gap, h, b, nlist, nlist2, mid;
+       yyval = oalloc();
+       gap = VERT( (ps*6*4)/10 ); /* 4/10 m between blocks */
+       if( type=='-' ) gap = 0;
+       nlist = p2 - p1;
+       nlist2 = (nlist+1)/2;
+       mid = p1 + nlist2 -1;
+       h = 0;
+       for( i=p1; i<p2; i++ )
+               h += eht[lp[i]];
+       eht[yyval] = h + (nlist-1)*gap;
+       b = 0;
+       for( i=p2-1; i>mid; i-- )
+               b += eht[lp[i]] + gap;
+       ebase[yyval] = (nlist%2) ? b + ebase[lp[mid]]
+                       : b - VERT( (ps*6*5)/10 ) - gap;
+       if(dbg) {
+               printf(".\tS%d <- %c pile of:", yyval, type);
+               for( i=p1; i<p2; i++)
+                       printf(" S%d", lp[i]);
+               printf(";h=%d b=%d\n", eht[yyval], ebase[yyval]);
+       }
+       nrwid(lp[p1], ps, lp[p1]);
+       printf(".nr %d \\n(%d\n", yyval, lp[p1]);
+       for( i = p1+1; i<p2; i++ ) {
+               nrwid(lp[i], ps, lp[i]);
+               printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", 
+                       lp[i], yyval, yyval, lp[i]);
+       }
+       printf(".ds %d \\v'%du'\\h'%du*\\n(%du'\\\n", yyval, ebase[yyval], 
+               type=='R' ? 1 : 0, yyval);
+       for(i = p2-1; i >=p1; i--) {
+               hi = eht[lp[i]]; 
+               bi = ebase[lp[i]];
+       switch(type) {
+
+       case 'L':
+               printf("\\v'%du'\\*(%d\\h'-\\n(%du'\\v'0-%du'\\\n", 
+                       -bi, lp[i], lp[i], hi-bi+gap);
+               continue;
+       case 'R':
+               printf("\\v'%du'\\h'-\\n(%du'\\*(%d\\v'0-%du'\\\n", 
+                       -bi, lp[i], lp[i], hi-bi+gap);
+               continue;
+       case 'C':
+       case '-':
+               printf("\\v'%du'\\h'\\n(%du-\\n(%du/2u'\\*(%d", 
+                       -bi, yyval, lp[i], lp[i]);
+               printf("\\h'-\\n(%du-\\n(%du/2u'\\v'0-%du'\\\n", 
+                       yyval, lp[i], hi-bi+gap);
+               continue;
+               }
+       }
+       printf("\\v'%du'\\h'%du*\\n(%du'\n", eht[yyval]-ebase[yyval]+gap, 
+               type!='R' ? 1 : 0, yyval);
+       for( i=p1; i<p2; i++ )
+               ofree(lp[i]);
+       lfont[yyval] = rfont[yyval] = 0;
+}
diff --git a/usr/src/cmd/eqn/shift.c b/usr/src/cmd/eqn/shift.c
new file mode 100644 (file)
index 0000000..adc7664
--- /dev/null
@@ -0,0 +1,103 @@
+# include "e.h"
+#include "e.def"
+
+bshiftb(p1, dir, p2) int p1, dir, p2; {
+       int shval, diffps, effps, effps2, d1, h1, b1, h2, b2;
+       char *sh1, *sh2;
+
+       yyval = p1;
+       h1 = eht[p1];
+       b1 = ebase[p1];
+       h2 = eht[p2];
+       b2 = ebase[p2];
+       effps = EFFPS(ps);
+       effps2 = EFFPS(ps+deltaps);
+       diffps = deltaps;
+       sh1 = sh2 = "";
+       if( dir == SUB ) {
+               /* top 1/2m above bottom of main box */
+               d1 = VERT( (effps2*6)/2 );
+               shval = - d1 + h2 - b2;
+               if( d1+b1 > h2 ) /* move little sub down */
+                       shval = b1-b2;
+               ebase[yyval] = b1 + max(0, h2-b1-d1);
+               eht[yyval] = h1 + max(0, h2-b1-d1);
+               if (rfont[p1] == ITAL && lfont[p2] == ROM)
+                       sh1 = "\\|";
+               if (rfont[p2] == ITAL)
+                       sh2 = "\\|";
+       } else {        /* superscript */
+               /* 4/10 up main box */
+               d1 = VERT( (effps*6*2)/10 );
+               ebase[yyval] = b1;
+               shval = -VERT( (4 * (h1-b1)) / 10 ) - b2;
+               if( VERT(4*(h1-b1)/10) + h2 < h1-b1 )   /* raise little super */
+                       shval = -(h1-b1) + h2-b2 - d1;
+               eht[yyval] = h1 + max(0, h2-VERT((6*(h1-b1))/10));
+               if (rfont[p1] == ITAL)
+                       sh1 = "\\|";
+               if (rfont[p2] == ITAL)
+                       sh2 = "\\|";
+       }
+       if(dbg)printf(".\tb:b shift b: S%d <- S%d vert %d S%d vert %d; b=%d, h=%d\n", 
+               yyval, p1, shval, p2, -shval, ebase[yyval], eht[yyval]);
+       printf(".as %d \\v'%du'\\s-%d%s\\*(%d\\s+%d%s\\v'%du'\n", 
+               yyval, shval, diffps, sh1, p2, diffps, sh2, -shval);
+       ps += deltaps;
+       if (rfont[p2] == ITAL)
+               rfont[p1] = 0;
+       else
+               rfont[p1] = rfont[p2];
+       ofree(p2);
+}
+
+shift(p1) int p1; {
+       ps -= deltaps;
+       yyval = p1;
+       if(dbg)printf(".\tshift: %d;ps=%d\n", yyval, ps);
+}
+
+shift2(p1, p2, p3) int p1, p2, p3; {
+       int effps, effps2, h1, h2, h3, b1, b2, b3, subsh, d1, d2, supsh;
+       int treg;
+       treg = oalloc();
+       yyval = p1;
+       if(dbg)printf(".\tshift2 s%d <- %d %d %d\n", yyval, p1, p2, p3);
+       effps = EFFPS(ps+deltaps);
+       eht[p3] = h3 = VERT( (eht[p3] * effps) / EFFPS(ps) );
+       ps += deltaps;
+       effps2 = EFFPS(ps+deltaps);
+       h1 = eht[p1]; b1 = ebase[p1];
+       h2 = eht[p2]; b2 = ebase[p2];
+       b3 = ebase[p3];
+       d1 = VERT( (effps2*6)/2 );
+       subsh = -d1+h2-b2;
+       if( d1+b1 > h2 ) /* move little sub down */
+               subsh = b1-b2;
+       supsh = -VERT( (4*(h1-b1))/10 ) - b3;
+       d2 = VERT( (effps*6*2)/10 );
+       if( VERT(4*(h1-b1)/10)+h3 < h1-b1 )
+               supsh = -(h1-b1) + (h3-b3) - d2;
+       eht[yyval] = h1 + max(0, h3-VERT( (6*(h1-b1))/10 )) + max(0, h2-b1-d1);
+       ebase[yyval] = b1+max(0, h2-b1-d1);
+       if (rfont[p1] == ITAL && lfont[p2] == ROM)
+               printf(".ds %d \\|\\*(%d\n", p2, p2);
+       if (rfont[p2] == ITAL)
+               printf(".as %d \\|\n", p2);
+       nrwid(p2, effps, p2);
+       if (rfont[p1] == ITAL && lfont[p3] == ROM)
+               printf(".ds %d \\|\\|\\*(%d\n", p3, p3);
+       else
+               printf(".ds %d \\|\\*(%d\n", p3, p3);
+       nrwid(p3, effps, p3);
+       printf(".nr %d \\n(%d\n", treg, p3);
+       printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, treg, treg, p2);
+       printf(".as %d \\v'%du'\\s%d\\*(%d\\h'-\\n(%du'\\v'%du'\\\n", 
+               p1, subsh, effps, p2, p2, -subsh+supsh);
+       printf("\\s%d\\*(%d\\h'-\\n(%du+\\n(%du'\\s%d\\v'%du'\n", 
+               effps, p3, p3, treg, effps2, -supsh);
+       ps += deltaps;
+       if (rfont[p2] == ITAL)
+               rfont[yyval] = 0;       /* lie */
+       ofree(p2); ofree(p3); ofree(treg);
+}
diff --git a/usr/src/cmd/eqn/size.c b/usr/src/cmd/eqn/size.c
new file mode 100644 (file)
index 0000000..8f99fa6
--- /dev/null
@@ -0,0 +1,46 @@
+# include "e.h"
+
+setsize(p)     /* set size as found in p */
+char *p;
+{
+       if (*p == '+')
+               ps += atoi(p+1);
+       else if (*p == '-')
+               ps -= atoi(p+1);
+       else
+               ps = atoi(p);
+       if(dbg)printf(".\tsetsize %s; ps = %d\n", p, ps);
+}
+
+size(p1, p2) int p1, p2; {
+               /* old size in p1, new in ps */
+       int effps, effp1;
+
+       yyval = p2;
+       if(dbg)printf(".\tb:sb: S%d <- \\s%d S%d \\s%d; b=%d, h=%d\n", 
+               yyval, ps, p2, p1, ebase[yyval], eht[yyval]);
+       effps = EFFPS(ps);
+       effp1 = EFFPS(p1);
+       printf(".ds %d \\s%d\\*(%d\\s%d\n", 
+               yyval, effps, p2, effp1);
+       ps = p1;
+}
+
+globsize() {
+       char temp[20];
+
+       getstr(temp, 20);
+       if (temp[0] == '+')
+               gsize += atoi(temp+1);
+       else if (temp[0] == '-')
+               gsize -= atoi(temp+1);
+       else
+               gsize = atoi(temp);
+       yyval = eqnreg = 0;
+       setps(gsize);
+       ps = gsize;
+       if (gsize >= 12)        /* sub and sup size change */
+               deltaps = gsize / 4;
+       else
+               deltaps = gsize / 3;
+}
diff --git a/usr/src/cmd/eqn/sqrt.c b/usr/src/cmd/eqn/sqrt.c
new file mode 100644 (file)
index 0000000..2229328
--- /dev/null
@@ -0,0 +1,17 @@
+# include "e.h"
+
+sqrt(p2) int p2; {
+       int nps;
+       nps = EFFPS(((eht[p2]*9)/10+5)/6);
+       yyval = p2;
+       eht[yyval] = VERT( (nps*6*12)/10 );
+       if(dbg)printf(".\tsqrt: S%d <- S%d;b=%d, h=%d\n", 
+               yyval, p2, ebase[yyval], eht[yyval]);
+       if (rfont[yyval] == ITAL)
+               printf(".as %d \\|\n", yyval);
+       nrwid(p2, ps, p2);
+       printf(".ds %d \\v'%du'\\s%d\\v'-.2m'\\(sr\\l'\\n(%du\\(rn'\\v'.2m'\\s%d", 
+               yyval, ebase[p2], nps, p2, ps);
+       printf("\\v'%du'\\h'-\\n(%du'\\*(%d\n", -ebase[p2], p2, p2);
+       lfont[yyval] = ROM;
+}
diff --git a/usr/src/cmd/eqn/text.c b/usr/src/cmd/eqn/text.c
new file mode 100644 (file)
index 0000000..79289d0
--- /dev/null
@@ -0,0 +1,170 @@
+# include "e.h"
+# include "e.def"
+
+int    csp;
+int    psp;
+#define        CSSIZE  400
+char   cs[420];
+
+int    lf, rf; /* temporary spots for left and right fonts */
+
+text(t,p1) int t; char *p1; {
+       int c;
+       char *p;
+       tbl *tp, *lookup();
+       extern tbl *restbl;
+
+       yyval = oalloc();
+       ebase[yyval] = 0;
+       eht[yyval] = VERT(6 * ((ps>6)?ps:6));   /* ht in machine units */
+       lfont[yyval] = rfont[yyval] = ROM;
+       if (t == QTEXT)
+               p = p1;
+       else if ( t == SPACE )
+               p = "\\ ";
+       else if ( t == THIN )
+               p = "\\|";
+       else if ( t == TAB )
+               p = "\\t";
+       else if ((tp = lookup(&restbl, p1, NULL)) != NULL)
+               p = tp->defn;
+       else {
+               lf = rf = 0;
+               for (csp=psp=0; (c=p1[psp++])!='\0';) {
+                       rf = trans(c, p1);
+                       if (lf == 0)
+                               lf = rf;        /* save first */
+                       if (csp>CSSIZE)
+                               error(FATAL,"converted token %.25s... too long",p1);
+               }
+               cs[csp] = '\0';
+               p = cs;
+               lfont[yyval] = lf;
+               rfont[yyval] = rf;
+       }
+       if(dbg)printf(".\t%dtext: S%d <- %s; b=%d,h=%d,lf=%c,rf=%c\n",
+               t, yyval, p, ebase[yyval], eht[yyval], lfont[yyval], rfont[yyval]);
+       printf(".ds %d \"%s\n", yyval, p);
+}
+
+trans(c,p1) int c; char *p1; {
+       int f;
+       f = ROM;
+       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 ',':
+               if (rf == ITAL)
+                       shim();
+               roman(c); break;
+       case '.':
+               if (rf == ROM)
+                       roman(c);
+               else
+                       cs[csp++] = c;
+               f = rf;
+               break;
+       case '|':
+               if (rf == ITAL)
+                       shim();
+               shim(); roman(c); shim(); break;
+       case '=':
+               if (rf == ITAL)
+                       shim();
+               name4('e','q');
+               break;
+       case '+':
+               if (rf == ITAL)
+                       shim();
+               name4('p', 'l');
+               break;
+       case '>': case '<':
+               if (rf == ITAL)
+                       shim();
+               if (p1[psp]=='=') {     /* look ahead for == <= >= */
+                       name4(c,'=');
+                       psp++;
+               } else {
+                       cs[csp++] = c;  
+               }
+               break;
+       case '-':
+               if (rf == ITAL)
+                       shim();
+               if (p1[psp]=='>') {
+                       name4('-','>'); psp++;
+               } else {
+                       name4('m','i');
+               }
+               break;
+       case '/':
+               if (rf == ITAL)
+                       shim();
+               name4('s','l');
+               break;
+       case '~': case ' ':
+               shim(); shim(); break;
+       case '^':
+               shim(); break;
+       case '\\':      /* troff - pass 2 or 3 more chars */
+               if (rf == ITAL)
+                       shim();
+               cs[csp++] = c; cs[csp++] = c = p1[psp++]; cs[csp++] = p1[psp++];
+               if (c=='(') cs[csp++] = p1[psp++];
+               if (c=='*' && cs[csp-1] == '(') {
+                       cs[csp++] = p1[psp++];
+                       cs[csp++] = p1[psp++];
+               }
+               break;
+       case '\'':
+               cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = rf==ITAL ? ITAL : ROM;
+               name4('f','m');
+               cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = 'P';
+               f = rf==ITAL ? ITAL : ROM;
+               break;
+
+       case 'f':
+               if (ft == ITAL) {
+                       cs[csp++] = '\\'; cs[csp++] = '^';
+                       cs[csp++] = 'f';
+                       cs[csp++] = '\\'; cs[csp++] = '|';      /* trying | instead of ^ */
+                       f = ITAL;
+               }
+               else
+                       cs[csp++] = 'f';
+               break;
+       case 'j':
+               if (ft == ITAL) {
+                       cs[csp++] = '\\'; cs[csp++] = '^';
+                       cs[csp++] = 'j';
+                       f = ITAL;
+               }
+               else
+                       cs[csp++] = 'j';
+               break;
+       default:
+               cs[csp++] = c;
+               f = ft==ITAL ? ITAL : ROM;
+               break;
+       }
+       return(f);
+}
+
+shim() {
+       cs[csp++] = '\\'; cs[csp++] = '|';
+}
+
+roman(c) int c; {
+       cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = ROM;
+       cs[csp++] = c;
+       cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = 'P';
+}
+
+name4(c1,c2) int c1,c2; {
+       cs[csp++] = '\\';
+       cs[csp++] = '(';
+       cs[csp++] = c1;
+       cs[csp++] = c2;
+}
diff --git a/usr/src/cmd/graph/graph.c b/usr/src/cmd/graph/graph.c
new file mode 100644 (file)
index 0000000..7bd4125
--- /dev/null
@@ -0,0 +1,693 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+#define        INF     1.e+37
+#define        F       .25
+
+struct xy {
+       int     xlbf;   /*flag:explicit lower bound*/
+       int     xubf;   /*flag:explicit upper bound*/
+       int     xqf;    /*flag:explicit quantum*/
+       double (*xf)(); /*transform function, e.g. log*/
+       float   xa,xb;  /*scaling coefficients*/
+       float   xlb,xub;        /*lower and upper bound*/
+       float   xquant; /*quantum*/
+       float   xoff;           /*screen offset fraction*/
+       float   xsize;          /*screen fraction*/
+       int     xbot,xtop;      /*screen coords of border*/     
+       float   xmult;  /*scaling constant*/
+} xd,yd;
+struct val {
+       float xv;
+       float yv;
+       int lblptr;
+} *xx;
+
+char *labs;
+int labsiz;
+
+int tick = 50;
+int top = 4000;
+int bot = 200;
+float absbot;
+int    n;
+int    erasf = 1;
+int    gridf = 2;
+int    symbf = 0;
+int    absf = 0;
+int    transf;
+int    brkf;
+float  dx;
+char   *plotsymb;
+
+double atof();
+#define BSIZ 80
+char   labbuf[BSIZ];
+char   titlebuf[BSIZ];
+
+char *modes[] = {
+       "disconnected",
+       "solid",
+       "dotted",
+       "dotdashed",
+       "shortdashed",
+       "longdashed"
+};
+int mode = 1;
+char *realloc();
+char *malloc();
+
+double ident(x)
+double x;
+{
+       return(x);
+}
+
+main(argc,argv)
+char *argv[];
+{
+
+       space(0,0,4096,4096);
+       init(&xd);
+       init(&yd);
+       xd.xsize = yd.xsize = 1.;
+       xx = (struct val *)malloc((unsigned)sizeof(struct val));
+       labs = malloc(1);
+       labs[labsiz++] = 0;
+       setopt(argc,argv);
+       if(erasf)
+               erase();
+       readin();
+       transpose();
+       scale(&xd,(struct val *)&xx->xv);
+       scale(&yd,(struct val *)&xx->yv);
+       axes();
+       title();
+       plot();
+       move(1,1);
+       closevt();
+       return(0);
+}
+
+init(p)
+struct xy *p;
+{
+       p->xf = ident;
+       p->xmult = 1;
+}
+
+setopt(argc,argv)
+char *argv[];
+{
+       char *p1, *p2;
+       float temp;
+
+       xd.xlb = yd.xlb = INF;
+       xd.xub = yd.xub = -INF;
+       while(--argc > 0) {
+               argv++;
+again:         switch(argv[0][0]) {
+               case '-':
+                       argv[0]++;
+                       goto again;
+               case 'l': /* label for plot */
+                       p1 = titlebuf;
+                       if (argc>=2) {
+                               argv++;
+                               argc--;
+                               p2 = argv[0];
+                               while (*p1++ = *p2++);
+                       }
+                       break;
+
+               case 'd':       /*disconnected,obsolete option*/
+               case 'm': /*line mode*/
+                       mode = 0;
+                       if(!numb(&temp,&argc,&argv))
+                               break;
+                       if(temp>=sizeof(modes)/sizeof(*modes))
+                               mode = 1;
+                       else if(temp>=0)
+                               mode = temp;
+                       break;
+
+               case 'a': /*automatic abscissas*/
+                       absf = 1;
+                       dx = 1;
+                       if(!numb(&dx,&argc,&argv))
+                               break;
+                       if(numb(&absbot,&argc,&argv))
+                               absf = 2;
+                       break;
+
+               case 's': /*save screen, overlay plot*/
+                       erasf = 0;
+                       break;
+
+               case 'g': /*grid style 0 none, 1 ticks, 2 full*/
+                       gridf = 0;
+                       if(!numb(&temp,&argc,&argv))
+                               temp = argv[0][1]-'0';  /*for caompatibility*/
+                       if(temp>=0&&temp<=2)
+                               gridf = temp;
+                       break;
+
+               case 'c': /*character(s) for plotting*/
+                       if(argc >= 2) {
+                               symbf = 1;
+                               plotsymb = argv[1];
+                               argv++;
+                               argc--;
+                       }
+                       break;
+
+               case 't':       /*transpose*/
+                       transf = 1;
+                       break;
+               case 'b':       /*breaks*/
+                       brkf = 1;
+                       break;
+               case 'x':       /*x limits */
+                       limread(&xd,&argc,&argv);
+                       break;
+               case 'y':
+                       limread(&yd,&argc,&argv);
+                       break;
+               case 'h': /*set height of plot */
+                       if(!numb(&yd.xsize, &argc,&argv))
+                               badarg();
+                       break;
+               case 'w': /*set width of plot */
+                       if(!numb(&xd.xsize, &argc, &argv))
+                               badarg();
+                       break;
+               case 'r': /* set offset to right */
+                       if(!numb(&xd.xoff, &argc, &argv))
+                               badarg();
+                       break;
+               case 'u': /*set offset up the screen*/
+                       if(!numb(&yd.xoff,&argc,&argv))
+                               badarg();
+                       break;
+               default:
+                       badarg();
+               }
+       }
+}
+
+limread(p, argcp, argvp)
+register struct xy *p;
+int *argcp;
+char ***argvp;
+{
+       if(*argcp>1 && (*argvp)[1][0]=='l') {
+               (*argcp)--;
+               (*argvp)++;
+               p->xf = log10;
+       }
+       if(!numb(&p->xlb,argcp,argvp))
+               return;
+       p->xlbf = 1;
+       if(!numb(&p->xub,argcp,argvp))
+               return;
+       p->xubf = 1;
+       if(!numb(&p->xquant,argcp,argvp))
+               return;
+       p->xqf = 1;
+}
+
+numb(np, argcp, argvp)
+int *argcp;
+float *np;
+register char ***argvp;
+{
+       register char c;
+
+       if(*argcp <= 1)
+               return(0);
+       while((c=(*argvp)[1][0]) == '+')
+               (*argvp)[1]++;
+       if(!(isdigit(c) || c=='-'&&(*argvp)[1][1]<'A' || c=='.'))
+               return(0);
+       *np = atof((*argvp)[1]);
+       (*argcp)--;
+       (*argvp)++;
+       return(1);
+}
+
+readin()
+{
+       register t;
+       struct val *temp;
+
+       if(absf==1) {
+               if(xd.xlbf)
+                       absbot = xd.xlb;
+               else if(xd.xf==log10)
+                       absbot = 1;
+       }
+       for(;;) {
+               temp = (struct val *)realloc((char*)xx,
+                       (unsigned)(n+1)*sizeof(struct val));
+               if(temp==0)
+                       return;
+               xx = temp;
+               if(absf)
+                       xx[n].xv = n*dx + absbot;
+               else
+                       if(!getfloat(&xx[n].xv))
+                               return;
+               if(!getfloat(&xx[n].yv))
+                       return;
+               xx[n].lblptr = -1;
+               t = getstring();
+               if(t>0)
+                       xx[n].lblptr = copystring(t);
+               n++;
+               if(t<0)
+                       return;
+       }
+}
+
+transpose()
+{
+       register i;
+       float f;
+       struct xy t;
+       if(!transf)
+               return;
+       t = xd; xd = yd; yd = t;
+       for(i= 0;i<n;i++) {
+               f = xx[i].xv; xx[i].xv = xx[i].yv; xx[i].yv = f;
+       }
+}
+
+copystring(k)
+{
+       register char *temp;
+       register i;
+       int q;
+
+       temp = realloc(labs,(unsigned)(labsiz+1+k));
+       if(temp==0)
+               return(0);
+       labs = temp;
+       q = labsiz;
+       for(i=0;i<=k;i++)
+               labs[labsiz++] = labbuf[i];
+       return(q);
+}
+
+float
+modceil(f,t)
+float f,t;
+{
+
+       t = fabs(t);
+       return(ceil(f/t)*t);
+}
+
+float
+modfloor(f,t)
+float f,t;
+{
+       t = fabs(t);
+       return(floor(f/t)*t);
+}
+
+getlim(p,v)
+register struct xy *p;
+struct val *v;
+{
+       register i;
+
+       i = 0;
+       do {
+               if(!p->xlbf && p->xlb>v[i].xv)
+                       p->xlb = v[i].xv;
+               if(!p->xubf && p->xub<v[i].xv)
+                       p->xub = v[i].xv;
+               i++;
+       } while(i < n);
+}
+
+struct z {
+       float lb,ub,mult,quant;
+} setloglim(), setlinlim();
+
+setlim(p)
+register struct xy *p;
+{
+       float t,delta,sign;
+       struct z z;
+       int mark[50];
+       float lb,ub;
+       int lbf,ubf;
+
+       lb = p->xlb;
+       ub = p->xub;
+       delta = ub-lb;
+       if(p->xqf) {
+               if(delta*p->xquant <=0 )
+                       badarg();
+               return;
+       }
+       sign = 1;
+       lbf = p->xlbf;
+       ubf = p->xubf;
+       if(delta < 0) {
+               sign = -1;
+               t = lb;
+               lb = ub;
+               ub = t;
+               t = lbf;
+               lbf = ubf;
+               ubf = t;
+       }
+       else if(delta == 0) {
+               if(ub > 0) {
+                       ub = 2*ub;
+                       lb = 0;
+               } 
+               else
+                       if(lb < 0) {
+                               lb = 2*lb;
+                               ub = 0;
+                       } 
+                       else {
+                               ub = 1;
+                               lb = -1;
+                       }
+       }
+       if(p->xf==log10 && lb>0 && ub>lb) {
+               z = setloglim(lbf,ubf,lb,ub);
+               p->xlb = z.lb;
+               p->xub = z.ub;
+               p->xmult *= z.mult;
+               p->xquant = z.quant;
+               if(setmark(mark,p)<2) {
+                       p->xqf = lbf = ubf = 1;
+                       lb = z.lb; ub = z.ub;
+               } else
+                       return;
+       }
+       z = setlinlim(lbf,ubf,lb,ub);
+       if(sign > 0) {
+               p->xlb = z.lb;
+               p->xub = z.ub;
+       } else {
+               p->xlb = z.ub;
+               p->xub = z.lb;
+       }
+       p->xmult *= z.mult;
+       p->xquant = sign*z.quant;
+}
+
+struct z
+setloglim(lbf,ubf,lb,ub)
+float lb,ub;
+{
+       float r,s,t;
+       struct z z;
+
+       for(s=1; lb*s<1; s*=10) ;
+       lb *= s;
+       ub *= s;
+       for(r=1; 10*r<=lb; r*=10) ;
+       for(t=1; t<ub; t*=10) ;
+       z.lb = !lbf ? r : lb;
+       z.ub = !ubf ? t : ub;
+       if(ub/lb<100) {
+               if(!lbf) {
+                       if(lb >= 5*z.lb)
+                               z.lb *= 5;
+                       else if(lb >= 2*z.lb)
+                               z.lb *= 2;
+               }
+               if(!ubf) {
+                       if(ub*5 <= z.ub)
+                               z.ub /= 5;
+                       else if(ub*2 <= z.ub)
+                               z.ub /= 2;
+               }
+       }
+       z.mult = s;
+       z.quant = r;
+       return(z);
+}
+
+struct z
+setlinlim(lbf,ubf,xlb,xub)
+int lbf,ubf;
+float xlb,xub;
+{
+       struct z z;
+       float r,s,delta;
+       float ub,lb;
+
+loop:
+       ub = xub;
+       lb = xlb;
+       delta = ub - lb;
+       /*scale up by s, a power of 10, so range (delta) exceeds 1*/
+       /*find power of 10 quantum, r, such that delta/10<=r<delta*/
+       r = s = 1;
+       while(delta*s < 10)
+               s *= 10;
+       delta *= s;
+       while(10*r < delta)
+               r *= 10;
+       lb *= s;
+       ub *= s;
+       /*set r=(1,2,5)*10**n so that 3-5 quanta cover range*/
+       if(r>=delta/2)
+               r /= 2;
+       else if(r<delta/5)
+               r *= 2;
+       z.ub = ubf? ub: modceil(ub,r);
+       z.lb = lbf? lb: modfloor(lb,r);
+       if(!lbf && z.lb<=r && z.lb>0) {
+               xlb = 0;
+               goto loop;
+       }
+       else if(!ubf && z.ub>=-r && z.ub<0) {
+               xub = 0;
+               goto loop;
+       }
+       z.quant = r;
+       z.mult = s;
+       return(z);
+}
+
+scale(p,v)
+register struct xy *p;
+struct val *v;
+{
+       float edge;
+
+       getlim(p,v);
+       setlim(p);
+       edge = top-bot;
+       p->xa = p->xsize*edge/((*p->xf)(p->xub) - (*p->xf)(p->xlb));
+       p->xbot = bot + edge*p->xoff;
+       p->xtop = p->xbot + (top-bot)*p->xsize;
+       p->xb = p->xbot - (*p->xf)(p->xlb)*p->xa + .5;
+}
+
+axes()
+{
+       register i;
+       int mark[50];
+       int xn, yn;
+       if(gridf==0)
+               return;
+
+       line(xd.xbot,yd.xbot,xd.xtop,yd.xbot);
+       cont(xd.xtop,yd.xtop);
+       cont(xd.xbot,yd.xtop);
+       cont(xd.xbot,yd.xbot);
+
+       xn = setmark(mark,&xd);
+       for(i=0; i<xn; i++) {
+               if(gridf==2)
+                       line(mark[i],yd.xbot,mark[i],yd.xtop);
+               if(gridf==1) {
+                       line(mark[i],yd.xbot,mark[i],yd.xbot+tick);
+                       line(mark[i],yd.xtop-tick,mark[i],yd.xtop);
+               }
+       }
+       yn = setmark(mark,&yd);
+       for(i=0; i<yn; i++) {
+               if(gridf==2)
+                       line(xd.xbot,mark[i],xd.xtop,mark[i]);
+               if(gridf==1) {
+                       line(xd.xbot,mark[i],xd.xbot+tick,mark[i]);
+                       line(xd.xtop-tick,mark[i],xd.xtop,mark[i]);
+               }
+       }
+}
+
+setmark(xmark,p)
+int *xmark;
+register struct xy *p;
+{
+       int xn = 0;
+       float x,xl,xu;
+       float q;
+       if(p->xf==log10&&!p->xqf) {
+               for(x=p->xquant; x<p->xub; x*=10) {
+                       submark(xmark,&xn,x,p);
+                       if(p->xub/p->xlb<=100) {
+                               submark(xmark,&xn,2*x,p);
+                               submark(xmark,&xn,5*x,p);
+                       }
+               }
+       } else {
+               xn = 0;
+               q = p->xquant;
+               if(q>0) {
+                       xl = modceil(p->xlb+q/6,q);
+                       xu = modfloor(p->xub-q/6,q)+q/2;
+               } else {
+                       xl = modceil(p->xub-q/6,q);
+                       xu = modfloor(p->xlb+q/6,q)-q/2;
+               }
+               for(x=xl; x<=xu; x+=fabs(p->xquant))
+                       xmark[xn++] = (*p->xf)(x)*p->xa + p->xb;
+       }
+       return(xn);
+}
+submark(xmark,pxn,x,p)
+int *xmark;
+int *pxn;
+float x;
+struct xy *p;
+{
+       if(1.001*p->xlb < x && .999*p->xub > x)
+               xmark[(*pxn)++] = log10(x)*p->xa + p->xb;
+}
+
+plot()
+{
+       int ix,iy;
+       int i;
+       int conn;
+
+       conn = 0;
+       if(mode!=0)
+               linemod(modes[mode]);
+       for(i=0; i<n; i++) {
+               if(!conv(xx[i].xv,&xd,&ix) ||
+                  !conv(xx[i].yv,&yd,&iy)) {
+                       conn = 0;
+                       continue;
+               }
+               if(mode!=0) {
+                       if(conn != 0)
+                               cont(ix,iy);
+                       else
+                               move(ix,iy);
+                       conn = 1;
+               }
+               conn &= symbol(ix,iy,xx[i].lblptr);
+       }
+       linemod(modes[1]);
+}
+
+conv(xv,p,ip)
+float xv;
+register struct xy *p;
+int *ip;
+{
+       long ix;
+       ix = p->xa*(*p->xf)(xv*p->xmult) + p->xb;
+       if(ix<p->xbot || ix>p->xtop)
+               return(0);
+       *ip = ix;
+       return(1);
+}
+
+getfloat(p)
+float *p;
+{
+       register i;
+
+       i = scanf("%f",p);
+       return(i==1);
+}
+
+getstring()
+{
+       register i;
+       char junk[20];
+       i = scanf("%1s",labbuf);
+       if(i==-1)
+               return(-1);
+       switch(*labbuf) {
+       default:
+               if(!isdigit(*labbuf)) {
+                       ungetc(*labbuf,stdin);
+                       i = scanf("%s",labbuf);
+                       break;
+               }
+       case '.':
+       case '+':
+       case '-':
+               ungetc(*labbuf,stdin);
+               return(0);
+       case '"':
+               i = scanf("%[^\"\n]",labbuf);
+               scanf("%[\"]",junk);
+               break;
+       }
+       if(i==-1)
+               return(-1);
+       return(strlen(labbuf));
+}
+
+
+symbol(ix,iy,k)
+{
+
+       if(symbf==0&&k<0) {
+               if(mode==0)
+                       point(ix,iy);
+               return(1);
+       } 
+       else {
+               move(ix,iy);
+               label(k>=0?labs+k:plotsymb);
+               move(ix,iy);
+               return(!brkf|k<0);
+       }
+}
+
+title()
+{
+       move(xd.xbot,yd.xbot-60);
+       if (titlebuf[0]) {
+               label(titlebuf);
+               label("       ");
+       }
+       if(erasf&&gridf) {
+               axlab('x',&xd);
+               label("  ");
+               axlab('y',&yd);
+       }
+}
+
+axlab(c,p)
+char c;
+struct xy *p;
+{
+       char buf[50];
+       sprintf(buf,"%g -%s%c- %g", p->xlb/p->xmult,
+               p->xf==log10?"log ":"", c, p->xub/p->xmult);
+       label(buf);
+}
+
+badarg()
+{
+       fprintf(stderr,"graph: error in arguments\n");
+       exit(1);
+}
diff --git a/usr/src/cmd/learn/README b/usr/src/cmd/learn/README
new file mode 100644 (file)
index 0000000..1d5333e
--- /dev/null
@@ -0,0 +1,43 @@
+The C script is not complete; use at your own risk.
+
+Lessons are in
+       /usr/lib/learn/*
+Source is in
+       /usr/src/cmd/learn
+Miscellaneous supporting code is also in source.
+
+Make a learn by
+       make
+When this seems right, extract the lessons by
+       make lessons
+This extracts the lesson archives
+for each course.  You can also do this one step at a
+time with "make files", "make editor", etc.,
+if you don't want all courses.
+If you do things separately, you must also say
+       make play; make log
+
+Finally, check that it's sensible with
+       make check
+If that doesn't print any messages,
+you're probably in good shape.
+
+Learn requires general write permission on the user playpen
+directory .../lib/play.  Lesson directories may be protected.
+
+Learn collects a log file for each script in the .../lib/log
+directory, with a file for each script (files,
+editor, etc.) containing an entry for each lesson
+attempted. These files will grow without bound,
+unless they are periodically truncated. 
+The log files should have general write permission.
+If you don't want logging (a sensible position to take),
+set the variable "logging" to zero in source/lrndef
+before making learn.
+
+Learn requires about 1500 blocks to make itself,
+and about 1000 when completely made.
+
+Please report problems, bad lessons, etc., to
+Brian Kernighan, MH 6021, 2C-518, or
+Mike Lesk, MH 6377, 2C-572.  Thanks.
diff --git a/usr/src/cmd/learn/copy.c b/usr/src/cmd/learn/copy.c
new file mode 100644 (file)
index 0000000..8d1f0f7
--- /dev/null
@@ -0,0 +1,272 @@
+#include "stdio.h"
+#include "signal.h"
+#include "lrnref"
+
+char last[100];
+char logf[100];
+char subdir[100];
+extern char * ctime();
+
+copy(prompt, fin)
+FILE *fin;
+{
+       FILE *fout, *f;
+       char s[100], t[100], s1[100], *r, *tod;
+       char nm[30];
+       int *p, tv[2];
+       extern int intrpt(), *action();
+       extern char *wordb();
+       int nmatch = 0;
+
+       if (subdir[0]==0)
+               sprintf(subdir, "../../%s", sname);
+       for (;;) {
+               if (pgets(s, prompt, fin) == 0)
+                       if (fin == stdin) {
+                               /* fprintf(stderr, "Don't type control-D\n"); */
+                               /* this didn't work out very well */
+                               continue;
+                       } else
+                               break;
+               trim(s);
+               /* change the sequence %s to lesson directory */
+               /* if needed */
+               for (r = s; *r; r++)
+                       if (*r == '%') {
+                               sprintf(s1, s, subdir, subdir, subdir);
+                               strcpy(s, s1);
+                               break;
+                       }
+               r = wordb(s, t);
+               p = action(t);
+               if (*p == ONCE) {       /* some actions done only once per script */
+                       if (wrong) {    /* we are on 2nd time */
+                               scopy(fin, NULL);
+                               continue;
+                       }
+                       strcpy(s, r);
+                       r = wordb(s, t);
+                       p = action(t);
+               }
+               if (p == 0) {
+                       if (comfile >= 0) {
+                               write(comfile, s, strlen(s));
+                               write(comfile, "\n", 1);
+                       }
+                       else {
+                               signal(SIGINT, SIG_IGN);
+                               status = mysys(s);
+                               signal(SIGINT, intrpt);
+                       }
+                       if (incopy) {
+                               fprintf(incopy, "%s\n", s);
+                               strcpy(last, s);
+                       }
+                       continue;
+               }
+               switch (*p) {
+               case READY:
+                       if (incopy && r) {
+                               fprintf(incopy, "%s\n", r);
+                               strcpy(last, r);
+                       }
+                       return;
+               case PRINT:
+                       if (wrong)
+                               scopy(fin, NULL);       /* don't repeat message */
+                       else if (r)
+                               list(r);
+                       else
+                               scopy(fin, stdout);
+                       break;
+               case NOP:
+                       break;
+               case MATCH:
+                       if (nmatch > 0) /* we have already passed */
+                               scopy(fin, NULL);
+                       else if ((status = strcmp(r, last)) == 0) {     /* did we pass this time? */
+                               nmatch++;
+                               scopy(fin, stdout);
+                       } else
+                               scopy(fin, NULL);
+                       break;
+               case BAD:
+                       if (strcmp(r, last) == 0) {
+                               scopy(fin, stdout);
+                       } else
+                               scopy(fin, NULL);
+                       break;
+               case SUCCEED:
+                       scopy(fin, (status == 0) ? stdout : NULL);
+                       break;
+               case FAIL:
+                       scopy(fin, (status != 0) ? stdout : NULL);
+                       break;
+               case CREATE:
+                       fout = fopen(r, "w");
+                       scopy(fin, fout);
+                       fclose(fout);
+                       break;
+               case CMP:
+                       status = cmp(r);        /* contains two file names */
+                       break;
+               case MV:
+                       sprintf(nm, "%s/L%s.%s", subdir, todo, r);
+                       fcopy(r, nm);
+                       break;
+               case USER:
+               case NEXT:
+                       more = 1;
+                       return;
+               case COPYIN:
+                       incopy = fopen(".copy", "w");
+                       break;
+               case UNCOPIN:
+                       fclose(incopy);
+                       incopy = NULL;
+                       break;
+               case COPYOUT:
+                       maktee();
+                       break;
+               case UNCOPOUT:
+                       untee();
+                       break;
+               case PIPE:
+                       comfile = makpipe();
+                       break;
+               case UNPIPE:
+                       close(comfile);
+                       wait(0);
+                       comfile = -1;
+                       break;
+               case YES:
+               case NO:
+                       if (incopy) {
+                               fprintf(incopy, "%s\n", s);
+                               strcpy(last, s);
+                       }
+                       return;
+               case WHERE:
+                       printf("You are in lesson %s\n", todo);
+                       fflush(stdout);
+                       break;
+               case BYE:
+                       more=0;
+                       return;
+               case CHDIR:
+                       printf("cd not allowed\n");
+                       fflush(stdout);
+                       break;
+               case LEARN:
+                       printf("You are already in learn.\n");
+                       fflush(stdout);
+                       break;
+               case LOG:
+                       if (!logging)
+                               break;
+                       if (logf[0] == 0)
+                               sprintf(logf, "%s/log/%s", direct, sname);
+                       f = fopen( (r? r : logf), "a");
+                       if (f == NULL)
+                               break;
+                       time(tv);
+                       tod = ctime(tv);
+                       tod[24] = 0;
+                       fprintf(f, "%s L%-6s %s %2d %s\n", tod,
+                               todo, status? "fail" : "pass", speed, pwline);
+                       fclose(f);
+                       break;
+               }
+       }
+       return;
+}
+
+pgets(s, prompt, f)
+FILE *f;
+{
+       if (prompt) {
+               if (comfile < 0)
+                       printf("$ ");
+               fflush(stdout);
+       }
+       if (fgets(s, 100,f))
+               return(1);
+       else
+               return(0);
+}
+
+trim(s)
+char *s;
+{
+       while (*s)
+               s++;
+       if (*--s == '\n')
+               *s=0;
+}
+
+scopy(fi, fo)  /* copy fi to fo until a line with # */
+FILE *fi, *fo;
+{
+       int c;
+
+       while ((c = getc(fi)) != '#' && c != EOF) {
+               do {
+                       if (fo != NULL)
+                               putc(c, fo);
+                       if (c == '\n')
+                               break;
+               } while ((c = getc(fi)) != EOF);
+       }
+       if (c == '#')
+               ungetc(c, fi);
+       fflush(fo);
+}
+
+cmp(r) /* compare two files for status */
+char *r;
+{
+       char *s;
+       FILE *f1, *f2;
+       int c1, c2, stat;
+
+       for (s = r; *s != ' ' && *s != '\0'; s++)
+               ;
+       *s++ = 0;       /* r contains file 1 */
+       while (*s == ' ')
+               s++;
+       f1 = fopen(r, "r");
+       f2 = fopen(s, "r");
+       if (f1 == NULL || f2 == NULL)
+               return(1);      /* failure */
+       stat = 0;
+       for (;;) {
+               c1 = getc(f1);
+               c2 = getc(f2);
+               if (c1 != c2) {
+                       stat = 1;
+                       break;
+               }
+               if (c1 == EOF || c2 == EOF)
+                       break;
+       }
+       fclose(f1);
+       fclose(f2);
+       return(stat);
+}
+
+char *
+wordb(s, t)    /* in s, t is prefix; return tail */
+char *s, *t;
+{
+       int c;
+
+       while (c = *s++) {
+               if (c == ' ' || c == '\t')
+                       break;
+               *t++ = c;
+       }
+       *t = 0;
+       while (*s == ' ' || *s == '\t')
+               s++;
+       return(c ? s : NULL);
+}
diff --git a/usr/src/cmd/learn/dounit.c b/usr/src/cmd/learn/dounit.c
new file mode 100644 (file)
index 0000000..26a65d4
--- /dev/null
@@ -0,0 +1,59 @@
+#include "stdio.h"
+#include "lrnref"
+
+dounit()
+{
+       char tbuff[100];
+
+       if (todo == 0)
+               return;
+       wrong = 0;
+retry:
+       start(todo);
+       sprintf(tbuff, "../../%s/L%s", sname, todo);    /* script = lesson */
+       scrin = fopen(tbuff, "r");
+       if (scrin == NULL) {
+               fprintf(stderr, "No script.\n");
+               wrapup(1);
+       }
+
+       copy(0, scrin);
+       if (more == 0)
+               return;
+       copy(1, stdin);
+       if (more == 0)
+               return;
+       copy(0, scrin);
+
+       if (comfile >= 0)
+               close(comfile);
+       wait(&didok);
+       didok = (status == 0);
+       if (!didok) {
+               wrong++;
+               printf("\nSorry, that's %snot right.  Do you want to try again?  ",
+                       wrong > 1 ? "still " : "");
+               fflush(stdout);
+               for(;;) {
+                       gets(tbuff);
+                       if (tbuff[0] == 'y') {
+                               printf("Try the problem again.\n");
+                               fflush(stdout);
+                               goto retry;
+                       } else if (strcmp(tbuff, "bye") == 0) {
+                               wrapup(1);
+                       } else if (tbuff[0] == 'n') {
+                               wrong = 0;
+                               printf("\nOK.  Lesson %s (%d)\n", todo, speed);
+                               printf("Skipping to next lesson.\n\n");
+                               fflush(stdout);
+                               break;
+                       } else {
+                               printf("Please type yes, no or bye:  ");
+                               fflush(stdout);
+                       }
+               }
+       }
+       setdid(todo, sequence++);
+}
+
diff --git a/usr/src/cmd/learn/lcount.c b/usr/src/cmd/learn/lcount.c
new file mode 100644 (file)
index 0000000..110d827
--- /dev/null
@@ -0,0 +1,12 @@
+#include "stdio.h"
+
+main() /* count lines in something */
+{
+       register n, c;
+
+       n = 0;
+       while ((c = getchar()) != EOF)
+               if (c == '\n')
+                       n++;
+       printf("%d\n", n);
+}
diff --git a/usr/src/cmd/learn/learn.c b/usr/src/cmd/learn/learn.c
new file mode 100644 (file)
index 0000000..3080f3f
--- /dev/null
@@ -0,0 +1,47 @@
+#include "stdio.h"
+#include "lrndef"
+#include "lrnref"
+#include "signal.h"
+
+main(argc,argv)
+char *argv[];
+{
+       extern hangup(), intrpt();
+       extern char * getlogin();
+       char *malloc();
+
+       speed = 0;
+       more = 1;
+       pwline = getlogin();
+       setbuf(stdout, malloc(BUFSIZ));
+       selsub(argc, argv);
+       signal(SIGHUP, hangup);
+       signal(SIGINT, intrpt);
+       while (more) {
+               selunit();
+               dounit();
+               whatnow();
+       }
+       wrapup(0);
+}
+
+hangup()
+{
+       wrapup(1);
+}
+
+intrpt()
+{
+       char response[20], *p;
+
+       signal(SIGINT, hangup);
+       write(2, "\nInterrupt.\nWant to go on?  ", 28);
+       p = response;
+       *p = 'n';
+       while (read(0, p, 1) == 1 && *p != '\n')
+               p++;
+       if (response[0] != 'y')
+               wrapup(1);
+       ungetc('\n', stdin);
+       signal(SIGINT, intrpt);
+}
diff --git a/usr/src/cmd/learn/list.c b/usr/src/cmd/learn/list.c
new file mode 100644 (file)
index 0000000..76cf6e8
--- /dev/null
@@ -0,0 +1,30 @@
+#include "stdio.h"
+#include "lrnref"
+#include "signal.h"
+
+int istop;
+
+list(r)
+char *r;
+{
+       int stop(), intrpt();
+       FILE *ft;
+       char s[100];
+
+       if (r==0)
+               return;
+       istop = 1;
+       signal(SIGINT, stop);
+       ft = fopen(r, "r");
+       if (ft != NULL) {
+               while (fgets(s, 100, ft) && istop)
+                       fputs(s, stdout);
+               fclose(ft);
+       }
+       signal(SIGINT, intrpt);
+}
+
+stop()
+{
+       istop=0;
+}
diff --git a/usr/src/cmd/learn/lrndef b/usr/src/cmd/learn/lrndef
new file mode 100644 (file)
index 0000000..be6b992
--- /dev/null
@@ -0,0 +1,18 @@
+#include       <stdio.h>
+char   *direct = "/usr/lib/learn";     /* CHANGE THIS ON YOUR SYSTEM */
+int    more;
+char   *level;
+int    speed;
+char   *sname;
+char   *todo;
+FILE   *incopy = NULL;
+int    didok;
+int    sequence        = 1;
+int    comfile = -1;
+int    status;
+int    wrong;
+char   *pwline;
+char   *dir;
+FILE   *scrin;
+int    logging = 1;    /* set to 0 to turn off logging */
+int    ask;
diff --git a/usr/src/cmd/learn/lrnref b/usr/src/cmd/learn/lrnref
new file mode 100644 (file)
index 0000000..602c0b2
--- /dev/null
@@ -0,0 +1,46 @@
+#define        READY   0
+#define        PRINT   1
+#define        COPYIN  2
+#define        COPYOUT 3
+#define        UNCOPIN 4
+#define        UNCOPOUT        5
+#define        PIPE    6
+#define        UNPIPE  7
+#define        YES     8
+#define        NO      9
+#define        SUCCEED 10
+#define        FAIL    11
+#define        BYE     12
+#define        LOG     13
+#define        CHDIR   14
+#define        LEARN   15
+#define        MV      16
+#define        USER    17
+#define        NEXT    18
+#define        SKIP    19
+#define        WHERE   20
+#define        MATCH   21
+#define        NOP     22
+#define        BAD     23
+#define        CREATE  24
+#define        CMP     25
+#define        GOTO    26
+#define        ONCE    27
+
+extern int     more;
+extern char    *level;
+extern int     speed;
+extern char    *sname;
+extern char    *direct;
+extern char    *todo;
+extern int     didok;
+extern int     sequence;
+extern int     comfile;
+extern int     status;
+extern int     wrong;
+extern char    *pwline;
+extern char    *dir;
+extern FILE    *incopy;
+extern FILE    *scrin;
+extern int     logging;
+extern int     ask;
diff --git a/usr/src/cmd/learn/makpipe.c b/usr/src/cmd/learn/makpipe.c
new file mode 100644 (file)
index 0000000..94e09c8
--- /dev/null
@@ -0,0 +1,20 @@
+#include "stdio.h"
+
+makpipe()
+{
+       int f[2];
+
+       pipe(f);
+       if (fork()==0) {
+               close(f[1]);
+               close(0);
+               dup(f[0]);
+               close(f[0]);
+               execl ("/bin/sh", "sh", "-i", 0);
+               execl ("/usr/bin/sh", "sh", "-i", 0);
+               write(2,"Exec error\n",11);
+       }
+       close(f[0]);
+       sleep(2);       /* so shell won't eat up too much input */
+       return(f[1]);
+}
diff --git a/usr/src/cmd/learn/maktee.c b/usr/src/cmd/learn/maktee.c
new file mode 100644 (file)
index 0000000..1585ac2
--- /dev/null
@@ -0,0 +1,46 @@
+#include "stdio.h"
+#include "signal.h"
+#include "lrnref"
+
+static int oldout;
+static char tee[50];
+
+maktee()
+{
+       int fpip[2], in, out;
+
+       if (tee[0] == 0)
+               sprintf(tee, "%s/tee", direct);
+       pipe(fpip);
+       in = fpip[0];
+       out= fpip[1];
+       if (fork() == 0) {
+               signal(SIGINT, SIG_IGN);
+               close(0);
+               close(out);
+               dup(in);
+               close(in);
+               execl (tee, "lrntee", 0);
+               fprintf(stderr, "Tee exec failed\n");
+               exit(1);
+       }
+       close(in);
+       fflush(stdout);
+       oldout = dup(1);
+       close(1);
+       if (dup(out) != 1)
+               fprintf(stderr, "Error making tee for copyout\n");
+       close(out);
+       return(1);
+}
+
+untee()
+{
+       int x;
+
+       fflush(stdout);
+       close(1);
+       dup(oldout);
+       close(oldout);
+       wait(&x);
+}
diff --git a/usr/src/cmd/learn/mem.c b/usr/src/cmd/learn/mem.c
new file mode 100644 (file)
index 0000000..b226a8d
--- /dev/null
@@ -0,0 +1,94 @@
+# include "stdio.h"
+# include "lrnref"
+# define SAME 0
+
+struct keys {
+       char *k_wd;
+       int k_val;
+} keybuff[] = {
+       {"ready",       READY},
+       {"answer",      READY},
+       {"#print",      PRINT},
+       {"#copyin",     COPYIN},
+       {"#uncopyin",   UNCOPIN},
+       {"#copyout",    COPYOUT},
+       {"#uncopyout",  UNCOPOUT},
+       {"#pipe",       PIPE},
+       {"#unpipe",     UNPIPE},
+       {"#succeed",    SUCCEED},
+       {"#fail",       FAIL},
+       {"bye",         BYE},
+       {"chdir",       CHDIR},
+       {"cd",          CHDIR},
+       {"learn",       LEARN},
+       {"#log",        LOG},
+       {"yes",         YES},
+       {"no",          NO},
+       {"#mv",         MV},
+       {"#user",       USER},
+       {"#next",       NEXT},
+       {"skip",        SKIP},
+       {"#where",      WHERE},
+       {"#match",      MATCH},
+       {"#bad",        BAD},
+       {"#create",     CREATE},
+       {"#cmp",        CMP},
+       {"#goto",       GOTO},
+       {"#once",       ONCE},
+       {"#",           NOP},
+       {NULL,          0}
+};
+
+int *action(s)
+char *s;
+{
+       struct keys *kp;
+       for (kp=keybuff; kp->k_wd; kp++)
+               if (strcmp(kp->k_wd, s) == SAME)
+                       return(&(kp->k_val));
+       return(NULL);
+}
+
+# define NW 100
+# define NWCH 800
+struct whichdid {
+       char *w_less;
+       int w_seq;
+} which[NW];
+int nwh = 0;
+char whbuff[NWCH];
+char *whcp = whbuff;
+
+setdid(lesson, sequence)
+char *lesson;
+{
+       struct whichdid *pw;
+       for(pw=which; pw < which+nwh; pw++)
+               if (strcmp(pw->w_less, lesson) == SAME)
+                       {
+                       pw->w_seq = sequence;
+                       return;
+                       }
+       pw=which+nwh++;
+       if (nwh >= NW) {
+               fprintf(stderr, "nwh>=NW\n");
+               wrapup(1);
+       }
+       pw->w_seq = sequence;
+       pw->w_less = whcp;
+       while (*whcp++ = *lesson++);
+       if (whcp >= whbuff + NWCH) {
+               fprintf(stderr, "lesson name too long\n");
+               wrapup(1);
+       }
+}
+
+already(lesson, sequence)
+char *lesson;
+{
+       struct whichdid *pw;
+       for (pw=which; pw < which+nwh; pw++)
+               if (strcmp(pw->w_less, lesson) == SAME)
+                       return(1);
+       return(0);
+}
diff --git a/usr/src/cmd/learn/mysys.c b/usr/src/cmd/learn/mysys.c
new file mode 100644 (file)
index 0000000..77b4a2e
--- /dev/null
@@ -0,0 +1,120 @@
+#include "stdio.h"
+#include "signal.h"
+
+#define        EASY    1
+#define        MEDIUM  2
+#define        HARD    3
+
+mysys(s)
+char *s;
+{
+       /* like "system" but rips off "mv", etc.*/
+       /* also tries to guess if can get away with exec cmd */
+       /* instead of sh cmd */
+       char p[300];
+       char *np[40];
+       register char *t;
+       int nv, type, stat;
+
+       type = EASY;    /* we hope */
+       for (t = s; *t && type != HARD; t++) {
+               switch (*t) {
+               case '*': 
+               case '[': 
+               case '?': 
+               case '>': 
+               case '<': 
+               case '$':
+               case '\'':
+               case '"':
+                       type = MEDIUM;
+                       break;
+               case '|': 
+               case ';': 
+               case '&':
+                       type = HARD;
+                       break;
+               }
+       }
+       switch (type) {
+       case HARD:
+               return(system(s));
+       case MEDIUM:
+               strcpy(p, "exec ");
+               strcat(p, s);
+               return(system(p));
+       case EASY:
+               strcpy(p,s);
+               nv = getargs(p, np);
+               t=np[0];
+               if ((strcmp(t, "mv") == 0)||
+                   (strcmp(t, "cp") == 0)||
+                   (strcmp(t, "rm") == 0)||
+                   (strcmp(t, "ls") == 0) ) {
+                       if (fork() == 0) {
+                               char b[100];
+                               signal(SIGINT, SIG_DFL);
+                               strcpy(b, "/bin/");
+                               strcat(b, t);
+                               np[nv] = 0;
+                               execv(b, np);
+                               fprintf(stderr, "Execv failed\n");
+                               exit(1);
+                       }
+                       wait(&stat);
+                       return(stat);
+               }
+               return(system(s));
+       }
+}
+
+/*
+ * system():
+ *     same as library version, except that resets
+ *     default handling of signals in child, so that
+ *     user gets the behavior he expects.
+ */
+
+system(s)
+char *s;
+{
+       int status, pid, w;
+       register int (*istat)(), (*qstat)();
+
+       istat = signal(SIGINT, SIG_IGN);
+       qstat = signal(SIGQUIT, SIG_IGN);
+       if ((pid = fork()) == 0) {
+               signal(SIGINT, SIG_DFL);
+               signal(SIGQUIT, SIG_DFL);
+               execl("/bin/sh", "sh", "-c", s, 0);
+               _exit(127);
+       }
+       while ((w = wait(&status)) != pid && w != -1)
+               ;
+       if (w == -1)
+               status = -1;
+       signal(SIGINT, istat);
+       signal(SIGQUIT, qstat);
+       return(status);
+}
+
+getargs(s, v)
+char *s, **v;
+{
+       int i;
+
+       i = 0;
+       for (;;) {
+               v[i++]=s;
+               while (*s != 0 && *s!=' '&& *s != '\t')
+                       s++;
+               if (*s == 0)
+                       break;
+               *s++ =0;
+               while (*s == ' ' || *s == '\t')
+                       s++;
+               if (*s == 0)
+                       break;
+       }
+       return(i);
+}
diff --git a/usr/src/cmd/learn/origmakefile b/usr/src/cmd/learn/origmakefile
new file mode 100644 (file)
index 0000000..e7aa1f1
--- /dev/null
@@ -0,0 +1,68 @@
+LESSONS = files editor morefiles macros eqn C
+
+FILES = lrndef lrnref \
+       copy.c dounit.c learn.c list.c \
+       makpipe.c maktee.c mem.c mysys.c selsub.c selunit.c \
+       start.c whatnow.c wrapup.c \
+       lcount.c tee.c \
+       makefile ../README
+
+OBJECTS = copy.o dounit.o learn.o list.o mem.o \
+       makpipe.o maktee.o mysys.o selsub.o selunit.o \
+       start.o whatnow.o wrapup.o
+
+CFLAGS = -O
+LIBRARY = -lS
+
+a.out: $(OBJECTS)
+       cc -n $(CFLAGS) $(OBJECTS) $(LIBRARY)
+
+$(OBJECTS): lrnref
+learn.o: lrndef
+
+list:
+       pr $(FILES)
+
+bin:
+       cp a.out /usr/bin/learn
+       strip /usr/bin/learn
+
+lcount tee:
+       cc $(CFLAGS) -s $@.c -o ../lib/$@ $(LIBRARY)
+
+lessons:       $(LESSONS)
+
+play log:
+       -rm -r ../lib/$@; mkdir ../lib/$@; chmod +w ../lib/$@
+
+$(LESSONS):
+       -rm -r ../lib/$@
+       mkdir ../lib/$@
+       (cd ../lib/$@; ar x ../$@.a)
+
+everything:    a.out bin tee lcount lessons play log check
+
+archives:
+       (cd ../lib/files; ar r ../files.a L*)
+       (cd ../lib/morefiles; ar r ../morefiles.a L*)
+       (cd ../lib/editor; ar r ../editor.a L*)
+       (cd ../lib/macros; ar r ../macros.a L*)
+       (cd ../lib/eqn; ar r ../eqn.a L* tinyms Init)
+       (cd ../lib/C; ar r ../C.a L* get*)
+
+export:
+       : make the directories
+       mkdir export export/source export/lib
+       : copy source files
+       -cp $(FILES) export/source
+       : non-directories in lib
+       -for i in ../lib/*;\
+       do if test -f $$i; then cp $$i export/lib; fi;\
+       done
+
+check:
+       -@test -r ../lib/tee || echo 'tee not present; make tee'
+       -@test -r ../lib/lcount || echo 'lcount not present; make lcount'
+       -@test -r ../lib/play || echo 'play directory not present; make play'
+       -@test -r ../lib/log || echo 'log directory not present; make log'
+       -@for i in $(LESSONS); do test -r ../lib/$$i/L0 || echo $$i not unarchived, make $$i; done
diff --git a/usr/src/cmd/learn/selsub.c b/usr/src/cmd/learn/selsub.c
new file mode 100644 (file)
index 0000000..0685a5f
--- /dev/null
@@ -0,0 +1,94 @@
+#include "stdio.h"
+#include "lrnref"
+
+selsub(argc,argv)
+char *argv[];
+{
+       char ans1[100], *cp;
+       static char ans2[30];
+       static char dirname[20];
+       static char subname[20];
+
+       if (argc > 1 && argv[1][0] == '-') {
+               direct = argv[1]+1;
+               argc--;
+               argv++;
+       }
+       chknam(direct);
+       if (chdir(direct) != 0) {
+               fprintf(stderr, "can't cd to %s\,", direct);
+               exit(1);
+       }
+       sname = argc > 1 ? argv[1] : 0;
+       if (argc > 2)
+               strcpy (level=ans2, argv[2]);
+       else
+               level = 0;
+       if (argc > 3 )
+               speed = atoi(argv[3]);
+       if (!sname) {
+               printf("These are the available courses -\n");
+               list("Linfo");
+               printf("If you want more information about the courses,\n");
+               printf("or if you have never used 'learn' before,\n");
+               printf("type 'return'; otherwise type the name of\n");
+               printf("the course you want, followed by 'return'.\n");
+               fflush(stdout);
+               gets(sname=subname);
+               if (sname[0] == '\0') {
+                       list("Xinfo");
+                       do {
+                               printf("\nWhich subject?  ");
+                               fflush(stdout);
+                               gets(sname=subname);
+                       } while (sname[0] == '\0');
+               }
+       }
+       chknam(sname);
+       if (!level) {
+               printf("If you were in the middle of this subject\n");
+               printf("and want to start where you left off, type\n");
+               printf("the last lesson number the computer printed.\n");
+               printf("To start at the beginning, just hit return.\n");
+               fflush(stdout);
+               gets(ans2);
+               if (ans2[0]==0)
+                       strcpy(ans2,"0");
+               for (cp=ans2; *cp; cp++)
+                       if (*cp == '(' || *cp == ' ')
+                               *cp= 0;
+               level=ans2;
+       }
+
+       /* make new directory for user to play in */
+       if (chdir("play") != 0) {
+               fprintf(stderr, "can't cd to playpen\n");
+               exit(1);
+       }
+       sprintf(dir=dirname, "pl%da", getpid());
+       sprintf(ans1, "mkdir %s", dir);
+       system(ans1);
+       if (chdir(dir) < 0) {
+               fprintf(stderr, "Couldn't create working directory.\nBye.\n");
+               exit(1);
+       }
+       /* after this point, we have a working directory. */
+       /* have to call wrapup to clean up */
+       if (access(sprintf(ans1, "%s/%s/Init", direct, sname), 04)==0)
+               if (system(sprintf(ans1, "%s/%s/Init %s", direct,sname, level)) != 0) {
+                       printf("Leaving learn.\n");
+                       wrapup(1);
+               }
+       if (level[0] == '-')    /* no lesson names start with - */
+               ask = 1;
+       start(level);
+}
+
+chknam(name)
+char *name;
+{
+       if (access(name, 05) < 0) {
+               printf("Sorry, there is no subject or lesson named %s.\nBye.\n", name);
+               exit(1);
+       }
+}
diff --git a/usr/src/cmd/learn/selunit.c b/usr/src/cmd/learn/selunit.c
new file mode 100644 (file)
index 0000000..ed5d1c9
--- /dev/null
@@ -0,0 +1,102 @@
+#include "stdio.h"
+#include "lrnref"
+
+int    nsave   = 0;
+
+selunit()
+{
+       char fnam[20], s[50];
+       static char dobuff[50];
+       char posslev[20][20];
+       int diff[20], i, k, m, n, best, alts;
+       FILE *f;
+       char zb[200];
+       static char saved[20];
+
+       while (ask) {
+               printf("What lesson? ");
+               fflush(stdout);
+               gets(dobuff);
+               if (strcmp(dobuff, "bye") == 0)
+                       wrapup(0);
+               level = todo = dobuff;
+               sprintf(s, "../../%s/L%s", sname, dobuff);
+               if (access(s, 04) == 0)
+                       return;
+               printf("no such lesson\n");
+       }
+       alts = 0;
+retry:
+       f=scrin;
+       if (f==NULL) {
+               sprintf(fnam, "../../%s/L%s", sname, level);
+               f = fopen(fnam, "r");
+               if (f==NULL) {
+                       fprintf(stderr, "No script for lesson %s.\n", level);
+                       wrapup(1);
+               }
+               while (fgets(zb, 200, f)) {
+                       trim(zb);
+                       if (strcmp(zb, "#next")==0)
+                               break;
+               }
+       }
+       if (feof(f)) {
+               printf("Congratulations; you have finished this sequence.\n");
+               fflush(stdout);
+               todo = 0;
+               return;
+       }
+       for(i=0; fgets(s, 50, f); i++) {
+               sscanf(s, "%s %d", posslev[i], &diff[i]);
+       }
+       best = -1;
+       /* cycle through lessons from random start */
+       /* first try the current place, failing that back up to
+            last place there are untried alternatives (but only one backup) */
+       n = grand()%i;
+       for(k=0; k<i; k++) {
+               m = (n+k)%i;
+               if (already(posslev[m],0)) continue;
+               if (best<0) best=m;
+               /* real alternatives */
+               alts++;
+               if (abs(diff[m]-speed) < abs(diff[best]-speed))
+                       best=m;
+       }
+       if (best < 0 && nsave) {
+               nsave--;
+               strcpy(level, saved);
+               goto retry;
+       }
+       if (best <0) {
+               /* lessons exhausted or missing */
+               printf("Sorry, there are no alternative lessons at this stage.\n");
+               printf("See someone for help.\n");
+               fflush(stdout);
+               todo = 0;
+               return;
+       }
+       strcpy (dobuff, posslev[best]);
+       if (alts>1) {
+               nsave=1;
+               strcpy (saved, level);
+       }
+       todo = dobuff;
+       fclose(f);
+}
+
+abs(x)
+{
+       return(x>=0? x: -x);
+}
+
+grand()
+{
+       static int garbage;
+       int a[2], b;
+
+       time(a);
+       b = a[1]+10*garbage++;
+       return(b&077777);
+}
diff --git a/usr/src/cmd/learn/temp b/usr/src/cmd/learn/temp
new file mode 100644 (file)
index 0000000..8fe50c0
--- /dev/null
@@ -0,0 +1,5 @@
+play:
+       -rm -r ../lib/play; mkdir ../lib/play; chmod +w ../lib/play
+
+log:
+       -rm -r ../lib/log; mkdir ../lib/log; chmod +w ../lib/log
diff --git a/usr/src/cmd/learn/whatnow.c b/usr/src/cmd/learn/whatnow.c
new file mode 100644 (file)
index 0000000..7a61164
--- /dev/null
@@ -0,0 +1,28 @@
+#include "stdio.h"
+#include "lrnref"
+
+whatnow()
+{
+       if (todo == 0) {
+               more=0;
+               return;
+       }
+       if (didok) {
+               strcpy(level,todo);
+               if (speed<=9) speed++;
+       }
+       else {
+               speed -= 4;
+               /* the 4 above means that 4 right, one wrong leave
+                   you with the same speed. */
+               if (speed <0) speed=0;
+       }
+       if (wrong) {
+               speed -= 2;
+               if (speed <0 ) speed = 0;
+       }
+       if (didok && more) {
+               printf("\nGood.  Lesson %s (%d)\n\n",level, speed);
+               fflush(stdout);
+       }
+}
diff --git a/usr/src/cmd/learn/wrapup.c b/usr/src/cmd/learn/wrapup.c
new file mode 100644 (file)
index 0000000..cdf44cc
--- /dev/null
@@ -0,0 +1,26 @@
+#include "signal.h"
+#include "stdio.h"
+#include "lrnref"
+
+wrapup(n)
+int n;
+{
+       /* this routine does not use 'system' because it wants
+        interrupts turned off */
+       int retval, pid, pidw;
+
+       signal(SIGINT, SIG_IGN);
+       chdir("..");
+       if ( (pid=fork()) ==0) {
+               signal(SIGHUP, SIG_IGN);
+               execl("/bin/rm", "rm", "-r", dir, 0);
+               execl("/usr/bin/rm", "rm", "-r", dir, 0);
+               fprintf(stderr, "Can't find 'rm' command.\n");
+               exit(0);
+       }
+       printf("Bye.\n"); /* not only does this reassure user but 
+                       it stalls for time while deleting directory */
+       fflush(stdout);
+       /* printf("Wantd %d got %d val %d\n",pid, pidw, retval); */
+       exit(n);
+}
diff --git a/usr/src/cmd/lex/header.c b/usr/src/cmd/lex/header.c
new file mode 100644 (file)
index 0000000..1e9561c
--- /dev/null
@@ -0,0 +1,109 @@
+# include "ldefs.c"
+phead1(){
+       ratfor ? rhd1() : chd1();
+       }
+
+chd1(){
+       fprintf(fout,"# include \"stdio.h\"\n");
+       if (ZCH>NCH)
+       fprintf(fout, "# define U(x) ((x)&0377)\n");
+       else
+       fprintf(fout, "# define U(x) x\n");
+       fprintf(fout, "# define NLSTATE yyprevious=YYNEWLINE\n");
+       fprintf(fout,"# define BEGIN yybgin = yysvec + 1 +\n");
+       fprintf(fout,"# define INITIAL 0\n");
+       fprintf(fout,"# define YYLERR yysvec\n");
+       fprintf(fout,"# define YYSTATE (yyestate-yysvec-1)\n");
+       if(optim)
+               fprintf(fout,"# define YYOPTIM 1\n");
+# ifdef DEBUG
+       fprintf(fout,"# define LEXDEBUG 1\n");
+# endif
+       fprintf(fout,"# define YYLMAX 200\n");
+       fprintf(fout,"# define output(c) putc(c,yyout)\n");
+       fprintf(fout, "%s%d%s\n",
+  "# define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==",
+       ctable['\n'],
+ "?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)");
+       fprintf(fout,
+"# define unput(c) {yytchar= (c);if(yytchar=='\\n')yylineno--;*yysptr++=yytchar;}\n");
+       fprintf(fout,"# define yymore() (yymorfg=1)\n");
+       fprintf(fout,"# define ECHO fprintf(yyout, \"%%s\",yytext)\n");
+       fprintf(fout,"# define REJECT { nstr = yyreject(); goto yyfussy;}\n");
+       fprintf(fout,"int yyleng; extern char yytext[];\n");
+       fprintf(fout,"int yymorfg;\n");
+       fprintf(fout,"extern char *yysptr, yysbuf[];\n");
+       fprintf(fout,"int yytchar;\n");
+       fprintf(fout,"FILE *yyin ={stdin}, *yyout ={stdout};\n");
+       fprintf(fout,"extern int yylineno;\n");
+       fprintf(fout,"struct yysvf { \n");
+       fprintf(fout,"\tstruct yywork *yystoff;\n");
+       fprintf(fout,"\tstruct yysvf *yyother;\n");
+       fprintf(fout,"\tint *yystops;};\n");
+       fprintf(fout,"struct yysvf *yyestate;\n");
+       fprintf(fout,"extern struct yysvf yysvec[], *yybgin;\n");
+       }
+
+rhd1(){
+       fprintf(fout,"integer function yylex(dummy)\n");
+       fprintf(fout,"define YYLMAX 200\n");
+       fprintf(fout,"define ECHO call yyecho(yytext,yyleng)\n");
+       fprintf(fout,"define REJECT nstr = yyrjct(yytext,yyleng);goto 30998\n");
+       fprintf(fout,"integer nstr,yylook,yywrap\n");
+       fprintf(fout,"integer yyleng, yytext(YYLMAX)\n");
+       fprintf(fout,"common /yyxel/ yyleng, yytext\n");
+       fprintf(fout,"common /yyldat/ yyfnd, yymorf, yyprev, yybgin, yylsp, yylsta\n");
+       fprintf(fout,"integer yyfnd, yymorf, yyprev, yybgin, yylsp, yylsta(YYLMAX)\n");
+       fprintf(fout,"for(;;){\n");
+       fprintf(fout,"\t30999 nstr = yylook(dummy)\n");
+       fprintf(fout,"\tgoto 30998\n");
+       fprintf(fout,"\t30000 k = yywrap(dummy)\n");
+       fprintf(fout,"\tif(k .ne. 0){\n");
+       fprintf(fout,"\tyylex=0; return; }\n");
+       fprintf(fout,"\t\telse goto 30998\n");
+       }
+
+phead2(){
+       if(!ratfor)chd2();
+       }
+
+chd2(){
+       fprintf(fout,"while((nstr = yylook()) >= 0)\n");
+       fprintf(fout,"yyfussy: switch(nstr){\n");
+       fprintf(fout,"case 0:\n");
+       fprintf(fout,"if(yywrap()) return(0); break;\n");
+       }
+
+ptail(){
+       if(!pflag)
+               ratfor ? rtail() : ctail();
+       pflag = 1;
+       }
+
+ctail(){
+       fprintf(fout,"case -1:\nbreak;\n");             /* for reject */
+       fprintf(fout,"default:\n");
+       fprintf(fout,"fprintf(yyout,\"bad switch yylook %%d\",nstr);\n");
+       fprintf(fout,"} return(0); }\n");
+       fprintf(fout,"/* end of yylex */\n");
+       }
+
+rtail(){
+       register int i;
+       fprintf(fout,"\n30998 if(nstr .lt. 0 .or. nstr .gt. %d)goto 30999\n",casecount);
+       fprintf(fout,"nstr = nstr + 1\n");
+       fprintf(fout,"goto(\n");
+       for(i=0; i<casecount; i++)
+               fprintf(fout,"%d,\n",30000+i);
+       fprintf(fout,"30999),nstr\n");
+       fprintf(fout,"30997 continue\n");
+       fprintf(fout,"}\nend\n");
+       }
+statistics(){
+       fprintf(errorf,"%d/%d nodes(%%e), %d/%d positions(%%p), %d/%d (%%n), %ld transitions\n",
+               tptr, treesize, nxtpos-positions, maxpos, stnum+1, nstates, rcount);
+       fprintf(errorf, ", %d/%d packed char classes(%%k)", pcptr-pchar, pchlen);
+       if(optim)fprintf(errorf,", %d/%d packed transitions(%%a)",nptr, ntrans);
+       fprintf(errorf, ", %d/%d output slots(%%o)", yytop, outsize);
+       putc('\n',errorf);
+       }
diff --git a/usr/src/cmd/lex/ldefs.c b/usr/src/cmd/lex/ldefs.c
new file mode 100644 (file)
index 0000000..f874c87
--- /dev/null
@@ -0,0 +1,162 @@
+# include <stdio.h>
+# define PP 1
+# ifdef unix
+
+# define CWIDTH 7
+# define CMASK 0177
+# define ASCII 1
+# endif
+
+# ifdef gcos
+# define CWIDTH 9
+# define CMASK 0777
+# define ASCII 1
+# endif
+
+# ifdef ibm
+# define CWIDTH 8
+# define CMASK 0377
+# define EBCDIC 1
+# endif
+
+# ifdef ASCII
+# define NCH 128
+# endif
+
+# ifdef EBCDIC
+# define NCH 256
+# endif
+
+
+# define TOKENSIZE 1000
+# define DEFSIZE 40
+# define DEFCHAR 1000
+# define STARTCHAR 100
+# define STARTSIZE 256
+# define CCLSIZE 1000
+# ifdef SMALL
+# define TREESIZE 600
+# define NTRANS 1500
+# define NSTATES 300
+# define MAXPOS 1500
+# define NOUTPUT 1500
+# endif
+
+# ifndef SMALL
+# define TREESIZE 1000
+# define NSTATES 500
+# define MAXPOS 2500
+# define NTRANS 2000
+# define NOUTPUT 3000
+# endif
+# define NACTIONS 100
+# define ALITTLEEXTRA 30
+
+# define RCCL NCH+90
+# define RNCCL NCH+91
+# define RSTR NCH+92
+# define RSCON NCH+93
+# define RNEWE NCH+94
+# define FINAL NCH+95
+# define RNULLS NCH+96
+# define RCAT NCH+97
+# define STAR NCH+98
+# define PLUS NCH+99
+# define QUEST NCH+100
+# define DIV NCH+101
+# define BAR NCH+102
+# define CARAT NCH+103
+# define S1FINAL NCH+104
+# define S2FINAL NCH+105
+
+# define DEFSECTION 1
+# define RULESECTION 2
+# define ENDSECTION 5
+# define TRUE 1
+# define FALSE 0
+
+# define PC 1
+# define PS 1
+
+# ifdef DEBUG
+# define LINESIZE 110
+extern int yydebug;
+extern int debug;              /* 1 = on */
+extern int charc;
+# endif
+
+# ifndef DEBUG
+# define freturn(s) s
+# endif
+
+extern int sargc;
+extern char **sargv;
+extern char buf[520];
+extern int ratfor;             /* 1 = ratfor, 0 = C */
+extern int yyline;             /* line number of file */
+extern int sect;
+extern int eof;
+extern int lgatflg;
+extern int divflg;
+extern int funcflag;
+extern int pflag;
+extern int casecount;
+extern int chset;      /* 1 = char set modified */
+extern FILE *fin, *fout, *fother, *errorf;
+extern int fptr;
+extern char *ratname, *cname;
+extern int prev;       /* previous input character */
+extern int pres;       /* present input character */
+extern int peek;       /* next input character */
+extern int *name;
+extern int *left;
+extern int *right;
+extern int *parent;
+extern char *nullstr;
+extern int tptr;
+extern char pushc[TOKENSIZE];
+extern char *pushptr;
+extern char slist[STARTSIZE];
+extern char *slptr;
+extern char **def, **subs, *dchar;
+extern char **sname, *schar;
+extern char *ccl;
+extern char *ccptr;
+extern char *dp, *sp;
+extern int dptr, sptr;
+extern char *bptr;             /* store input position */
+extern char *tmpstat;
+extern int count;
+extern int **foll;
+extern int *nxtpos;
+extern int *positions;
+extern int *gotof;
+extern int *nexts;
+extern char *nchar;
+extern int **state;
+extern int *sfall;             /* fallback state num */
+extern char *cpackflg;         /* true if state has been character packed */
+extern int *atable, aptr;
+extern int nptr;
+extern char symbol[NCH];
+extern char cindex[NCH];
+extern int xstate;
+extern int stnum;
+extern int ctable[];
+extern int ZCH;
+extern int ccount;
+extern char match[NCH];
+extern char extra[NACTIONS];
+extern char *pcptr, *pchar;
+extern int pchlen;
+extern int nstates, maxpos;
+extern int yytop;
+extern int report;
+extern int ntrans, treesize, outsize;
+extern long rcount;
+extern int optim;
+extern int *verify, *advance, *stoff;
+extern int scon;
+extern char *psave;
+extern char *calloc(), *myalloc();
+extern int buserr(), segviol();
diff --git a/usr/src/cmd/lex/lmain.c b/usr/src/cmd/lex/lmain.c
new file mode 100644 (file)
index 0000000..3ef43af
--- /dev/null
@@ -0,0 +1,227 @@
+# include "ldefs.c"
+# include "once.c"
+
+       /* lex [-[drcyvntf]] [file] ... [file] */
+
+       /* Copyright 1976, Bell Telephone Laboratories, Inc.,
+           written by Eric Schmidt, August 27, 1976   */
+
+main(argc,argv)
+  int argc;
+  char **argv; {
+       register int i;
+# ifdef DEBUG
+#include <signal.h>
+       signal(SIGBUS,buserr);
+       signal(SIGSEGV,segviol);
+# endif
+       while (argc > 1 && argv[1][0] == '-' ){
+               i = 0;
+               while(argv[1][++i]){
+                       switch (argv[1][i]){
+# ifdef DEBUG
+                               case 'd': debug++; break;
+                               case 'y': yydebug = TRUE; break;
+# endif
+                               case 'r': case 'R':
+                                       ratfor=TRUE; break;
+                               case 'c': case 'C':
+                                       ratfor=FALSE; break;
+                               case 't': case 'T':
+                                       fout = stdout;
+                                       errorf = stderr;
+                                       break;
+                               case 'v': case 'V':
+                                       report = 1;
+                                       break;
+                               case 'f': case 'F':
+                                       optim = FALSE;
+                                       break;
+                               case 'n': case 'N':
+                                       report = 0;
+                                       break;
+                               default:
+                                       warning("Unknown option %c",argv[1][i]);
+                               }
+                       }
+               argc--;
+               argv++;
+               }
+       sargc = argc;
+       sargv = argv;
+       if (argc > 1){
+               fin = fopen(argv[++fptr], "r");         /* open argv[1] */
+               sargc--;
+               sargv++;
+               }
+       else fin = stdin;
+       if(fin == NULL)
+               error ("Can't read input file %s",argc>1?argv[1]:"standard input");
+       gch();
+               /* may be gotten: def, subs, sname, schar, ccl, dchar */
+       get1core();
+               /* may be gotten: name, left, right, nullstr, parent */
+       scopy("INITIAL",sp);
+       sname[0] = sp;
+       sp += slength("INITIAL") + 1;
+       sname[1] = 0;
+       if(yyparse(0)) exit(1); /* error return code */
+               /* may be disposed of: def, subs, dchar */
+       free1core();
+               /* may be gotten: tmpstat, foll, positions, gotof, nexts, nchar, state, atable, sfall, cpackflg */
+       get2core();
+       ptail();
+       mkmatch();
+# ifdef DEBUG
+       if(debug) pccl();
+# endif
+       sect  = ENDSECTION;
+       if(tptr>0)cfoll(tptr-1);
+# ifdef DEBUG
+       if(debug)pfoll();
+# endif
+       cgoto();
+# ifdef DEBUG
+       if(debug){
+               printf("Print %d states:\n",stnum+1);
+               for(i=0;i<=stnum;i++)stprt(i);
+               }
+# endif
+               /* may be disposed of: positions, tmpstat, foll, state, name, left, right, parent, ccl, schar, sname */
+               /* may be gotten: verify, advance, stoff */
+       free2core();
+       get3core();
+       layout();
+               /* may be disposed of: verify, advance, stoff, nexts, nchar,
+                       gotof, atable, ccpackflg, sfall */
+# ifdef DEBUG
+       free3core();
+# endif
+       if (ZCH>NCH) cname="/usr/lib/lex/ebcform";
+       fother = fopen(ratfor?ratname:cname,"r");
+       if(fother == NULL)
+               error("Lex driver missing, file %s",ratfor?ratname:cname);
+       while ( (i=getc(fother)) != EOF)
+               putc(i,fout);
+
+       fclose(fother);
+       fclose(fout);
+       if(
+# ifdef DEBUG
+               debug   ||
+# endif
+                       report == 1)statistics();
+       fclose(stdout);
+       fclose(stderr);
+       exit(0);        /* success return code */
+       }
+get1core(){
+       register int i, val;
+       register char *p;
+ccptr =        ccl = myalloc(CCLSIZE,sizeof(*ccl));
+pcptr = pchar = myalloc(pchlen, sizeof(*pchar));
+       def = myalloc(DEFSIZE,sizeof(*def));
+       subs = myalloc(DEFSIZE,sizeof(*subs));
+dp =   dchar = myalloc(DEFCHAR,sizeof(*dchar));
+       sname = myalloc(STARTSIZE,sizeof(*sname));
+sp =   schar = myalloc(STARTCHAR,sizeof(*schar));
+       if(ccl == 0 || def == 0 || subs == 0 || dchar == 0 || sname == 0 || schar == 0)
+               error("Too little core to begin");
+       }
+free1core(){
+       cfree(def,DEFSIZE,sizeof(*def));
+       cfree(subs,DEFSIZE,sizeof(*subs));
+       cfree(dchar,DEFCHAR,sizeof(*dchar));
+       }
+get2core(){
+       register int i, val;
+       register char *p;
+       gotof = myalloc(nstates,sizeof(*gotof));
+       nexts = myalloc(ntrans,sizeof(*nexts));
+       nchar = myalloc(ntrans,sizeof(*nchar));
+       state = myalloc(nstates,sizeof(*state));
+       atable = myalloc(nstates,sizeof(*atable));
+       sfall = myalloc(nstates,sizeof(*sfall));
+       cpackflg = myalloc(nstates,sizeof(*cpackflg));
+       tmpstat = myalloc(tptr+1,sizeof(*tmpstat));
+       foll = myalloc(tptr+1,sizeof(*foll));
+nxtpos = positions = myalloc(maxpos,sizeof(*positions));
+       if(tmpstat == 0 || foll == 0 || positions == 0 ||
+               gotof == 0 || nexts == 0 || nchar == 0 || state == 0 || atable == 0 || sfall == 0 || cpackflg == 0 )
+               error("Too little core for state generation");
+       for(i=0;i<=tptr;i++)foll[i] = 0;
+       }
+free2core(){
+       cfree(positions,maxpos,sizeof(*positions));
+       cfree(tmpstat,tptr+1,sizeof(*tmpstat));
+       cfree(foll,tptr+1,sizeof(*foll));
+       cfree(name,treesize,sizeof(*name));
+       cfree(left,treesize,sizeof(*left));
+       cfree(right,treesize,sizeof(*right));
+       cfree(parent,treesize,sizeof(*parent));
+       cfree(nullstr,treesize,sizeof(*nullstr));
+       cfree(state,nstates,sizeof(*state));
+       cfree(sname,STARTSIZE,sizeof(*sname));
+       cfree(schar,STARTCHAR,sizeof(*schar));
+       cfree(ccl,CCLSIZE,sizeof(*ccl));
+       }
+get3core(){
+       register int i, val;
+       register char *p;
+       verify = myalloc(outsize,sizeof(*verify));
+       advance = myalloc(outsize,sizeof(*advance));
+       stoff = myalloc(stnum+2,sizeof(*stoff));
+       if(verify == 0 || advance == 0 || stoff == 0)
+               error("Too little core for final packing");
+       }
+# ifdef DEBUG
+free3core(){
+       cfree(advance,outsize,sizeof(*advance));
+       cfree(verify,outsize,sizeof(*verify));
+       cfree(stoff,stnum+1,sizeof(*stoff));
+       cfree(gotof,nstates,sizeof(*gotof));
+       cfree(nexts,ntrans,sizeof(*nexts));
+       cfree(nchar,ntrans,sizeof(*nchar));
+       cfree(atable,nstates,sizeof(*atable));
+       cfree(sfall,nstates,sizeof(*sfall));
+       cfree(cpackflg,nstates,sizeof(*cpackflg));
+       }
+# endif
+char *myalloc(a,b)
+  int a,b; {
+       register int i;
+       i = calloc(a, b);
+       if(i==0)
+               warning("OOPS - calloc returns a 0");
+       else if(i == -1){
+# ifdef DEBUG
+               warning("calloc returns a -1");
+# endif
+               return(0);
+               }
+       return(i);
+       }
+# ifdef DEBUG
+buserr(){
+       fflush(errorf);
+       fflush(fout);
+       fflush(stdout);
+       fprintf(errorf,"Bus error\n");
+       if(report == 1)statistics();
+       fflush(errorf);
+       }
+segviol(){
+       fflush(errorf);
+       fflush(fout);
+       fflush(stdout);
+       fprintf(errorf,"Segmentation violation\n");
+       if(report == 1)statistics();
+       fflush(errorf);
+       }
+# endif
+
+yyerror(s)
+char *s;
+{
+       fprintf(stderr, "%s\n", s);
+}
diff --git a/usr/src/cmd/lex/ncform b/usr/src/cmd/lex/ncform
new file mode 100644 (file)
index 0000000..8ca51b4
--- /dev/null
@@ -0,0 +1,179 @@
+int yylineno =1;
+# define YYU(x) x
+# define NLSTATE yyprevious=YYNEWLINE
+char yytext[YYLMAX];
+struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp;
+char yysbuf[YYLMAX];
+char *yysptr = yysbuf;
+int *yyfnd;
+extern struct yysvf *yyestate;
+int yyprevious = YYNEWLINE;
+yylook(){
+       register struct yysvf *yystate, **lsp;
+       register struct yywork *yyt;
+       struct yysvf *yyz;
+       int yych;
+       struct yywork *yyr;
+# ifdef LEXDEBUG
+       int debug;
+# endif
+       char *yylastch;
+       /* start off machines */
+# ifdef LEXDEBUG
+       debug = 0;
+# endif
+       if (!yymorfg)
+               yylastch = yytext;
+       else {
+               yymorfg=0;
+               yylastch = yytext+yyleng;
+               }
+       for(;;){
+               lsp = yylstate;
+               yyestate = yystate = yybgin;
+               if (yyprevious==YYNEWLINE) yystate++;
+               for (;;){
+# ifdef LEXDEBUG
+                       if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1);
+# endif
+                       yyt = yystate->yystoff;
+                       if(yyt == yycrank){             /* may not be any transitions */
+                               yyz = yystate->yyother;
+                               if(yyz == 0)break;
+                               if(yyz->yystoff == yycrank)break;
+                               }
+                       *yylastch++ = yych = input();
+               tryagain:
+# ifdef LEXDEBUG
+                       if(debug){
+                               fprintf(yyout,"char ");
+                               allprint(yych);
+                               putchar('\n');
+                               }
+# endif
+                       yyr = yyt;
+                       if ( (int)yyt > (int)yycrank){
+                               yyt = yyr + yych;
+                               if (yyt <= yytop && yyt->verify+yysvec == yystate){
+                                       if(yyt->advance+yysvec == YYLERR)       /* error transitions */
+                                               {unput(*--yylastch);break;}
+                                       *lsp++ = yystate = yyt->advance+yysvec;
+                                       goto contin;
+                                       }
+                               }
+# ifdef YYOPTIM
+                       else if((int)yyt < (int)yycrank) {              /* r < yycrank */
+                               yyt = yyr = yycrank+(yycrank-yyt);
+# ifdef LEXDEBUG
+                               if(debug)fprintf(yyout,"compressed state\n");
+# endif
+                               yyt = yyt + yych;
+                               if(yyt <= yytop && yyt->verify+yysvec == yystate){
+                                       if(yyt->advance+yysvec == YYLERR)       /* error transitions */
+                                               {unput(*--yylastch);break;}
+                                       *lsp++ = yystate = yyt->advance+yysvec;
+                                       goto contin;
+                                       }
+                               yyt = yyr + YYU(yymatch[yych]);
+# ifdef LEXDEBUG
+                               if(debug){
+                                       fprintf(yyout,"try fall back character ");
+                                       allprint(YYU(yymatch[yych]));
+                                       putchar('\n');
+                                       }
+# endif
+                               if(yyt <= yytop && yyt->verify+yysvec == yystate){
+                                       if(yyt->advance+yysvec == YYLERR)       /* error transition */
+                                               {unput(*--yylastch);break;}
+                                       *lsp++ = yystate = yyt->advance+yysvec;
+                                       goto contin;
+                                       }
+                               }
+                       if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){
+# ifdef LEXDEBUG
+                               if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1);
+# endif
+                               goto tryagain;
+                               }
+# endif
+                       else
+                               {unput(*--yylastch);break;}
+               contin:
+# ifdef LEXDEBUG
+                       if(debug){
+                               fprintf(yyout,"state %d char ",yystate-yysvec-1);
+                               allprint(yych);
+                               putchar('\n');
+                               }
+# endif
+                       ;
+                       }
+# ifdef LEXDEBUG
+               if(debug){
+                       fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1);
+                       allprint(yych);
+                       putchar('\n');
+                       }
+# endif
+               while (lsp-- > yylstate){
+                       *yylastch-- = 0;
+                       if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){
+                               yyolsp = lsp;
+                               if(yyextra[*yyfnd]){            /* must backup */
+                                       while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){
+                                               lsp--;
+                                               unput(*yylastch--);
+                                               }
+                                       }
+                               yyprevious = YYU(*yylastch);
+                               yylsp = lsp;
+                               yyleng = yylastch-yytext+1;
+                               yytext[yyleng] = 0;
+# ifdef LEXDEBUG
+                               if(debug){
+                                       fprintf(yyout,"\nmatch ");
+                                       sprint(yytext);
+                                       fprintf(yyout," action %d\n",*yyfnd);
+                                       }
+# endif
+                               return(*yyfnd++);
+                               }
+                       unput(*yylastch);
+                       }
+               if (yytext[0] == 0  /* && feof(yyin) */)
+                       {
+                       yysptr=yysbuf;
+                       return(0);
+                       }
+               yyprevious = yytext[0] = input();
+               if (yyprevious>0)
+                       output(yyprevious);
+               yylastch=yytext;
+# ifdef LEXDEBUG
+               if(debug)putchar('\n');
+# endif
+               }
+       }
+yyback(p, m)
+       int *p;
+{
+if (p==0) return(0);
+while (*p)
+       {
+       if (*p++ == m)
+               return(1);
+       }
+return(0);
+}
+       /* the following are only used in the lex library */
+yyinput(){
+       return(input());
+       }
+yyoutput(c)
+  int c; {
+       output(c);
+       }
+yyunput(c)
+   int c; {
+       unput(c);
+       }
diff --git a/usr/src/cmd/lex/once.c b/usr/src/cmd/lex/once.c
new file mode 100644 (file)
index 0000000..f9b5249
--- /dev/null
@@ -0,0 +1,130 @@
+       /* because of external definitions, this code should occur only once */
+# ifdef ASCII
+int ctable[2*NCH] = {
+  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+100,101,102,103,104,105,106,107,108,109,
+110,111,112,113,114,115,116,117,118,119,
+120,121,122,123,124,125,126,127};
+# endif
+# ifdef EBCDIC
+int ctable[2*NCH] = {
+  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+100,101,102,103,104,105,106,107,108,109,
+110,111,112,113,114,115,116,117,118,119,
+120,121,122,123,124,125,126,127,128,129,
+130,131,132,133,134,135,136,137,138,139,
+140,141,142,143,144,145,146,147,148,149,
+150,151,152,153,154,155,156,157,158,159,
+160,161,162,163,164,165,166,167,168,169,
+170,171,172,173,174,175,176,177,178,179,
+180,181,182,183,184,185,186,187,188,189,
+190,191,192,193,194,195,196,197,198,199,
+200,201,202,203,204,205,206,207,208,209,
+210,211,212,213,214,215,216,217,218,219,
+220,221,222,223,224,225,226,227,228,229,
+230,231,232,233,234,235,236,237,238,239,
+240,241,242,243,244,245,246,247,248,249,
+250,251,252,253,254,255};
+# endif
+int ZCH = NCH;
+FILE *fout = NULL, *errorf = {stdout};
+int sect = DEFSECTION;
+int prev = '\n';       /* previous input character */
+int pres = '\n';       /* present input character */
+int peek = '\n';       /* next input character */
+char *pushptr = pushc;
+char *slptr = slist;
+
+# if (unix || ibm)
+char *cname = "/usr/lib/lex/ncform";
+char *ratname = "/usr/lib/lex/nrform";
+# endif
+
+# ifdef gcos
+char *cname = "pounce/lexcform";
+char *ratname = "pounce/lexrform";
+# endif
+int ccount = 1;
+int casecount = 1;
+int aptr = 1;
+int nstates = NSTATES, maxpos = MAXPOS;
+int treesize = TREESIZE, ntrans = NTRANS;
+int yytop;
+int outsize = NOUTPUT;
+int sptr = 1;
+int optim = TRUE;
+int report = 2;
+int debug;             /* 1 = on */
+int charc;
+int sargc;
+char **sargv;
+char buf[520];
+int ratfor;            /* 1 = ratfor, 0 = C */
+int yyline;            /* line number of file */
+int eof;
+int lgatflg;
+int divflg;
+int funcflag;
+int pflag;
+int chset;     /* 1 = char set modified */
+FILE *fin, *fother;
+int fptr;
+int *name;
+int *left;
+int *right;
+int *parent;
+char *nullstr;
+int tptr;
+char pushc[TOKENSIZE];
+char slist[STARTSIZE];
+char **def, **subs, *dchar;
+char **sname, *schar;
+char *ccl;
+char *ccptr;
+char *dp, *sp;
+int dptr;
+char *bptr;            /* store input position */
+char *tmpstat;
+int count;
+int **foll;
+int *nxtpos;
+int *positions;
+int *gotof;
+int *nexts;
+char *nchar;
+int **state;
+int *sfall;            /* fallback state num */
+char *cpackflg;                /* true if state has been character packed */
+int *atable;
+int nptr;
+char symbol[NCH];
+char cindex[NCH];
+int xstate;
+int stnum;
+char match[NCH];
+char extra[NACTIONS];
+char *pchar, *pcptr;
+int pchlen = TOKENSIZE;
+ long rcount;
+int *verify, *advance, *stoff;
+int scon;
+char *psave;
+int buserr(), segviol();
diff --git a/usr/src/cmd/lex/parser.y b/usr/src/cmd/lex/parser.y
new file mode 100644 (file)
index 0000000..81df2d0
--- /dev/null
@@ -0,0 +1,710 @@
+%token CHAR CCL NCCL STR DELIM SCON ITER NEWE NULLS
+%left SCON '/' NEWE
+%left '|'
+%left '$' '^'
+%left CHAR CCL NCCL '(' '.' STR NULLS
+%left ITER
+%left CAT
+%left '*' '+' '?'
+
+%{
+# include "ldefs.c"
+%}
+%%
+%{
+int i;
+int j,k;
+int g;
+char *p;
+%}
+acc    :       lexinput
+       ={      
+# ifdef DEBUG
+               if(debug) sect2dump();
+# endif
+       }
+       ;
+lexinput:      defns delim prods end
+       |       defns delim end
+       ={
+               if(!funcflag)phead2();
+               funcflag = TRUE;
+       }
+       | error
+       ={
+# ifdef DEBUG
+               if(debug) {
+                       sect1dump();
+                       sect2dump();
+                       }
+# endif
+               }
+       ;
+end:           delim | ;
+defns: defns STR STR
+       ={      scopy($2,dp);
+               def[dptr] = dp;
+               dp += slength($2) + 1;
+               scopy($3,dp);
+               subs[dptr++] = dp;
+               if(dptr >= DEFSIZE)
+                       error("Too many definitions");
+               dp += slength($3) + 1;
+               if(dp >= dchar+DEFCHAR)
+                       error("Definitions too long");
+               subs[dptr]=def[dptr]=0; /* for lookup - require ending null */
+       }
+       |
+       ;
+delim: DELIM
+       ={
+# ifdef DEBUG
+               if(sect == DEFSECTION && debug) sect1dump();
+# endif
+               sect++;
+               }
+       ;
+prods: prods pr
+       ={      $$ = mn2(RNEWE,$1,$2);
+               }
+       |       pr
+       ={      $$ = $1;}
+       ;
+pr:    r NEWE
+       ={
+               if(divflg == TRUE)
+                       i = mn1(S1FINAL,casecount);
+               else i = mn1(FINAL,casecount);
+               $$ = mn2(RCAT,$1,i);
+               divflg = FALSE;
+               casecount++;
+               }
+       | error NEWE
+       ={
+# ifdef DEBUG
+               if(debug) sect2dump();
+# endif
+               }
+r:     CHAR
+       ={      $$ = mn0($1); }
+       | STR
+       ={
+               p = $1;
+               i = mn0(*p++);
+               while(*p)
+                       i = mn2(RSTR,i,*p++);
+               $$ = i;
+               }
+       | '.'
+       ={      symbol['\n'] = 0;
+               if(psave == FALSE){
+                       p = ccptr;
+                       psave = ccptr;
+                       for(i=1;i<'\n';i++){
+                               symbol[i] = 1;
+                               *ccptr++ = i;
+                               }
+                       for(i='\n'+1;i<NCH;i++){
+                               symbol[i] = 1;
+                               *ccptr++ = i;
+                               }
+                       *ccptr++ = 0;
+                       if(ccptr > ccl+CCLSIZE)
+                               error("Too many large character classes");
+                       }
+               else
+                       p = psave;
+               $$ = mn1(RCCL,p);
+               cclinter(1);
+               }
+       | CCL
+       ={      $$ = mn1(RCCL,$1); }
+       | NCCL
+       ={      $$ = mn1(RNCCL,$1); }
+       | r '*'
+       ={      $$ = mn1(STAR,$1); }
+       | r '+'
+       ={      $$ = mn1(PLUS,$1); }
+       | r '?'
+       ={      $$ = mn1(QUEST,$1); }
+       | r '|' r
+       ={      $$ = mn2(BAR,$1,$3); }
+       | r r %prec CAT
+       ={      $$ = mn2(RCAT,$1,$2); }
+       | r '/' r
+       ={      if(!divflg){
+                       j = mn1(S2FINAL,-casecount);
+                       i = mn2(RCAT,$1,j);
+                       $$ = mn2(DIV,i,$3);
+                       }
+               else {
+                       $$ = mn2(RCAT,$1,$3);
+                       warning("Extra slash removed");
+                       }
+               divflg = TRUE;
+               }
+       | r ITER ',' ITER '}'
+       ={      if($2 > $4){
+                       i = $2;
+                       $2 = $4;
+                       $4 = i;
+                       }
+               if($4 <= 0)
+                       warning("Iteration range must be positive");
+               else {
+                       j = $1;
+                       for(k = 2; k<=$2;k++)
+                               j = mn2(RCAT,j,dupl($1));
+                       for(i = $2+1; i<=$4; i++){
+                               g = dupl($1);
+                               for(k=2;k<=i;k++)
+                                       g = mn2(RCAT,g,dupl($1));
+                               j = mn2(BAR,j,g);
+                               }
+                       $$ = j;
+                       }
+       }
+       | r ITER '}'
+       ={
+               if($2 < 0)warning("Can't have negative iteration");
+               else if($2 == 0) $$ = mn0(RNULLS);
+               else {
+                       j = $1;
+                       for(k=2;k<=$2;k++)
+                               j = mn2(RCAT,j,dupl($1));
+                       $$ = j;
+                       }
+               }
+       | r ITER ',' '}'
+       ={
+                               /* from n to infinity */
+               if($2 < 0)warning("Can't have negative iteration");
+               else if($2 == 0) $$ = mn1(STAR,$1);
+               else if($2 == 1)$$ = mn1(PLUS,$1);
+               else {          /* >= 2 iterations minimum */
+                       j = $1;
+                       for(k=2;k<$2;k++)
+                               j = mn2(RCAT,j,dupl($1));
+                       k = mn1(PLUS,dupl($1));
+                       $$ = mn2(RCAT,j,k);
+                       }
+               }
+       | SCON r
+       ={      $$ = mn2(RSCON,$2,$1); }
+       | '^' r
+       ={      $$ = mn1(CARAT,$2); }
+       | r '$'
+       ={      i = mn0('\n');
+               if(!divflg){
+                       j = mn1(S2FINAL,-casecount);
+                       k = mn2(RCAT,$1,j);
+                       $$ = mn2(DIV,k,i);
+                       }
+               else $$ = mn2(RCAT,$1,i);
+               divflg = TRUE;
+               }
+       | '(' r ')'
+       ={      $$ = $2; }
+       |       NULLS
+       ={      $$ = mn0(RNULLS); }
+       ;
+%%
+yylex(){
+       register char *p;
+       register int c, i;
+       char  *t, *xp;
+       int n, j, k, x;
+       static int sectbegin;
+       static char token[TOKENSIZE];
+       static int iter;
+
+# ifdef DEBUG
+       yylval = 0;
+# endif
+
+       if(sect == DEFSECTION) {                /* definitions section */
+               while(!eof) {
+                       if(prev == '\n'){               /* next char is at beginning of line */
+                               getl(p=buf);
+                               switch(*p){
+                               case '%':
+                                       switch(c= *(p+1)){
+                                       case '%':
+                                               lgate();
+                                               if(!ratfor)fprintf(fout,"# ");
+                                               fprintf(fout,"define YYNEWLINE %d\n",ctable['\n']);
+                                               if(!ratfor)fprintf(fout,"yylex(){\nint nstr; extern int yyprevious;\n");
+                                               sectbegin = TRUE;
+                                               i = treesize*(sizeof(*name)+sizeof(*left)+
+                                                       sizeof(*right)+sizeof(*nullstr)+sizeof(*parent))+ALITTLEEXTRA;
+                                               c = myalloc(i,1);
+                                               if(c == 0)
+                                                       error("Too little core for parse tree");
+                                               p = c;
+                                               cfree(p,i,1);
+                                               name = myalloc(treesize,sizeof(*name));
+                                               left = myalloc(treesize,sizeof(*left));
+                                               right = myalloc(treesize,sizeof(*right));
+                                               nullstr = myalloc(treesize,sizeof(*nullstr));
+                                               parent = myalloc(treesize,sizeof(*parent));
+                                               if(name == 0 || left == 0 || right == 0 || parent == 0 || nullstr == 0)
+                                                       error("Too little core for parse tree");
+                                               return(freturn(DELIM));
+                                       case 'p': case 'P':     /* has overridden number of positions */
+                                               while(*p && !digit(*p))p++;
+                                               maxpos = siconv(p);
+# ifdef DEBUG
+                                               if (debug) printf("positions (%%p) now %d\n",maxpos);
+# endif
+                                               if(report == 2)report = 1;
+                                               continue;
+                                       case 'n': case 'N':     /* has overridden number of states */
+                                               while(*p && !digit(*p))p++;
+                                               nstates = siconv(p);
+# ifdef DEBUG
+                                               if(debug)printf( " no. states (%%n) now %d\n",nstates);
+# endif
+                                               if(report == 2)report = 1;
+                                               continue;
+                                       case 'e': case 'E':             /* has overridden number of tree nodes */
+                                               while(*p && !digit(*p))p++;
+                                               treesize = siconv(p);
+# ifdef DEBUG
+                                               if (debug) printf("treesize (%%e) now %d\n",treesize);
+# endif
+                                               if(report == 2)report = 1;
+                                               continue;
+                                       case 'o': case 'O':
+                                               while (*p && !digit(*p))p++;
+                                               outsize = siconv(p);
+                                               if (report ==2) report=1;
+                                               continue;
+                                       case 'a': case 'A':             /* has overridden number of transitions */
+                                               while(*p && !digit(*p))p++;
+                                               if(report == 2)report = 1;
+                                               ntrans = siconv(p);
+# ifdef DEBUG
+                                               if (debug)printf("N. trans (%%a) now %d\n",ntrans);
+# endif
+                                               continue;
+                                       case 'k': case 'K': /* overriden packed char classes */
+                                               while (*p && !digit(*p))p++;
+                                               if (report==2) report=1;
+                                               cfree(pchar, pchlen, sizeof(*pchar));
+                                               pchlen = siconv(p);
+# ifdef DEBUG
+                                               if (debug) printf( "Size classes (%%k) now %d\n",pchlen);
+# endif
+                                               pchar=pcptr=myalloc(pchlen, sizeof(*pchar));
+                                               continue;
+                                       case 't': case 'T':     /* character set specifier */
+                                               ZCH = atoi(p+2);
+                                               if (ZCH < NCH) ZCH = NCH;
+                                               if (ZCH > 2*NCH) error("ch table needs redeclaration");
+                                               chset = TRUE;
+                                               for(i = 0; i<ZCH; i++)
+                                                       ctable[i] = 0;
+                                               while(getl(p) && scomp(p,"%T") != 0 && scomp(p,"%t") != 0){
+                                                       if((n = siconv(p)) <= 0 || n > ZCH){
+                                                               warning("Character value %d out of range",n);
+                                                               continue;
+                                                               }
+                                                       while(!space(*p) && *p) p++;
+                                                       while(space(*p)) p++;
+                                                       t = p;
+                                                       while(*t){
+                                                               c = ctrans(&t);
+                                                               if(ctable[c]){
+                                                                       if (printable(c))
+                                                                               warning("Character '%c' used twice",c);
+                                                                       else
+                                                                               warning("Character %o used twice",c);
+                                                                       }
+                                                               else ctable[c] = n;
+                                                               t++;
+                                                               }
+                                                       p = buf;
+                                                       }
+                                               {
+                                               char chused[2*NCH]; int kr;
+                                               for(i=0; i<ZCH; i++)
+                                                       chused[i]=0;
+                                               for(i=0; i<NCH; i++)
+                                                       chused[ctable[i]]=1;
+                                               for(kr=i=1; i<NCH; i++)
+                                                       if (ctable[i]==0)
+                                                               {
+                                                               while (chused[kr] == 0)
+                                                                       kr++;
+                                                               ctable[i]=kr;
+                                                               chused[kr]=1;
+                                                               }
+                                               }
+                                               lgate();
+                                               continue;
+                                       case 'r': case 'R':
+                                               c = 'r';
+                                       case 'c': case 'C':
+                                               if(lgatflg)
+                                                       error("Too late for language specifier");
+                                               ratfor = (c == 'r');
+                                               continue;
+                                       case '{':
+                                               lgate();
+                                               while(getl(p) && scomp(p,"%}") != 0)
+                                                       fprintf(fout, "%s\n",p);
+                                               if(p[0] == '%') continue;
+                                               error("Premature eof");
+                                       case 's': case 'S':             /* start conditions */
+                                               lgate();
+                                               while(*p && index(*p," \t,") < 0) p++;
+                                               n = TRUE;
+                                               while(n){
+                                                       while(*p && index(*p," \t,") >= 0) p++;
+                                                       t = p;
+                                                       while(*p && index(*p," \t,") < 0)p++;
+                                                       if(!*p) n = FALSE;
+                                                       *p++ = 0;
+                                                       if (*t == 0) continue;
+                                                       i = sptr*2;
+                                                       if(!ratfor)fprintf(fout,"# ");
+                                                       fprintf(fout,"define %s %d\n",t,i);
+                                                       scopy(t,sp);
+                                                       sname[sptr++] = sp;
+                                                       sname[sptr] = 0;        /* required by lookup */
+                                                       if(sptr >= STARTSIZE)
+                                                               error("Too many start conditions");
+                                                       sp += slength(sp) + 1;
+                                                       if(sp >= schar+STARTCHAR)
+                                                               error("Start conditions too long");
+                                                       }
+                                               continue;
+                                       default:
+                                               warning("Invalid request %s",p);
+                                               continue;
+                                               }       /* end of switch after seeing '%' */
+                               case ' ': case '\t':            /* must be code */
+                                       lgate();
+                                       fprintf(fout, "%s\n",p);
+                                       continue;
+                               default:                /* definition */
+                                       while(*p && !space(*p)) p++;
+                                       if(*p == 0)
+                                               continue;
+                                       prev = *p;
+                                       *p = 0;
+                                       bptr = p+1;
+                                       yylval = buf;
+                                       if(digit(buf[0]))
+                                               warning("Substitution strings may not begin with digits");
+                                       return(freturn(STR));
+                                       }
+                               }
+                       /* still sect 1, but prev != '\n' */
+                       else {
+                               p = bptr;
+                               while(*p && space(*p)) p++;
+                               if(*p == 0)
+                                       warning("No translation given - null string assumed");
+                               scopy(p,token);
+                               yylval = token;
+                               prev = '\n';
+                               return(freturn(STR));
+                               }
+                       }
+               /* end of section one processing */
+               }
+       else if(sect == RULESECTION){           /* rules and actions */
+               while(!eof){
+                       switch(c=gch()){
+                       case '\0':
+                               return(freturn(0));
+                       case '\n':
+                               if(prev == '\n') continue;
+                               x = NEWE;
+                               break;
+                       case ' ':
+                       case '\t':
+                               if(sectbegin == TRUE){
+                                       cpyact();
+                                       while((c=gch()) && c != '\n');
+                                       continue;
+                                       }
+                               if(!funcflag)phead2();
+                               funcflag = TRUE;
+                               if(ratfor)fprintf(fout,"%d\n",30000+casecount);
+                               else fprintf(fout,"case %d:\n",casecount);
+                               if(cpyact()){
+                                       if(ratfor)fprintf(fout,"goto 30997\n");
+                                       else fprintf(fout,"break;\n");
+                                       }
+                               while((c=gch()) && c != '\n');
+                               if(peek == ' ' || peek == '\t' || sectbegin == TRUE){
+                                       warning("Executable statements should occur right after %%");
+                                       continue;
+                                       }
+                               x = NEWE;
+                               break;
+                       case '%':
+                               if(prev != '\n') goto character;
+                               if(peek == '{'){        /* included code */
+                                       getl(buf);
+                                       while(!eof && getl(buf) && scomp("%}",buf) != 0)
+                                               fprintf(fout,"%s\n",buf);
+                                       continue;
+                                       }
+                               if(peek == '%'){
+                                       c = gch();
+                                       c = gch();
+                                       x = DELIM;
+                                       break;
+                                       }
+                               goto character;
+                       case '|':
+                               if(peek == ' ' || peek == '\t' || peek == '\n'){
+                                       if(ratfor)fprintf(fout,"%d\n",30000+casecount++);
+                                       else fprintf(fout,"case %d:\n",casecount++);
+                                       continue;
+                                       }
+                               x = '|';
+                               break;
+                       case '$':
+                               if(peek == '\n' || peek == ' ' || peek == '\t' || peek == '|' || peek == '/'){
+                                       x = c;
+                                       break;
+                                       }
+                               goto character;
+                       case '^':
+                               if(prev != '\n' && scon != TRUE) goto character;        /* valid only at line begin */
+                               x = c;
+                               break;
+                       case '?':
+                       case '+':
+                       case '.':
+                       case '*':
+                       case '(':
+                       case ')':
+                       case ',':
+                       case '/':
+                               x = c;
+                               break;
+                       case '}':
+                               iter = FALSE;
+                               x = c;
+                               break;
+                       case '{':       /* either iteration or definition */
+                               if(digit(c=gch())){     /* iteration */
+                                       iter = TRUE;
+                               ieval:
+                                       i = 0;
+                                       while(digit(c)){
+                                               token[i++] = c;
+                                               c = gch();
+                                               }
+                                       token[i] = 0;
+                                       yylval = siconv(token);
+                                       munput('c',c);
+                                       x = ITER;
+                                       break;
+                                       }
+                               else {          /* definition */
+                                       i = 0;
+                                       while(c && c!='}'){
+                                               token[i++] = c;
+                                               c = gch();
+                                               }
+                                       token[i] = 0;
+                                       i = lookup(token,def);
+                                       if(i < 0)
+                                               warning("Definition %s not found",token);
+                                       else
+                                               munput('s',subs[i]);
+                                       continue;
+                                       }
+                       case '<':               /* start condition ? */
+                               if(prev != '\n')                /* not at line begin, not start */
+                                       goto character;
+                               t = slptr;
+                               do {
+                                       i = 0;
+                                       c = gch();
+                                       while(c != ',' && c && c != '>'){
+                                               token[i++] = c;
+                                               c = gch();
+                                               }
+                                       token[i] = 0;
+                                       if(i == 0)
+                                               goto character;
+                                       i = lookup(token,sname);
+                                       if(i < 0) {
+                                               warning("Undefined start condition %s",token);
+                                               continue;
+                                               }
+                                       *slptr++ = i+1;
+                                       } while(c && c != '>');
+                               *slptr++ = 0;
+                               /* check if previous value re-usable */
+                               for (xp=slist; xp<t; )
+                                       {
+                                       if (strcmp(xp, t)==0)
+                                               break;
+                                       while (*xp++);
+                                       }
+                               if (xp<t)
+                                       {
+                                       /* re-use previous pointer to string */
+                                       slptr=t;
+                                       t=xp;
+                                       }
+                               if(slptr > slist+STARTSIZE)             /* note not packed ! */
+                                       error("Too many start conditions used");
+                               yylval = t;
+                               x = SCON;
+                               break;
+                       case '"':
+                               i = 0;
+                               while((c=gch()) && c != '"' && c != '\n'){
+                                       if(c == '\\') c = usescape(c=gch());
+                                       token[i++] = c;
+                                       if(i > TOKENSIZE){
+                                               warning("String too long");
+                                               i = TOKENSIZE-1;
+                                               break;
+                                               }
+                                       }
+                               if(c == '\n') {
+                                       yyline--;
+                                       warning("Non-terminated string");
+                                       yyline++;
+                                       }
+                               token[i] = 0;
+                               if(i == 0)x = NULLS;
+                               else if(i == 1){
+                                       yylval = token[0];
+                                       x = CHAR;
+                                       }
+                               else {
+                                       yylval = token;
+                                       x = STR;
+                                       }
+                               break;
+                       case '[':
+                               for(i=1;i<NCH;i++) symbol[i] = 0;
+                               x = CCL;
+                               if((c = gch()) == '^'){
+                                       x = NCCL;
+                                       c = gch();
+                                       }
+                               while(c != ']' && c){
+                                       if(c == '\\') c = usescape(c=gch());
+                                       symbol[c] = 1;
+                                       j = c;
+                                       if((c=gch()) == '-' && peek != ']'){            /* range specified */
+                                               c = gch();
+                                               if(c == '\\') c = usescape(c=gch());
+                                               k = c;
+                                               if(j > k) {
+                                                       n = j;
+                                                       j = k;
+                                                       k = n;
+                                                       }
+                                               if(!(('A' <= j && k <= 'Z') ||
+                                                    ('a' <= j && k <= 'z') ||
+                                                    ('0' <= j && k <= '9')))
+                                                       warning("Non-portable Character Class");
+                                               for(n=j+1;n<=k;n++)
+                                                       symbol[n] = 1;          /* implementation dependent */
+                                               c = gch();
+                                               }
+                                       }
+                               /* try to pack ccl's */
+                               i = 0;
+                               for(j=0;j<NCH;j++)
+                                       if(symbol[j])token[i++] = j;
+                               token[i] = 0;
+                               p = ccptr;
+                               if(optim){
+                                       p = ccl;
+                                       while(p <ccptr && scomp(token,p) != 0)p++;
+                                       }
+                               if(p < ccptr)   /* found it */
+                                       yylval = p;
+                               else {
+                                       yylval = ccptr;
+                                       scopy(token,ccptr);
+                                       ccptr += slength(token) + 1;
+                                       if(ccptr >= ccl+CCLSIZE)
+                                               error("Too many large character classes");
+                                       }
+                               cclinter(x==CCL);
+                               break;
+                       case '\\':
+                               c = usescape(c=gch());
+                       default:
+                       character:
+                               if(iter){       /* second part of an iteration */
+                                       iter = FALSE;
+                                       if('0' <= c && c <= '9')
+                                               goto ieval;
+                                       }
+                               if(alpha(peek)){
+                                       i = 0;
+                                       yylval = token;
+                                       token[i++] = c;
+                                       while(alpha(peek))
+                                               token[i++] = gch();
+                                       if(peek == '?' || peek == '*' || peek == '+')
+                                               munput('c',token[--i]);
+                                       token[i] = 0;
+                                       if(i == 1){
+                                               yylval = token[0];
+                                               x = CHAR;
+                                               }
+                                       else x = STR;
+                                       }
+                               else {
+                                       yylval = c;
+                                       x = CHAR;
+                                       }
+                               }
+                       scon = FALSE;
+                       if(x == SCON)scon = TRUE;
+                       sectbegin = FALSE;
+                       return(freturn(x));
+                       }
+               }
+       /* section three */
+       ptail();
+# ifdef DEBUG
+       if(debug)
+               fprintf(fout,"\n/*this comes from section three - debug */\n");
+# endif
+       while(getl(buf) && !eof)
+               fprintf(fout,"%s\n",buf);
+       return(freturn(0));
+       }
+/* end of yylex */
+# ifdef DEBUG
+freturn(i)
+  int i; {
+       if(yydebug) {
+               printf("now return ");
+               if(i < NCH) allprint(i);
+               else printf("%d",i);
+               printf("   yylval = ");
+               switch(i){
+                       case STR: case CCL: case NCCL:
+                               strpt(yylval);
+                               break;
+                       case CHAR:
+                               allprint(yylval);
+                               break;
+                       default:
+                               printf("%d",yylval);
+                               break;
+                       }
+               putchar('\n');
+               }
+       return(i);
+       }
+# endif
diff --git a/usr/src/cmd/lex/sub1.c b/usr/src/cmd/lex/sub1.c
new file mode 100644 (file)
index 0000000..45dc1a9
--- /dev/null
@@ -0,0 +1,683 @@
+# include "ldefs.c"
+char *
+getl(p)        /* return next line of input, throw away trailing '\n' */
+       /* returns 0 if eof is had immediately */
+  char *p;
+       {
+       register int c;
+       register char *s, *t;
+       t = s = p;
+       while(((c = gch()) != 0) && c != '\n')
+               *t++ = c;
+       *t = 0;
+       if(c == 0 && s == t) return(0);
+       prev = '\n';
+       pres = '\n';
+       return(s);
+       }
+space(ch)
+       {
+       switch(ch)
+               {
+               case ' ':
+               case '\t':
+               case '\n':
+                       return(1);
+               }
+       return(0);
+       }
+
+digit(c)
+{
+       return(c>='0' && c <= '9');
+}
+error(s,p,d)
+       {
+       if(!eof)fprintf(errorf,"%d: ",yyline);
+       fprintf(errorf,"(Error) ");
+       fprintf(errorf,s,p,d);
+       putc('\n',errorf);
+# ifdef DEBUG
+       if(debug && sect != ENDSECTION) {
+               sect1dump();
+               sect2dump();
+       }
+# endif
+       if(
+# ifdef DEBUG
+               debug ||
+# endif
+               report == 1) statistics();
+       exit(1);        /* error return code */
+       }
+
+warning(s,p,d)
+       {
+       if(!eof)fprintf(errorf,"%d: ",yyline);
+       fprintf(errorf,"(Warning) ");
+       fprintf(errorf,s,p,d);
+       putc('\n',errorf);
+       fflush(errorf);
+       fflush(fout);
+       fflush(stdout);
+       }
+index(a,s)
+       char *s;
+{
+       register int k;
+       for(k=0; s[k]; k++)
+               if (s[k]== a)
+                       return(k);
+       return(-1);
+       }
+
+alpha(c)
+  int c; {
+# ifdef ASCII
+return('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z');
+# endif
+# ifdef EBCDIC
+return(index(c,"abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") >= 0);
+# endif
+}
+printable(c)
+{
+# ifdef ASCII
+return( c>040 && c < 0177);
+# endif
+# ifdef EBCDIC
+return(index(c, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,;:><+*)('&%!-=\"")>=0);
+# endif
+}
+lgate()
+{
+       char fname[20];
+       if (lgatflg) return;
+       lgatflg=1;
+       if(fout == NULL){
+               sprintf(fname, "lex.yy.%c", ratfor ? 'r' : 'c' );
+               fout = fopen(fname, "w");
+               }
+       if(fout == NULL) error("Can't open %s",fname);
+       if(ratfor) fprintf( fout, "#\n");
+       phead1();
+       }
+/* scopy(ptr to str, ptr to str) - copy first arg str to second */
+/* returns ptr to second arg */
+scopy(s,t)
+  char *s, *t; {
+       register char *i;
+       i = t;
+       while(*i++ = *s++);
+       return;
+       }
+siconv(t)      /* convert string t, return integer value */
+  char *t; {
+       register int i,sw;
+       register char *s;
+       s = t;
+       while(!(('0' <= *s && *s <= '9') || *s == '-') && *s) s++;
+       sw = 0;
+       if(*s == '-'){  /* neg */
+               sw = 1;
+               s++;
+               }
+       i = 0;
+       while('0' <= *s && *s <= '9')
+               i = i * 10 + (*(s++)-'0');
+       return(sw ? -i : i);
+       }
+/* slength(ptr to str) - return integer length of string arg */
+/* excludes '\0' terminator */
+slength(s)
+  char *s; {
+       register int n;
+       register char *t;
+       t = s;
+       for (n = 0; *t++; n++);
+       return(n);
+       }
+/* scomp(x,y) - return -1 if x < y,
+               0 if x == y,
+               return 1 if x > y, all lexicographically */
+scomp(x,y)
+  char *x,*y; {
+       register char *a,*d;
+       a = x;
+       d = y;
+       while(*a || *d){
+               if(*a > *d)
+                       return(1);      /* greater */
+               if(*a < *d)
+                       return(-1);     /* less */
+               a++;
+               d++;
+               }
+       return(0);      /* equal */
+       }
+ctrans(ss)
+       char **ss;
+{
+       register int c, k;
+       if ((c = **ss) != '\\')
+               return(c);
+       switch(c= *++*ss)
+       {
+       case 'n': c = '\n'; break;
+       case 't': c = '\t'; break;
+       case 'r': c = '\r'; break;
+       case 'b': c = '\b'; break;
+       case 'f': c = 014; break;               /* form feed for ascii */
+       case '\\': c = '\\'; break;
+       case '0': case '1': case '2': case '3':
+       case '4': case '5': case '6': case '7':
+               c -= '0';
+               while ((k = *(*ss+1)) >= '0' && k <= '7')
+                       {
+                       c = c*8 + k - '0';
+                       (*ss)++;
+                       }
+               break;
+       }
+       return(c);
+}
+cclinter(sw)
+  int sw; {
+               /* sw = 1 ==> ccl */
+       register int i, j, k;
+       int m;
+       if(!sw){                /* is NCCL */
+               for(i=1;i<NCH;i++)
+                       symbol[i] ^= 1;                 /* reverse value */
+               }
+       for(i=1;i<NCH;i++)
+               if(symbol[i]) break;
+       if(i >= NCH) return;
+       i = cindex[i];
+       /* see if ccl is already in our table */
+       j = 0;
+       if(i){
+               for(j=1;j<NCH;j++){
+                       if((symbol[j] && cindex[j] != i) ||
+                          (!symbol[j] && cindex[j] == i)) break;
+                       }
+               }
+       if(j >= NCH) return;            /* already in */
+       m = 0;
+       k = 0;
+       for(i=1;i<NCH;i++)
+               if(symbol[i]){
+                       if(!cindex[i]){
+                               cindex[i] = ccount;
+                               symbol[i] = 0;
+                               m = 1;
+                               }
+                       else k = 1;
+                       }
+                       /* m == 1 implies last value of ccount has been used */
+       if(m)ccount++;
+       if(k == 0) return;      /* is now in as ccount wholly */
+       /* intersection must be computed */
+       for(i=1;i<NCH;i++){
+               if(symbol[i]){
+                       m = 0;
+                       j = cindex[i];  /* will be non-zero */
+                       for(k=1;k<NCH;k++){
+                               if(cindex[k] == j){
+                                       if(symbol[k]) symbol[k] = 0;
+                                       else {
+                                               cindex[k] = ccount;
+                                               m = 1;
+                                               }
+                                       }
+                               }
+                       if(m)ccount++;
+                       }
+               }
+       return;
+       }
+usescape(c)
+  int c; {
+       register char d;
+       switch(c){
+       case 'n': c = '\n'; break;
+       case 'r': c = '\r'; break;
+       case 't': c = '\t'; break;
+       case 'b': c = '\b'; break;
+       case 'f': c = 014; break;               /* form feed for ascii */
+       case '0': case '1': case '2': case '3':
+       case '4': case '5': case '6': case '7':
+               c -= '0';
+               while('0' <= (d=gch()) && d <= '7'){
+                       c = c * 8 + (d-'0');
+                       if(!('0' <= peek && peek <= '7')) break;
+                       }
+               break;
+       }
+       return(c);
+       }
+lookup(s,t)
+  char *s;
+  char **t; {
+       register int i;
+       i = 0;
+       while(*t){
+               if(scomp(s,*t) == 0)
+                       return(i);
+               i++;
+               t++;
+               }
+       return(-1);
+       }
+cpyact(){ /* copy C action to the next ; or closing } */
+       register int brac, c, mth;
+       int savline, sw;
+
+       brac = 0;
+       sw = TRUE;
+
+while(!eof){
+       c = gch();
+swt:
+       switch( c ){
+
+case '|':      if(brac == 0 && sw == TRUE){
+                       if(peek == '|')gch();           /* eat up an extra '|' */
+                       return(0);
+                       }
+               break;
+
+case ';':
+               if( brac == 0 ){
+                       putc(c,fout);
+                       putc('\n',fout);
+                       return(1);
+                       }
+               break;
+
+case '{':
+               brac++;
+               savline=yyline;
+               break;
+
+case '}':
+               brac--;
+               if( brac == 0 ){
+                       putc(c,fout);
+                       putc('\n',fout);
+                       return(1);
+                       }
+               break;
+
+case '/':      /* look for comments */
+               putc(c,fout);
+               c = gch();
+               if( c != '*' ) goto swt;
+
+               /* it really is a comment */
+
+               putc(c,fout);
+               savline=yyline;
+               while( c=gch() ){
+                       if( c=='*' ){
+                               putc(c,fout);
+                               if( (c=gch()) == '/' ) goto loop;
+                               }
+                       putc(c,fout);
+                       }
+               yyline=savline;
+               error( "EOF inside comment" );
+
+case '\'':     /* character constant */
+               mth = '\'';
+               goto string;
+
+case '"':      /* character string */
+               mth = '"';
+
+       string:
+
+               putc(c,fout);
+               while( c=gch() ){
+                       if( c=='\\' ){
+                               putc(c,fout);
+                               c=gch();
+                               }
+                       else if( c==mth ) goto loop;
+                       putc(c,fout);
+                       if (c == '\n')
+                               {
+                               yyline--;
+                               error( "Non-terminated string or character constant");
+                               }
+                       }
+               error( "EOF in string or character constant" );
+
+case '\0':
+               yyline = savline;
+               error("Action does not terminate");
+default:
+               break;          /* usual character */
+               }
+loop:
+       if(c != ' ' && c != '\t' && c != '\n') sw = FALSE;
+       putc(c,fout);
+       }
+error("Premature EOF");
+}
+gch(){
+       register int c;
+       prev = pres;
+       c = pres = peek;
+       peek = pushptr > pushc ? *--pushptr : getc(fin);
+       if(peek == EOF && sargc > 1){
+               fclose(fin);
+               fin = fopen(sargv[++fptr],"r");
+               if(fin == NULL)
+                       error("Cannot open file %s",sargv[fptr]);
+               peek = getc(fin);
+               sargc--;
+               sargv++;
+               }
+       if(c == EOF) {
+               eof = TRUE;
+               fclose(fin);
+               return(0);
+               }
+       if(c == '\n')yyline++;
+       return(c);
+       }
+mn2(a,d,c)
+  int a,d,c;
+       {
+       name[tptr] = a;
+       left[tptr] = d;
+       right[tptr] = c;
+       parent[tptr] = 0;
+       nullstr[tptr] = 0;
+       switch(a){
+       case RSTR:
+               parent[d] = tptr;
+               break;
+       case BAR:
+       case RNEWE:
+               if(nullstr[d] || nullstr[c]) nullstr[tptr] = TRUE;
+               parent[d] = parent[c] = tptr;
+               break;
+       case RCAT:
+       case DIV:
+               if(nullstr[d] && nullstr[c])nullstr[tptr] = TRUE;
+               parent[d] = parent[c] = tptr;
+               break;
+       case RSCON:
+               parent[d] = tptr;
+               nullstr[tptr] = nullstr[d];
+               break;
+# ifdef DEBUG
+       default:
+               warning("bad switch mn2 %d %d",a,d);
+               break;
+# endif
+               }
+       if(tptr > treesize)
+               error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
+       return(tptr++);
+       }
+mn1(a,d)
+  int a,d;
+       {
+       name[tptr] = a;
+       left[tptr] = d;
+       parent[tptr] = 0;
+       nullstr[tptr] = 0;
+       switch(a){
+       case RCCL:
+       case RNCCL:
+               if(slength(d) == 0) nullstr[tptr] = TRUE;
+               break;
+       case STAR:
+       case QUEST:
+               nullstr[tptr] = TRUE;
+               parent[d] = tptr;
+               break;
+       case PLUS:
+       case CARAT:
+               nullstr[tptr] = nullstr[d];
+               parent[d] = tptr;
+               break;
+       case S2FINAL:
+               nullstr[tptr] = TRUE;
+               break;
+# ifdef DEBUG
+       case FINAL:
+       case S1FINAL:
+               break;
+       default:
+               warning("bad switch mn1 %d %d",a,d);
+               break;
+# endif
+               }
+       if(tptr > treesize)
+               error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
+       return(tptr++);
+       }
+mn0(a)
+  int a;
+       {
+       name[tptr] = a;
+       parent[tptr] = 0;
+       nullstr[tptr] = 0;
+       if(a >= NCH) switch(a){
+       case RNULLS: nullstr[tptr] = TRUE; break;
+# ifdef DEBUG
+       default:
+               warning("bad switch mn0 %d",a);
+               break;
+# endif
+       }
+       if(tptr > treesize)
+               error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
+       return(tptr++);
+       }
+munput(t,p)    /* implementation dependent */
+  char *p;
+  int t; {
+       register int i,j;
+       if(t == 'c'){
+               *pushptr++ = peek;              /* watch out for this */
+               peek = p;
+               }
+       else if(t == 's'){
+               *pushptr++ = peek;
+               peek = p[0];
+               i = slength(p);
+               for(j = i-1; j>=1; j--)
+                       *pushptr++ = p[j];
+               }
+# ifdef DEBUG
+       else error("Unrecognized munput option %c",t);
+# endif
+       if(pushptr >= pushc+TOKENSIZE)
+               error("Too many characters pushed");
+       return;
+       }
+
+dupl(n)
+  int n; {
+       /* duplicate the subtree whose root is n, return ptr to it */
+       register int i;
+       i = name[n];
+       if(i < NCH) return(mn0(i));
+       switch(i){
+       case RNULLS:
+               return(mn0(i));
+       case RCCL: case RNCCL: case FINAL: case S1FINAL: case S2FINAL:
+               return(mn1(i,left[n]));
+       case STAR: case QUEST: case PLUS: case CARAT:
+               return(mn1(i,dupl(left[n])));
+       case RSTR: case RSCON:
+               return(mn2(i,dupl(left[n]),right[n]));
+       case BAR: case RNEWE: case RCAT: case DIV:
+               return(mn2(i,dupl(left[n]),dupl(right[n])));
+# ifdef DEBUG
+       default:
+               warning("bad switch dupl %d",n);
+# endif
+       }
+       return(0);
+       }
+# ifdef DEBUG
+allprint(c)
+  char c; {
+       switch(c){
+               case 014:
+                       printf("\\f");
+                       charc++;
+                       break;
+               case '\n':
+                       printf("\\n");
+                       charc++;
+                       break;
+               case '\t':
+                       printf("\\t");
+                       charc++;
+                       break;
+               case '\b':
+                       printf("\\b");
+                       charc++;
+                       break;
+               case ' ':
+                       printf("\\\bb");
+                       break;
+               default:
+                       if(!printable(c)){
+                               printf("\\%-3o",c);
+                               charc =+ 3;
+                               }
+                       else 
+                               putchar(c);
+                       break;
+               }
+       charc++;
+       return;
+       }
+strpt(s)
+  char *s; {
+       charc = 0;
+       while(*s){
+               allprint(*s++);
+               if(charc > LINESIZE){
+                       charc = 0;
+                       printf("\n\t");
+                       }
+               }
+       return;
+       }
+sect1dump(){
+       register int i;
+       printf("Sect 1:\n");
+       if(def[0]){
+               printf("str     trans\n");
+               i = -1;
+               while(def[++i])
+                       printf("%s\t%s\n",def[i],subs[i]);
+               }
+       if(sname[0]){
+               printf("start names\n");
+               i = -1;
+               while(sname[++i])
+                       printf("%s\n",sname[i]);
+               }
+       if(chset == TRUE){
+               printf("char set changed\n");
+               for(i=1;i<NCH;i++){
+                       if(i != ctable[i]){
+                               allprint(i);
+                               putchar(' ');
+                               printable(ctable[i]) ? putchar(ctable[i]) : printf("%d",ctable[i]);
+                               putchar('\n');
+                               }
+                       }
+               }
+       }
+sect2dump(){
+       printf("Sect 2:\n");
+       treedump();
+       }
+treedump()
+       {
+       register int t;
+       register char *p;
+       printf("treedump %d nodes:\n",tptr);
+       for(t=0;t<tptr;t++){
+               printf("%4d ",t);
+               parent[t] ? printf("p=%4d",parent[t]) : printf("      ");
+               printf("  ");
+               if(name[t] < NCH) {
+                               allprint(name[t]);
+                               }
+               else switch(name[t]){
+                       case RSTR:
+                               printf("%d ",left[t]);
+                               allprint(right[t]);
+                               break;
+                       case RCCL:
+                               printf("ccl ");
+                               strpt(left[t]);
+                               break;
+                       case RNCCL:
+                               printf("nccl ");
+                               strpt(left[t]);
+                               break;
+                       case DIV:
+                               printf("/ %d %d",left[t],right[t]);
+                               break;
+                       case BAR:
+                               printf("| %d %d",left[t],right[t]);
+                               break;
+                       case RCAT:
+                               printf("cat %d %d",left[t],right[t]);
+                               break;
+                       case PLUS:
+                               printf("+ %d",left[t]);
+                               break;
+                       case STAR:
+                               printf("* %d",left[t]);
+                               break;
+                       case CARAT:
+                               printf("^ %d",left[t]);
+                               break;
+                       case QUEST:
+                               printf("? %d",left[t]);
+                               break;
+                       case RNULLS:
+                               printf("nullstring");
+                               break;
+                       case FINAL:
+                               printf("final %d",left[t]);
+                               break;
+                       case S1FINAL:
+                               printf("s1final %d",left[t]);   
+                               break;
+                       case S2FINAL:
+                               printf("s2final %d",left[t]);
+                               break;
+                       case RNEWE:
+                               printf("new %d %d",left[t],right[t]);
+                               break;
+                       case RSCON:
+                               p = right[t];
+                               printf("start %s",sname[*p++-1]);
+                               while(*p)
+                                       printf(", %s",sname[*p++-1]);
+                               printf(" %d",left[t]);
+                               break;
+                       default:
+                               printf("unknown %d %d %d",name[t],left[t],right[t]);
+                               break;
+                       }
+               if(nullstr[t])printf("\t(null poss.)");
+               putchar('\n');
+               }
+       }
+# endif
diff --git a/usr/src/cmd/lex/sub2.c b/usr/src/cmd/lex/sub2.c
new file mode 100644 (file)
index 0000000..ce0741d
--- /dev/null
@@ -0,0 +1,951 @@
+# include "ldefs.c"
+cfoll(v)
+       int v;
+       {
+       register int i,j,k;
+       char *p;
+       i = name[v];
+       if(i < NCH) i = 1;      /* character */
+       switch(i){
+               case 1: case RSTR: case RCCL: case RNCCL: case RNULLS:
+                       for(j=0;j<tptr;j++)
+                               tmpstat[j] = FALSE;
+                       count = 0;
+                       follow(v);
+# ifdef PP
+                       padd(foll,v);           /* packing version */
+# endif
+# ifndef PP
+                       add(foll,v);            /* no packing version */
+# endif
+                       if(i == RSTR) cfoll(left[v]);
+                       else if(i == RCCL || i == RNCCL){       /* compress ccl list */
+                               for(j=1; j<NCH;j++)
+                                       symbol[j] = (i==RNCCL);
+                               p = left[v];
+                               while(*p)
+                                       symbol[*p++] = (i == RCCL);
+                               p = pcptr;
+                               for(j=1;j<NCH;j++)
+                                       if(symbol[j]){
+                                               for(k=0;p+k < pcptr; k++)
+                                                       if(cindex[j] == *(p+k))
+                                                               break;
+                                               if(p+k >= pcptr)*pcptr++ = cindex[j];
+                                               }
+                               *pcptr++ = 0;
+                               if(pcptr > pchar + pchlen)
+                                       error("Too many packed character classes");
+                               left[v] = p;
+                               name[v] = RCCL; /* RNCCL eliminated */
+# ifdef DEBUG
+                               if(debug && *p){
+                                       printf("ccl %d: %d",v,*p++);
+                                       while(*p)
+                                               printf(", %d",*p++);
+                                       putchar('\n');
+                                       }
+# endif
+                               }
+                       break;
+               case CARAT:
+                       cfoll(left[v]);
+                       break;
+               case STAR: case PLUS: case QUEST: case RSCON: 
+                       cfoll(left[v]);
+                       break;
+               case BAR: case RCAT: case DIV: case RNEWE:
+                       cfoll(left[v]);
+                       cfoll(right[v]);
+                       break;
+# ifdef DEBUG
+               case FINAL:
+               case S1FINAL:
+               case S2FINAL:
+                       break;
+               default:
+                       warning("bad switch cfoll %d",v);
+# endif
+               }
+       return;
+       }
+# ifdef DEBUG
+pfoll()
+       {
+       register int i,k,*p;
+       int j;
+       /* print sets of chars which may follow positions */
+       printf("pos\tchars\n");
+       for(i=0;i<tptr;i++)
+               if(p=foll[i]){
+                       j = *p++;
+                       if(j >= 1){
+                               printf("%d:\t%d",i,*p++);
+                               for(k=2;k<=j;k++)
+                                       printf(", %d",*p++);
+                               putchar('\n');
+                               }
+                       }
+       return;
+       }
+# endif
+add(array,n)
+  int **array;
+  int n; {
+       register int i, *temp;
+       register char *ctemp;
+       temp = nxtpos;
+       ctemp = tmpstat;
+       array[n] = nxtpos;              /* note no packing is done in positions */
+       *temp++ = count;
+       for(i=0;i<tptr;i++)
+               if(ctemp[i] == TRUE)
+                       *temp++ = i;
+       nxtpos = temp;
+       if(nxtpos >= positions+maxpos)
+               error("Too many positions %s",(maxpos== MAXPOS?"\nTry using %p num":""));
+       return;
+       }
+follow(v)
+  int v;
+       {
+       register int p;
+       if(v >= tptr-1)return;
+       p = parent[v];
+       if(p == 0) return;
+       switch(name[p]){
+                       /* will not be CHAR RNULLS FINAL S1FINAL S2FINAL RCCL RNCCL */
+               case RSTR:
+                       if(tmpstat[p] == FALSE){
+                               count++;
+                               tmpstat[p] = TRUE;
+                               }
+                       break;
+               case STAR: case PLUS:
+                       first(v);
+                       follow(p);
+                       break;
+               case BAR: case QUEST: case RNEWE:
+                       follow(p);
+                       break;
+               case RCAT: case DIV: 
+                       if(v == left[p]){
+                               if(nullstr[right[p]])
+                                       follow(p);
+                               first(right[p]);
+                               }
+                       else follow(p);
+                       break;
+               case RSCON: case CARAT: 
+                       follow(p);
+                       break;
+# ifdef DEBUG
+               default:
+                       warning("bad switch follow %d",p);
+# endif
+               }
+       return;
+       }
+first(v)       /* calculate set of positions with v as root which can be active initially */
+  int v; {
+       register int i;
+       register char *p;
+       i = name[v];
+       if(i < NCH)i = 1;
+       switch(i){
+               case 1: case RCCL: case RNCCL: case RNULLS: case FINAL: case S1FINAL: case S2FINAL:
+                       if(tmpstat[v] == FALSE){
+                               count++;
+                               tmpstat[v] = TRUE;
+                               }
+                       break;
+               case BAR: case RNEWE:
+                       first(left[v]);
+                       first(right[v]);
+                       break;
+               case CARAT:
+                       if(stnum % 2 == 1)
+                               first(left[v]);
+                       break;
+               case RSCON:
+                       i = stnum/2 +1;
+                       p = right[v];
+                       while(*p)
+                               if(*p++ == i){
+                                       first(left[v]);
+                                       break;
+                                       }
+                       break;
+               case STAR: case QUEST: case PLUS:  case RSTR:
+                       first(left[v]);
+                       break;
+               case RCAT: case DIV:
+                       first(left[v]);
+                       if(nullstr[left[v]])
+                               first(right[v]);
+                       break;
+# ifdef DEBUG
+               default:
+                       warning("bad switch first %d",v);
+# endif
+               }
+       return;
+       }
+cgoto(){
+       register int i, j, s;
+       int npos, curpos, n;
+       int tryit;
+       char tch[NCH];
+       int tst[NCH];
+       char *q;
+       /* generate initial state, for each start condition */
+       if(ratfor){
+               fprintf(fout,"blockdata\n");
+               fprintf(fout,"common /Lvstop/ vstop\n");
+               fprintf(fout,"define Svstop %d\n",nstates+1);
+               fprintf(fout,"integer vstop(Svstop)\n");
+               }
+       else fprintf(fout,"int yyvstop[] ={\n0,\n");
+       while(stnum < 2 || stnum/2 < sptr){
+               for(i = 0; i<tptr; i++) tmpstat[i] = 0;
+               count = 0;
+               if(tptr > 0)first(tptr-1);
+               add(state,stnum);
+# ifdef DEBUG
+               if(debug){
+                       if(stnum > 1)
+                               printf("%s:\n",sname[stnum/2]);
+                       pstate(stnum);
+                       }
+# endif
+               stnum++;
+               }
+       stnum--;
+       /* even stnum = might not be at line begin */
+       /* odd stnum  = must be at line begin */
+       /* even states can occur anywhere, odd states only at line begin */
+       for(s = 0; s <= stnum; s++){
+               tryit = FALSE;
+               cpackflg[s] = FALSE;
+               sfall[s] = -1;
+               acompute(s);
+               for(i=0;i<NCH;i++) symbol[i] = 0;
+               npos = *state[s];
+               for(i = 1; i<=npos; i++){
+                       curpos = *(state[s]+i);
+                       if(name[curpos] < NCH) symbol[name[curpos]] = TRUE;
+                       else switch(name[curpos]){
+                       case RCCL:
+                               tryit = TRUE;
+                               q = left[curpos];
+                               while(*q){
+                                       for(j=1;j<NCH;j++)
+                                               if(cindex[j] == *q)
+                                                       symbol[j] = TRUE;
+                                       q++;
+                                       }
+                               break;
+                       case RSTR:
+                               symbol[right[curpos]] = TRUE;
+                               break;
+# ifdef DEBUG
+                       case RNULLS:
+                       case FINAL:
+                       case S1FINAL:
+                       case S2FINAL:
+                               break;
+                       default:
+                               warning("bad switch cgoto %d state %d",curpos,s);
+                               break;
+# endif
+                       }
+               }
+# ifdef DEBUG
+               if(debug){
+                       printf("State %d transitions on:\n\t",s);
+                       charc = 0;
+                       for(i = 1; i<NCH; i++){
+                               if(symbol[i]) allprint(i);
+                               if(charc > LINESIZE){
+                                       charc = 0;
+                                       printf("\n\t");
+                                       }
+                               }
+                       putchar('\n');
+                       }
+# endif
+               /* for each char, calculate next state */
+               n = 0;
+               for(i = 1; i<NCH; i++){
+                       if(symbol[i]){
+                               nextstate(s,i);         /* executed for each state, transition pair */
+                               xstate = notin(stnum);
+                               if(xstate == -2) warning("bad state  %d %o",s,i);
+                               else if(xstate == -1){
+                                       if(stnum >= nstates)
+                                               error("Too many states %s",(nstates == NSTATES ? "\nTry using %n num":""));
+                                       add(state,++stnum);
+# ifdef DEBUG
+                                       if(debug)pstate(stnum);
+# endif
+                                       tch[n] = i;
+                                       tst[n++] = stnum;
+                                       }
+                               else {          /* xstate >= 0 ==> state exists */
+                                       tch[n] = i;
+                                       tst[n++] = xstate;
+                                       }
+                               }
+                       }
+               tch[n] = 0;
+               tst[n] = -1;
+               /* pack transitions into permanent array */
+               if(n > 0) packtrans(s,tch,tst,n,tryit);
+               else gotof[s] = -1;
+               }
+       ratfor ? fprintf(fout,"end\n") : fprintf(fout,"0};\n");
+       return;
+       }
+       /*      Beware -- 70% of total CPU time is spent in this subroutine -
+               if you don't believe me - try it yourself ! */
+nextstate(s,c)
+  int s,c; {
+       register int j, *newpos;
+       register char *temp, *tz;
+       int *pos, i, *f, num, curpos, number;
+       /* state to goto from state s on char c */
+       num = *state[s];
+       temp = tmpstat;
+       pos = state[s] + 1;
+       for(i = 0; i<num; i++){
+               curpos = *pos++;
+               j = name[curpos];
+               if(j < NCH && j == c
+               || j == RSTR && c == right[curpos]
+               || j == RCCL && member(c,left[curpos])){
+                       f = foll[curpos];
+                       number = *f;
+                       newpos = f+1;
+                       for(j=0;j<number;j++)
+                               temp[*newpos++] = 2;
+                       }
+               }
+       j = 0;
+       tz = temp + tptr;
+       while(temp < tz){
+               if(*temp == 2){
+                       j++;
+                       *temp++ = 1;
+                       }
+               else *temp++ = 0;
+               }
+       count = j;
+       return;
+       }
+notin(n)
+  int n;       {       /* see if tmpstat occurs previously */
+       register int *j,k;
+       register char *temp;
+       int i;
+       if(count == 0)
+               return(-2);
+       temp = tmpstat;
+       for(i=n;i>=0;i--){      /* for each state */
+               j = state[i];
+               if(count == *j++){
+                       for(k=0;k<count;k++)
+                               if(!temp[*j++])break;
+                       if(k >= count)
+                               return(i);
+                       }
+               }
+       return(-1);
+       }
+packtrans(st,tch,tst,cnt,tryit)
+  int st, *tst, cnt,tryit;
+  char *tch; {
+       /* pack transitions into nchar, nexts */
+       /* nchar is terminated by '\0', nexts uses cnt, followed by elements */
+       /* gotof[st] = index into nchr, nexts for state st */
+
+       /* sfall[st] =  t implies t is fall back state for st */
+       /*              == -1 implies no fall back */
+
+       int cmin, cval, tcnt, diff, p, *ast;
+       register int i,j,k;
+       char *ach;
+       int go[NCH], temp[NCH], c;
+       int swork[NCH];
+       char cwork[NCH];
+       int upper;
+
+       rcount += cnt;
+       cmin = -1;
+       cval = NCH;
+       ast = tst;
+       ach = tch;
+       /* try to pack transitions using ccl's */
+       if(!optim)goto nopack;          /* skip all compaction */
+       if(tryit){      /* ccl's used */
+               for(i=1;i<NCH;i++){
+                       go[i] = temp[i] = -1;
+                       symbol[i] = 1;
+                       }
+               for(i=0;i<cnt;i++){
+                       go[tch[i]] = tst[i];
+                       symbol[tch[i]] = 0;
+                       }
+               for(i=0; i<cnt;i++){
+                       c = match[tch[i]];
+                       if(go[c] != tst[i] || c == tch[i])
+                               temp[tch[i]] = tst[i];
+                       }
+               /* fill in error entries */
+               for(i=1;i<NCH;i++)
+                       if(symbol[i]) temp[i] = -2;     /* error trans */
+               /* count them */
+               k = 0;
+               for(i=1;i<NCH;i++)
+                       if(temp[i] != -1)k++;
+               if(k <cnt){     /* compress by char */
+# ifdef DEBUG
+                       if(debug) printf("use compression  %d,  %d vs %d\n",st,k,cnt);
+# endif
+                       k = 0;
+                       for(i=1;i<NCH;i++)
+                               if(temp[i] != -1){
+                                       cwork[k] = i;
+                                       swork[k++] = (temp[i] == -2 ? -1 : temp[i]);
+                                       }
+                       cwork[k] = 0;
+# ifdef PC
+                       ach = cwork;
+                       ast = swork;
+                       cnt = k;
+                       cpackflg[st] = TRUE;
+# endif
+                       }
+               }
+       for(i=0; i<st; i++){    /* get most similar state */
+                               /* reject state with more transitions, state already represented by a third state,
+                                       and state which is compressed by char if ours is not to be */
+               if(sfall[i] != -1) continue;
+               if(cpackflg[st] == 1) if(!(cpackflg[i] == 1)) continue;
+               p = gotof[i];
+               if(p == -1) /* no transitions */ continue;
+               tcnt = nexts[p];
+               if(tcnt > cnt) continue;
+               diff = 0;
+               k = 0;
+               j = 0;
+               upper = p + tcnt;
+               while(ach[j] && p < upper){
+                       while(ach[j] < nchar[p] && ach[j]){diff++; j++; }
+                       if(ach[j] == 0)break;
+                       if(ach[j] > nchar[p]){diff=NCH;break;}
+                       /* ach[j] == nchar[p] */
+                       if(ast[j] != nexts[++p] || ast[j] == -1 || (cpackflg[st] && ach[j] != match[ach[j]]))diff++;
+                       j++;
+                       }
+               while(ach[j]){
+                       diff++;
+                       j++;
+                       }
+               if(p < upper)diff = NCH;
+               if(diff < cval && diff < tcnt){
+                       cval = diff;
+                       cmin = i;
+                       if(cval == 0)break;
+                       }
+               }
+       /* cmin = state "most like" state st */
+# ifdef DEBUG
+       if(debug)printf("select st %d for st %d diff %d\n",cmin,st,cval);
+# endif
+# ifdef PS
+       if(cmin != -1){ /* if we can use st cmin */
+               gotof[st] = nptr;
+               k = 0;
+               sfall[st] = cmin;
+               p = gotof[cmin]+1;
+               j = 0;
+               while(ach[j]){
+                       /* if cmin has a transition on c, then so will st */
+                       /* st may be "larger" than cmin, however */
+                       while(ach[j] < nchar[p-1] && ach[j]){
+                               k++;
+                               nchar[nptr] = ach[j];
+                               nexts[++nptr] = ast[j];
+                               j++;
+                               }
+                       if(nchar[p-1] == 0)break;
+                       if(ach[j] > nchar[p-1]){
+                               warning("bad transition %d %d",st,cmin);
+                               goto nopack;
+                               }
+                       /* ach[j] == nchar[p-1] */
+                       if(ast[j] != nexts[p] || ast[j] == -1 || (cpackflg[st] && ach[j] != match[ach[j]])){
+                               k++;
+                               nchar[nptr] = ach[j];
+                               nexts[++nptr] = ast[j];
+                               }
+                       p++;
+                       j++;
+                       }
+               while(ach[j]){
+                       nchar[nptr] = ach[j];
+                       nexts[++nptr] = ast[j++];
+                       k++;
+                       }
+               nexts[gotof[st]] = cnt = k;
+               nchar[nptr++] = 0;
+               }
+       else {
+# endif
+nopack:
+       /* stick it in */
+               gotof[st] = nptr;
+               nexts[nptr] = cnt;
+               for(i=0;i<cnt;i++){
+                       nchar[nptr] = ach[i];
+                       nexts[++nptr] = ast[i];
+                       }
+               nchar[nptr++] = 0;
+# ifdef PS
+               }
+# endif
+       if(cnt < 1){
+               gotof[st] = -1;
+               nptr--;
+               }
+       else
+               if(nptr > ntrans)
+                       error("Too many transitions %s",(ntrans==NTRANS?"\nTry using %a num":""));
+       return;
+       }
+# ifdef DEBUG
+pstate(s)
+  int s; {
+       register int *p,i,j;
+       printf("State %d:\n",s);
+       p = state[s];
+       i = *p++;
+       if(i == 0) return;
+       printf("%4d",*p++);
+       for(j = 1; j<i; j++){
+               printf(", %4d",*p++);
+               if(j%30 == 0)putchar('\n');
+               }
+       putchar('\n');
+       return;
+       }
+# endif
+member(d,t)
+  int d;
+  char *t;     {
+       register int c;
+       register char *s;
+       c = d;
+       s = t;
+       c = cindex[c];
+       while(*s)
+               if(*s++ == c) return(1);
+       return(0);
+       }
+# ifdef DEBUG
+stprt(i)
+  int i; {
+       register int p, t;
+       printf("State %d:",i);
+       /* print actions, if any */
+       t = atable[i];
+       if(t != -1)printf(" final");
+       putchar('\n');
+       if(cpackflg[i] == TRUE)printf("backup char in use\n");
+       if(sfall[i] != -1)printf("fall back state %d\n",sfall[i]);
+       p = gotof[i];
+       if(p == -1) return;
+       printf("(%d transitions)\n",nexts[p]);
+       while(nchar[p]){
+               charc = 0;
+               if(nexts[p+1] >= 0)
+                       printf("%d\t",nexts[p+1]);
+               else printf("err\t");
+               allprint(nchar[p++]);
+               while(nexts[p] == nexts[p+1] && nchar[p]){
+                       if(charc > LINESIZE){
+                               charc = 0;
+                               printf("\n\t");
+                               }
+                       allprint(nchar[p++]);
+                       }
+               putchar('\n');
+               }
+       putchar('\n');
+       return;
+       }
+# endif
+acompute(s)    /* compute action list = set of poss. actions */
+  int s; {
+       register int *p, i, j;
+       int cnt, m;
+       int temp[300], k, neg[300], n;
+       k = 0;
+       n = 0;
+       p = state[s];
+       cnt = *p++;
+       if(cnt > 300)
+               error("Too many positions for one state - acompute");
+       for(i=0;i<cnt;i++){
+               if(name[*p] == FINAL)temp[k++] = left[*p];
+               else if(name[*p] == S1FINAL){temp[k++] = left[*p];
+                       if (left[*p] >NACTIONS) error("Too many right contexts");
+                       extra[left[*p]] = 1;
+                       }
+               else if(name[*p] == S2FINAL)neg[n++] = left[*p];
+               p++;
+               }
+       atable[s] = -1;
+       if(k < 1 && n < 1) return;
+# ifdef DEBUG
+       if(debug) printf("final %d actions:",s);
+# endif
+       /* sort action list */
+       for(i=0; i<k; i++)
+               for(j=i+1;j<k;j++)
+                       if(temp[j] < temp[i]){
+                               m = temp[j];
+                               temp[j] = temp[i];
+                               temp[i] = m;
+                               }
+       /* remove dups */
+       for(i=0;i<k-1;i++)
+               if(temp[i] == temp[i+1]) temp[i] = 0;
+       /* copy to permanent quarters */
+       atable[s] = aptr;
+# ifdef DEBUG
+       if(!ratfor)fprintf(fout,"/* actions for state %d */",s);
+# endif
+       putc('\n',fout);
+       for(i=0;i<k;i++)
+               if(temp[i] != 0){
+                       ratfor ? fprintf(fout,"data vstop(%d)/%d/\n",aptr,temp[i]) : fprintf(fout,"%d,\n",temp[i]);
+# ifdef DEBUG
+                       if(debug)
+                               printf("%d ",temp[i]);
+# endif
+                       aptr++;
+                       }
+       for(i=0;i<n;i++){               /* copy fall back actions - all neg */
+               ratfor ? fprintf(fout,"data vstop(%d)/%d/\n",aptr,neg[i]) : fprintf(fout,"%d,\n",neg[i]);
+               aptr++;
+# ifdef DEBUG
+               if(debug)printf("%d ",neg[i]);
+# endif
+               }
+# ifdef DEBUG
+       if(debug)putchar('\n');
+# endif
+       ratfor ? fprintf(fout,"data vstop (%d)/0/\n",aptr) : fprintf(fout,"0,\n");
+       aptr++;
+       return;
+       }
+# ifdef DEBUG
+pccl() {
+       /* print character class sets */
+       register int i, j;
+       printf("char class intersection\n");
+       for(i=0; i< ccount; i++){
+               charc = 0;
+               printf("class %d:\n\t",i);
+               for(j=1;j<NCH;j++)
+                       if(cindex[j] == i){
+                               allprint(j);
+                               if(charc > LINESIZE){
+                                       printf("\n\t");
+                                       charc = 0;
+                                       }
+                               }
+               putchar('\n');
+               }
+       charc = 0;
+       printf("match:\n");
+       for(i=0;i<NCH;i++){
+               allprint(match[i]);
+               if(charc > LINESIZE){
+                       putchar('\n');
+                       charc = 0;
+                       }
+               }
+       putchar('\n');
+       return;
+       }
+# endif
+mkmatch(){
+       register int i;
+       char tab[NCH];
+       for(i=0; i<ccount; i++)
+               tab[i] = 0;
+       for(i=1;i<NCH;i++)
+               if(tab[cindex[i]] == 0)
+                       tab[cindex[i]] = i;
+       /* tab[i] = principal char for new ccl i */
+       for(i = 1; i<NCH; i++)
+               match[i] = tab[cindex[i]];
+       return;
+       }
+layout(){
+       /* format and output final program's tables */
+       register int i, j, k;
+       int  top, bot, startup, omin;
+       startup = 0;
+       for(i=0; i<outsize;i++)
+               verify[i] = advance[i] = 0;
+       omin = 0;
+       yytop = 0;
+       for(i=0; i<= stnum; i++){       /* for each state */
+               j = gotof[i];
+               if(j == -1){
+                       stoff[i] = 0;
+                       continue;
+                       }
+               bot = j;
+               while(nchar[j])j++;
+               top = j - 1;
+# if DEBUG
+               if (debug)
+                       {
+                       printf("State %d: (layout)\n", i);
+                       for(j=bot; j<=top;j++)
+                               {
+                               printf("  %o", nchar[j]);
+                               if (j%10==0) putchar('\n');
+                               }
+                       putchar('\n');
+                       }
+# endif
+               while(verify[omin+ZCH]) omin++;
+               startup = omin;
+# if DEBUG
+               if (debug) printf("bot,top %d, %d startup begins %d\n",bot,top,startup);
+# endif
+               if(chset){
+                       do {
+                               ++startup;
+                               if(startup > outsize - ZCH)
+                                       error("output table overflow");
+                               for(j = bot; j<= top; j++){
+                                       k=startup+ctable[nchar[j]];
+                                       if(verify[k])break;
+                                       }
+                               } while (j <= top);
+# if DEBUG
+                       if (debug) printf(" startup will be %d\n",startup);
+# endif
+                       /* have found place */
+                       for(j = bot; j<= top; j++){
+                               k = startup + ctable[nchar[j]];
+                               if (ctable[nchar[j]]<=0)
+                                printf("j %d nchar %d ctable.nch %d\n",j,nchar[j],ctable[nchar[k]]);
+                               verify[k] = i+1;                        /* state number + 1*/
+                               advance[k] = nexts[j+1]+1;              /* state number + 1*/
+                               if(yytop < k) yytop = k;
+                               }
+                       }
+               else {
+                       do {
+                               ++startup;
+                               if(startup > outsize - ZCH)
+                                       error("output table overflow");
+                               for(j = bot; j<= top; j++){
+                                       k = startup + nchar[j];
+                                       if(verify[k])break;
+                                       }
+                               } while (j <= top);
+                       /* have found place */
+# if DEBUG
+       if (debug) printf(" startup going to be %d\n", startup);
+# endif
+                       for(j = bot; j<= top; j++){
+                               k = startup + nchar[j];
+                               verify[k] = i+1;                        /* state number + 1*/
+                               advance[k] = nexts[j+1]+1;              /* state number + 1*/
+                               if(yytop < k) yytop = k;
+                               }
+                       }
+               stoff[i] = startup;
+               }
+
+       /* stoff[i] = offset into verify, advance for trans for state i */
+       /* put out yywork */
+       if(ratfor){
+               fprintf(fout, "define YYTOPVAL %d\n", yytop);
+               rprint(verify,"verif",yytop+1);
+               rprint(advance,"advan",yytop+1);
+               shiftr(stoff, stnum); 
+               rprint(stoff,"stoff",stnum+1);
+               shiftr(sfall, stnum); upone(sfall, stnum+1);
+               rprint(sfall,"sfall",stnum+1);
+               bprint(extra,"extra",casecount+1);
+               bprint(match,"match",NCH);
+               shiftr(atable, stnum);
+               rprint(atable,"atable",stnum+1);
+               return;
+               }
+       fprintf(fout,"# define YYTYPE %s\n",stnum+1 > NCH ? "int" : "char");
+       fprintf(fout,"struct yywork { YYTYPE verify, advance; } yycrank[] ={\n");
+       for(i=0;i<=yytop;i+=4){
+               for(j=0;j<4;j++){
+                       k = i+j;
+                       if(verify[k])
+                               fprintf(fout,"%d,%d,\t",verify[k],advance[k]);
+                       else
+                               fprintf(fout,"0,0,\t");
+                       }
+               putc('\n',fout);
+               }
+       fprintf(fout,"0,0};\n");
+
+       /* put out yysvec */
+
+       fprintf(fout,"struct yysvf yysvec[] ={\n");
+       fprintf(fout,"0,\t0,\t0,\n");
+       for(i=0;i<=stnum;i++){  /* for each state */
+               if(cpackflg[i])stoff[i] = -stoff[i];
+               fprintf(fout,"yycrank+%d,\t",stoff[i]);
+               if(sfall[i] != -1)
+                       fprintf(fout,"yysvec+%d,\t", sfall[i]+1);       /* state + 1 */
+               else fprintf(fout,"0,\t\t");
+               if(atable[i] != -1)
+                       fprintf(fout,"yyvstop+%d,",atable[i]);
+               else fprintf(fout,"0,\t");
+# ifdef DEBUG
+               fprintf(fout,"\t\t/* state %d */",i);
+# endif
+               putc('\n',fout);
+               }
+       fprintf(fout,"0,\t0,\t0};\n");
+
+       /* put out yymatch */
+       
+       fprintf(fout,"struct yywork *yytop = yycrank+%d;\n",yytop);
+       fprintf(fout,"struct yysvf *yybgin = yysvec+1;\n");
+       if(optim){
+               fprintf(fout,"char yymatch[] ={\n");
+               if (chset==0) /* no chset, put out in normal order */
+                       {
+                       for(i=0; i<NCH; i+=8){
+                               for(j=0; j<8; j++){
+                                       int fbch;
+                                       fbch = match[i+j];
+                                       if(printable(fbch) && fbch != '\'' && fbch != '\\')
+                                               fprintf(fout,"'%c' ,",fbch);
+                                       else fprintf(fout,"0%-3o,",fbch);
+                                       }
+                               putc('\n',fout);
+                               }
+                       }
+               else
+                       {
+                       int *fbarr;
+                       fbarr = myalloc(2*NCH, sizeof(*fbarr));
+                       if (fbarr==0)
+                               error("No space for char table reverse",0);
+                       for(i=0; i<ZCH; i++)
+                               fbarr[i]=0;
+                       for(i=0; i<NCH; i++)
+                               fbarr[ctable[i]] = ctable[match[i]];
+                       for(i=0; i<ZCH; i+=8)
+                               {
+                               for(j=0; j<8; j++)
+                                       fprintf(fout, "0%-3o,",fbarr[i+j]);
+                               putc('\n',fout);
+                               }
+                       cfree(fbarr, 2*NCH, 1);
+                       }
+               fprintf(fout,"0};\n");
+               }
+       /* put out yyextra */
+       fprintf(fout,"char yyextra[] ={\n");
+       for(i=0;i<casecount;i+=8){
+               for(j=0;j<8;j++)
+                       fprintf(fout, "%d,", i+j<NACTIONS ?
+                               extra[i+j] : 0);
+               putc('\n',fout);
+               }
+       fprintf(fout,"0};\n");
+       return;
+       }
+rprint(a,s,n)
+  char *s;
+  int *a, n; {
+       register int i;
+       fprintf(fout,"block data\n");
+       fprintf(fout,"common /L%s/ %s\n",s,s);
+       fprintf(fout,"define S%s %d\n",s,n);
+       fprintf(fout,"integer %s (S%s)\n",s,s);
+       for(i=1; i<=n; i++)
+               {
+               if (i%8==1) fprintf(fout, "data ");
+               fprintf(fout, "%s (%d)/%d/",s,i,a[i]);
+               fprintf(fout, (i%8 && i<n) ? ", " : "\n");
+               }
+       fprintf(fout,"end\n");
+       }
+shiftr(a, n)
+       int *a;
+{
+int i;
+for(i=n; i>=0; i--)
+       a[i+1]=a[i];
+}
+upone(a,n)
+       int *a;
+{
+int i;
+for(i=0; i<=n ; i++)
+       a[i]++;
+}
+bprint(a,s,n)
+ char *s,  *a;
+ int  n; {
+       register int i, j, k;
+       fprintf(fout,"block data\n");
+       fprintf(fout,"common /L%s/ %s\n",s,s);
+       fprintf(fout,"define S%s %d\n",s,n);
+       fprintf(fout,"integer %s (S%s)\n",s,s);
+       for(i=1;i<n;i+=8){
+               fprintf(fout,"data %s (%d)/%d/",s,i,a[i]);
+               for(j=1;j<8;j++){
+                       k = i+j;
+                       if(k < n)fprintf(fout,", %s (%d)/%d/",s,k,a[k]);
+                       }
+               putc('\n',fout);
+               }
+       fprintf(fout,"end\n");
+       }
+# ifdef PP
+padd(array,n)
+  int **array;
+  int n; {
+       register int i, *j, k;
+       array[n] = nxtpos;
+       if(count == 0){
+               *nxtpos++ = 0;
+               return;
+               }
+       for(i=tptr-1;i>=0;i--){
+               j = array[i];
+               if(j && *j++ == count){
+                       for(k=0;k<count;k++)
+                               if(!tmpstat[*j++])break;
+                       if(k >= count){
+                               array[n] = array[i];
+                               return;
+                               }
+                       }
+               }
+       add(array,n);
+       return;
+       }
+# endif
diff --git a/usr/src/cmd/lint/READ_ME b/usr/src/cmd/lint/READ_ME
new file mode 100644 (file)
index 0000000..4d4dd04
--- /dev/null
@@ -0,0 +1,3 @@
+Most of lint's source files are shared with the portable
+compiler: they are found in /usr/src/cmd/mip.
+The files here are only those which are unique to lint.
diff --git a/usr/src/cmd/lint/SHELL b/usr/src/cmd/lint/SHELL
new file mode 100755 (executable)
index 0000000..dbb6feb
--- /dev/null
@@ -0,0 +1,23 @@
+L=/usr/lib/lint T=/usr/tmp/lint.$$ PATH=/bin:/usr/bin O="-C -Dlint" X= P=unix
+LL=/usr/lib
+trap "rm -f $T; exit" 1 2 15
+for A in $*
+do
+       case $A in
+       -*n*)   P= ;;
+       -*p*)   P=port ;;
+       esac
+       case $A in
+       -l*)    (/lib/cpp $O $LL/llib$A | ${L}1 -v$X-L$A >>$T)2>&1 ;;
+       -[IDOU]*)       O="$O $A" ;;
+       -X)     LL=/usr/src/cmd/lint L=/usr/src/cmd/lint/lpass ;;
+       -*)     X="$X$A" ;;
+       *)      (/lib/cpp $O $A | ${L}1 $X-L$A >>$T)2>&1
+       esac
+       done
+case $P in
+       unix)   (/lib/cpp $O $LL/llib-lc | ${L}1 -v$X-L-lc >>$T)2>&1 ;;
+       port)   (/lib/cpp $O $LL/llib-port | ${L}1 -v$X-L-lc >>$T)2>&1 ;;
+       esac
+sort -u $T | ${L}2 $X
+rm -f $T
diff --git a/usr/src/cmd/lint/lint.c b/usr/src/cmd/lint/lint.c
new file mode 100644 (file)
index 0000000..663cd63
--- /dev/null
@@ -0,0 +1,793 @@
+# include "mfile1"
+
+# include "lmanifest"
+
+# include <ctype.h>
+
+# define VAL 0
+# define EFF 1
+
+/* these are appropriate for the -p flag */
+int  SZCHAR = 8;
+int  SZINT = 16;
+int  SZFLOAT = 32;
+int  SZDOUBLE = 64;
+int  SZLONG = 32;
+int  SZSHORT = 16;
+int SZPOINT = 16;
+int ALCHAR = 8;
+int ALINT = 16;
+int ALFLOAT = 32;
+int ALDOUBLE = 64;
+int ALLONG = 32;
+int ALSHORT = 16;
+int ALPOINT = 16;
+int ALSTRUCT = 16;
+
+int vflag = 1;  /* tell about unused argments */
+int xflag = 0;  /* tell about unused externals */
+int argflag = 0;  /* used to turn off complaints about arguments */
+int libflag = 0;  /* used to generate library descriptions */
+int vaflag = -1;  /* used to signal functions with a variable number of args */
+int aflag = 0;  /* used th check precision of assignments */
+
+char *flabel = "xxx";
+
+# define LNAMES 100
+
+struct lnm {
+       short lid, flgs;
+       }  lnames[LNAMES], *lnp;
+
+contx( p, down, pl, pr ) register NODE *p; register *pl, *pr; {
+
+       *pl = *pr = VAL;
+       switch( p->op ){
+
+       case ANDAND:
+       case OROR:
+       case QUEST:
+               *pr = down;
+               break;
+
+       case SCONV:
+       case PCONV:
+       case COLON:
+               *pr = *pl = down;
+               break;
+
+       case COMOP:
+               *pl = EFF;
+               *pr = down;
+
+       case FORCE:
+       case INIT:
+       case UNARY CALL:
+       case STCALL:
+       case UNARY STCALL:
+       case CALL:
+       case UNARY FORTCALL:
+       case FORTCALL:
+       case CBRANCH:
+               break;
+
+       default:
+               if( asgop(p->op) ) break;
+               if( p->op == UNARY MUL && ( p->type == STRTY || p->type == UNIONTY) ) {
+                       break;  /* the compiler does this... */
+                       }
+               if( down == EFF && hflag ) werror( "null effect" );
+
+               }
+       }
+
+ecode( p ) NODE *p; {
+       /* compile code for p */
+
+       fwalk( p, contx, EFF );
+       lnp = lnames;
+       lprt( p, EFF, 0 );
+       }
+
+ejobcode( flag ){
+       /* called after processing each job */
+       /* flag is nonzero if errors were detected */
+       register k;
+       register struct symtab *p;
+
+       for( p=stab; p< &stab[SYMTSZ]; ++p ){
+
+               if( p->stype != TNULL ) {
+
+                       if( p->stype == STRTY || p->stype == UNIONTY ){
+                               if( dimtab[p->sizoff+1] < 0 ){ /* never defined */
+                                       if( hflag ) werror( "struct/union %.7s never defined", p->sname );
+                                       }
+                               }
+
+                       switch( p->sclass ){
+                       
+                       case STATIC:
+                               if( p->suse > 0 ){
+                                       k = lineno;
+                                       lineno = p->suse;
+                                       uerror( "static variable %s unused",
+                                               p->sname );
+                                       lineno = k;
+                                       break;
+                                       }
+
+                       case EXTERN:
+                       case USTATIC:
+                               /* with the xflag, worry about externs not used */
+                               /* the filename may be wrong here... */
+                               if( xflag && p->suse >= 0 && !libflag ){
+                                       printf( "%.7s\t%03d\t%o\t%d\t", p->sname, LDX, p->stype, 0 );
+                                       /* we don't really know the file number; we know only the line 
+                                               number, so we put only that out */
+                                       printf( "\"???\"\t%d\t%s\n", p->suse, flabel );
+                                       }
+                       
+                       case EXTDEF:
+                               if( p->suse < 0 ){  /* used */
+                                       printf( "%.7s\t%03d\t%o\t%d\t", exname(p->sname), LUM, p->stype, 0 );
+                                       fident( -p->suse );
+                                       }
+                               break;
+                               }
+                       
+                       }
+
+               }
+       exit( 0 );
+       }
+
+fident( line ){ /* like ident, but lineno = line */
+       register temp;
+       temp = lineno;
+       lineno = line;
+       ident();
+       lineno = temp;
+       }
+
+ident(){ /* write out file and line identification  */
+       printf( "%s\t%d\t%s\n", ftitle, lineno, flabel );
+       }
+
+bfcode( a, n ) int a[]; {
+       /* code for the beginning of a function; a is an array of
+               indices in stab for the arguments; n is the number */
+       /* this must also set retlab */
+       register i;
+       register struct symtab *cfp;
+       register unsigned t;
+
+       retlab = 1;
+       cfp = &stab[curftn];
+
+       /* if variable number of arguments, only print the ones which will be checked */
+       if( vaflag > 0 ){
+               if( n < vaflag ) werror( "declare the VARARGS arguments you want checked!" );
+               else n = vaflag;
+               }
+       printf( "%.7s\t%03d\t%o\t%d\t", exname(cfp->sname), libflag?LIB:LDI,
+               cfp->stype, vaflag>=0?-n:n );
+       vaflag = -1;
+
+       for( i=0; i<n; ++i ) {
+               switch( t = stab[a[i]].stype ){
+
+               case ULONG:
+                       break;
+
+               case CHAR:
+               case SHORT:
+                       t = INT;
+                       break;
+
+               case UCHAR:
+               case USHORT:
+               case UNSIGNED:
+                       t = UNSIGNED;
+                       break;
+
+                       }
+
+               printf( "%o\t", t );
+               }
+       ident();
+       }
+
+ctargs( p ) NODE *p; {
+       /* count arguments; p points to at least one */
+       /* the arguemnts are a tower of commasto the left */
+       register c;
+       c = 1; /* count the rhs */
+       while( p->op == CM ){
+               ++c;
+               p = p->left;
+               }
+       return( c );
+       }
+
+lpta( p ) NODE *p; {
+       TWORD t;
+
+       if( p->op == CM ){
+               lpta( p->left );
+               p = p->right;
+               }
+       switch( t = p->type ){
+
+               case CHAR:
+               case SHORT:
+                       t = INT;
+               case LONG:
+               case ULONG:
+               case INT:
+               case UNSIGNED:
+                       break;
+
+               case UCHAR:
+               case USHORT:
+                       t = UNSIGNED;
+                       break;
+
+               case FLOAT:
+                       printf( "%o\t", DOUBLE );
+                       return;
+
+               default:
+                       printf( "%o\t", p->type );
+                       return;
+               }
+
+       if( p->op == ICON ) printf( "%o<1\t", t );
+       else printf( "%o\t", t );
+       }
+
+# define VALSET 1
+# define VALUSED 2
+# define VALASGOP 4
+# define VALADDR 8
+
+lprt( p, down, uses ) register NODE *p; {
+       register struct symtab *q;
+       register id;
+       register acount;
+       register down1, down2;
+       register use1, use2;
+       register struct lnm *np1, *np2;
+
+       /* first, set variables which are set... */
+
+       use1 = use2 = VALUSED;
+       if( p->op == ASSIGN ) use1 = VALSET;
+       else if( p->op == UNARY AND ) use1 = VALADDR;
+       else if( asgop( p->op ) ){ /* =ops */
+               use1 = VALUSED|VALSET;
+               if( down == EFF ) use1 |= VALASGOP;
+               }
+
+
+       /* print the lines for lint */
+
+       down2 = down1 = VAL;
+       acount = 0;
+
+       switch( p->op ){
+
+       case EQ:
+       case NE:
+       case GT:
+       case GE:
+       case LT:
+       case LE:
+               if( p->left->type == CHAR && p->right->op==ICON && p->right->lval < 0 ){
+                       werror( "nonportable character comparison" );
+                       }
+               if( (p->op==EQ || p->op==NE ) && ISUNSIGNED(p->left->type) && p->right->op == ICON ){
+                       if( p->right->lval < 0 && p->right->rval == NONAME && !ISUNSIGNED(p->right->type) ){
+                               werror( "comparison of unsigned with negative constant" );
+                               }
+                       }
+               break;
+
+       case UGE:
+       case ULT:
+               if( p->right->op == ICON && p->right->lval == 0 && p->right->rval == NONAME ){
+                       werror( "unsigned comparison with 0?" );
+                       break;
+                       }
+       case UGT:
+       case ULE:
+               if( p->right->op == ICON && p->right->lval <= 0 && !ISUNSIGNED(p->right->type) && p->right->rval == NONAME ){
+                       werror( "degenerate unsigned comparison" );
+                       }
+               break;
+
+       case COMOP:
+               down1 = EFF;
+
+       case ANDAND:
+       case OROR:
+       case QUEST:
+               down2 = down;
+               /* go recursively left, then right  */
+               np1 = lnp;
+               lprt( p->left, down1, use1 );
+               np2 = lnp;
+               lprt( p->right, down2, use2 );
+               lmerge( np1, np2, 0 );
+               return;
+
+       case SCONV:
+       case PCONV:
+       case COLON:
+               down1 = down2 = down;
+               break;
+
+       case CALL:
+       case STCALL:
+       case FORTCALL:
+               acount = ctargs( p->right );
+       case UNARY CALL:
+       case UNARY STCALL:
+       case UNARY FORTCALL:
+               if( p->left->op == ICON && (id=p->left->rval) != NONAME ){ /* used to be &name */
+                       printf( "%.7s\t%03d\t%o\t%d\t",
+                               exname(stab[id].sname),
+                               down==EFF ? LUE : LUV,
+                               DECREF(p->left->type), acount );
+                       if( acount ) lpta( p->right );
+                       ident();
+                       }
+               break;
+
+       case ICON:
+               /* look for &name case */
+               if( (id = p->rval) >= 0 && id != NONAME ){
+                       q = &stab[id];
+                       q->sflags |= (SREF|SSET);
+                       }
+               return;
+
+       case NAME:
+               if( (id = p->rval) >= 0 && id != NONAME ){
+                       q = &stab[id];
+                       if( (uses&VALUSED) && !(q->sflags&SSET) ){
+                               if( q->sclass == AUTO || q->sclass == REGISTER ){
+                                       if( !ISARY(q->stype ) && !ISFTN(q->stype) && q->stype!=STRTY ){
+                                               werror( "%.7s may be used before set", q->sname );
+                                               q->sflags |= SSET;
+                                               }
+                                       }
+                               }
+                       if( uses & VALASGOP ) break;  /* not a real use */
+                       if( uses & VALSET ) q->sflags |= SSET;
+                       if( uses & VALUSED ) q->sflags |= SREF;
+                       if( uses & VALADDR ) q->sflags |= (SREF|SSET);
+                       if( p->lval == 0 ){
+                               lnp->lid = id;
+                               lnp->flgs = (uses&VALADDR)?0:((uses&VALSET)?VALSET:VALUSED);
+                               if( ++lnp >= &lnames[LNAMES] ) --lnp;
+                               }
+                       }
+               return;
+
+               }
+
+       /* recurse, going down the right side first if we can */
+
+       switch( optype(p->op) ){
+
+       case BITYPE:
+               np1 = lnp;
+               lprt( p->right, down2, use2 );
+       case UTYPE:
+               np2 = lnp;
+               lprt( p->left, down1, use1 );
+               }
+
+       if( optype(p->op) == BITYPE ){
+               if( p->op == ASSIGN && p->left->op == NAME ){ /* special case for a =  .. a .. */
+                       lmerge( np1, np2, 0 );
+                       }
+               else lmerge( np1, np2, p->op != COLON );
+               /* look for assignments to fields, and complain */
+               if( p->op == ASSIGN && p->left->op == FLD && p->right->op == ICON ) fldcon( p );
+               }
+
+       }
+
+lmerge( np1, np2, flag ) struct lnm *np1, *np2; {
+       /* np1 and np2 point to lists of lnm members, for the two sides
+        * of a binary operator
+        * flag is 1 if commutation is possible, 0 otherwise
+        * lmerge returns a merged list, starting at np1, resetting lnp
+        * it also complains, if appropriate, about side effects
+        */
+
+       register struct lnm *npx, *npy;
+
+       for( npx = np2; npx < lnp; ++npx ){
+
+               /* is it already there? */
+               for( npy = np1; npy < np2; ++npy ){
+                       if( npx->lid == npy->lid ){ /* yes */
+                               if( npx->flgs == 0 || npx->flgs == (VALSET|VALUSED) )
+                                       ;  /* do nothing */
+                               else if( (npx->flgs|npy->flgs)== (VALSET|VALUSED) ||
+                                       (npx->flgs&npy->flgs&VALSET) ){
+                                       if( flag ) werror( "%.8s evaluation order undefined", stab[npy->lid].sname );
+                                       }
+                               if( npy->flgs == 0 ) npx->flgs = 0;
+                               else npy->flgs |= npx->flgs;
+                               goto foundit;
+                               }
+                       }
+
+               /* not there: update entry */
+               np2->lid = npx->lid;
+               np2->flgs = npx->flgs;
+               ++np2;
+
+               foundit: ;
+               }
+
+       /* all finished: merged list is at np1 */
+       lnp = np2;
+       }
+
+efcode(){
+       /* code for the end of a function */
+       register struct symtab *cfp;
+
+       cfp = &stab[curftn];
+       if( retstat & RETVAL ){
+               printf( "%.7s\t%03d\t%o\t%d\t", exname(cfp->sname),
+                       LRV, DECREF( cfp->stype), 0 );
+               ident();
+               }
+       if( !vflag ){
+               vflag = argflag;
+               argflag = 0;
+               }
+       if( retstat == RETVAL+NRETVAL )
+               werror( "function %.8s has return(e); and return;", cfp->sname);
+       }
+
+aocode(p) struct symtab *p; {
+       /* called when automatic p removed from stab */
+       register struct symtab *cfs;
+       cfs = &stab[curftn];
+       if(p->suse>0 && !(p->sflags&SMOS) ){
+               if( p->sclass == PARAM ){
+                       if( vflag ) werror( "argument %.7s unused in function %.7s",
+                               p->sname,
+                               cfs->sname );
+                       }
+               else {
+                       if( p->sclass != TYPEDEF ) werror( "%.7s unused in function %.7s",
+                               p->sname, cfs->sname );
+                       }
+               }
+
+       if( p->suse < 0 && (p->sflags & (SSET|SREF|SMOS)) == SSET &&
+               !ISARY(p->stype) && !ISFTN(p->stype) ){
+
+               werror( "%.7s set but not used in function %.7s", p->sname, cfs->sname );
+               }
+
+       if( p->stype == STRTY || p->stype == UNIONTY || p->stype == ENUMTY ){
+               if( dimtab[p->sizoff+1] < 0 ) werror( "structure %.7s never defined", p->sname );
+               }
+
+       }
+
+defnam( p ) register struct symtab *p; {
+       /* define the current location as the name p->sname */
+
+       if( p->sclass == STATIC && p->slevel>1 ) return;
+
+       if( !ISFTN( p->stype ) ){
+               printf( "%.7s\t%03d\t%o\t%d\t",
+                       exname(p->sname), libflag?LIB:LDI, p->stype, 0 );
+               ident();
+               }
+       }
+
+zecode( n ){
+       /* n integer words of zeros */
+       OFFSZ temp;
+       temp = n;
+       inoff += temp*SZINT;
+       ;
+       }
+
+andable( p ) NODE *p; {  /* p is a NAME node; can it accept & ? */
+       register r;
+
+       if( p->op != NAME ) cerror( "andable error" );
+
+       if( (r = p->rval) < 0 ) return(1);  /* labels are andable */
+
+       if( stab[r].sclass == AUTO || stab[r].sclass == PARAM ) return(0); 
+       return(1);
+       }
+
+NODE *
+clocal(p) NODE *p; {
+
+       /* this is called to do local transformations on
+          an expression tree preparitory to its being
+          written out in intermediate code.
+       */
+
+       /* the major essential job is rewriting the
+          automatic variables and arguments in terms of
+          REG and OREG nodes */
+       /* conversion ops which are not necessary are also clobbered here */
+       /* in addition, any special features (such as rewriting
+          exclusive or) are easily handled here as well */
+
+       register o;
+       register unsigned t, tl;
+
+       switch( o = p->op ){
+
+       case SCONV:
+       case PCONV:
+               if( p->left->type==ENUMTY ){
+                       p->left = pconvert( p->left );
+                       }
+               /* assume conversion takes place; type is inherited */
+               t = p->type;
+               tl = p->left->type;
+               if( aflag && (tl==LONG||tl==ULONG) && (t!=LONG&&t!=ULONG) ){
+                       werror( "long assignment may lose accuracy" );
+                       }
+               if( ISPTR(tl) && ISPTR(t) ){
+                       tl = DECREF(tl);
+                       t = DECREF(t);
+                       switch( ISFTN(t) + ISFTN(tl) ){
+
+                       case 0:  /* neither is a function pointer */
+                               if( talign(t,p->csiz) > talign(tl,p->left->csiz) ){
+                                       if( hflag||pflag ) werror( "possible pointer alignment problem" );
+                                       }
+                               break;
+
+                       case 1:
+                               werror( "questionable conversion of function pointer" );
+
+                       case 2:
+                               ;
+                               }
+                       }
+               p->left->type = p->type;
+               p->left->cdim = p->cdim;
+               p->left->csiz = p->csiz;
+               p->op = FREE;
+               return( p->left );
+
+       case PVCONV:
+       case PMCONV:
+               if( p->right->op != ICON ) cerror( "bad conversion");
+               p->op = FREE;
+               return( buildtree( o==PMCONV?MUL:DIV, p->left, p->right ) );
+
+               }
+
+       return(p);
+       }
+
+NODE *
+offcon( off, t, d, s ) OFFSZ off; TWORD t;{  /* make a structure offset node */
+       register NODE *p;
+       p = bcon(0);
+       p->lval = off/SZCHAR;
+       return(p);
+       }
+
+noinit(){
+       /* storage class for such as "int a;" */
+       return( pflag ? EXTDEF : EXTERN );
+       }
+
+
+cinit( p, sz ) NODE *p; { /* initialize p into size sz */
+       inoff += sz;
+       if( p->op == INIT ){
+               if( p->left->op == ICON ) return;
+               if( p->left->op == NAME && p->left->type == MOE ) return;
+               }
+       uerror( "illegal initialization" );
+       }
+
+char *
+exname( p ) char *p; {
+       /* make a name look like an external name in the local machine */
+       static char aa[8];
+       register int i;
+
+       if( !pflag ) return(p);
+       for( i=0; i<6; ++i ){
+               if( isupper(*p ) ) aa[i] = tolower( *p );
+               else aa[i] = *p;
+               if( *p ) ++p;
+               }
+       aa[6] = '\0';
+       return( aa );
+       }
+
+where(f){ /* print true location of error */
+       if( f == 'u' && nerrors>1 ) --nerrors; /* don't get "too many errors" */
+       fprintf( stderr, "%s, line %d: ", ftitle, lineno );
+       }
+
+       /* a number of dummy routines, unneeded by lint */
+
+branch(n){;}
+defalign(n){;}
+deflab(n){;}
+bycode(t,i){;}
+cisreg(t){return(1);}  /* everyting is a register variable! */
+
+fldty(p) struct symtab *p; {
+       ; /* all types are OK here... */
+       }
+
+fldal(t) unsigned t; { /* field alignment... */
+       if( t == ENUMTY ) return( ALCHAR );  /* this should be thought through better... */
+       if( ISPTR(t) ){ /* really for the benefit of honeywell (and someday IBM) */
+               if( pflag ) uerror( "nonportable field type" );
+               }
+       else uerror( "illegal field type" );
+       return(ALINT);
+       }
+
+main( argc, argv ) char *argv[]; {
+       char *p;
+
+       /* handle options */
+
+       for( p=argv[1]; *p; ++p ){
+
+               switch( *p ){
+
+               case '-':
+                       continue;
+
+               case 'L':  /* produced by driver program */
+                       flabel = p;
+                       goto break2;
+
+               case '\0':
+                       break;
+
+               case 'b':
+                       brkflag = 1;
+                       continue;
+
+               case 'p':
+                       pflag = 1;
+                       continue;
+
+               case 'c':
+                       cflag = 1;
+                       continue;
+
+               case 's':
+                       /* for the moment, -s triggers -h */
+
+               case 'h':
+                       hflag = 1;
+                       continue;
+
+               case 'v':
+                       vflag = 0;
+                       continue;
+
+               case 'x':
+                       xflag = 1;
+                       continue;
+
+               case 'a':
+                       aflag = 1;
+               case 'u':       /* done in second pass */
+               case 'n':       /* done in shell script */
+                       continue;
+
+               case 't':
+                       werror( "option %c now default: see `man 6 lint'", *p );
+                       continue;
+
+               default:
+                       uerror( "illegal option: %c", *p );
+                       continue;
+
+                       }
+               }
+
+       break2:
+       if( !pflag ){  /* set sizes to sizes of target machine */
+# ifdef gcos
+               SZCHAR = ALCHAR = 9;
+# else
+               SZCHAR = ALCHAR = 8;
+# endif
+               SZINT = ALINT = sizeof(int)*SZCHAR;
+               SZFLOAT = ALFLOAT = sizeof(float)*SZCHAR;
+               SZDOUBLE = ALDOUBLE = sizeof(double)*SZCHAR;
+               SZLONG = ALLONG = sizeof(long)*SZCHAR;
+               SZSHORT = ALSHORT = sizeof(short)*SZCHAR;
+               SZPOINT = ALPOINT = sizeof(int *)*SZCHAR;
+               ALSTRUCT = ALINT;
+               /* now, fix some things up for various machines (I wish we had "alignof") */
+
+# ifdef pdp11
+               ALLONG = ALDOUBLE = ALFLOAT = ALINT;
+#endif
+# ifdef ibm
+               ALSTRUCT = ALCHAR;
+#endif
+               }
+
+       return( mainp1( argc, argv ) );
+       }
+
+ctype( type ) unsigned type; { /* are there any funny types? */
+       return( type );
+       }
+
+commdec( i ){
+       /* put out a common declaration */
+       register struct symtab *p;
+       p = &stab[i];
+       printf( "%.7s\t%03d\t%o\t%d\t", exname(p->sname), libflag?LIB:LDC, p->stype, 0 );
+       ident();
+       }
+
+isitfloat ( s ) char *s; {
+       /* s is a character string;
+          if floating point is implemented, set dcon to the value of s */
+       /* lint version
+       */
+       dcon = atof( s );
+       return( FCON );
+       }
+
+fldcon( p ) register NODE *p; {
+       /* p is an assignment of a constant to a field */
+       /* check to see if the assignment is going to overflow, or otherwise cause trouble */
+       register s;
+       CONSZ v;
+
+       if( !hflag & !pflag ) return;
+
+       s = UPKFSZ(p->left->rval);
+       v = p->right->lval;
+
+       switch( p->left->type ){
+
+       case CHAR:
+       case INT:
+       case SHORT:
+       case LONG:
+       case ENUMTY:
+               if( v>=0 && (v>>(s-1))==0 ) return;
+               werror( "precision lost in assignment to (possibly sign-extended) field" );
+       default:
+               return;
+
+       case UNSIGNED:
+       case UCHAR:
+       case USHORT:
+       case ULONG:
+               if( v<0 || (v>>s)!=0 ) werror( "precision lost in field assignment" );
+               
+               return;
+               }
+
+       }
diff --git a/usr/src/cmd/lint/llib-lc b/usr/src/cmd/lint/llib-lc
new file mode 100644 (file)
index 0000000..ebff38e
--- /dev/null
@@ -0,0 +1,105 @@
+       /* LINTLIBRARY */
+#include <stdio.h>
+#include <sgtty.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+int    errno;
+int    alarm(s) unsigned s; { return(s); }
+char   *brk(a) char *a; { return(a); }
+int    chdir(s) char *s; { return(0); }
+int    chmod(s, m) char *s; { return(0); }
+int    chown(s, u, g) char *s; { return(0); }
+int    close(f) { return(0); }
+int    creat(s, m) char *s; { return(0); }
+int    dup(f) { return(f); }
+       /* VARARGS */
+       execl(f, a) char *f, *a; {;}
+       execv(s, v) char *s, *v[]; {;}
+       exit(s) {;}
+int    fork() { return(0); }
+int    fstat(f, b) struct stat *b; { return(0); }
+int    getgid() { return(1); }
+int    getegid() { return(1); }
+int    getpid() { return(1); }
+int    getuid() { return(1); }
+int    geteuid() { return(1); }
+int    gtty(f, b) struct sgttyb *b; { return(0); }
+int    kill(p, s) { return(0); }
+int    link(a, b) char *a, *b; { return(0); }
+long   lseek(f, o, d) long o; { return(0); }
+int    mknod(n, m, a) char *n; { return(0); }
+char   *mktemp(p) char *p; { return(p);}
+int    mount(s, n, f) char *s, *n; { return(0); }
+int    nice(p) { return(0); }
+int    open(f, m) char *f; { return(0); }
+       pause() {;}
+int    pipe(f) int f[2]; { return(0); }
+       profil(b, s, o, i) char *b; {;}
+int    ptrace(r, p, a, d) { return(0); }
+int    read(f, b, l) char *b; { return(l); }
+char   *sbrk(i) { return((char *)0); }
+int    seek(f, o, p) { return(0); }
+int    setgid(g) { return(0); }
+int    setuid(u) { return(0); }
+int    (*signal(c, f))() int (*f)(); { return(f); }
+int    stat(s, b) char *s; struct stat *b; { return(0); }
+char   *strcat(a, b) char *a, *b; { ; }
+int    strcmp(a, b) char *a, *b; { return(1); }
+char   *strcpy(a, b) char *a, *b; { ; }
+int    strlen(s) char *s; { return(1); }
+int    stty(f, b) struct sgttyb *b; { return(0); }
+long   tell(f) { return((long)0); }
+int    system(s) char *s; { return(0); }
+time_t time(t) time_t *t; { return( 0 );}
+int    unlink(s) char *s; { return(0); }
+int    wait(s) int *s; { return(1); }
+int    write(f, b, l) char *b; { return(l); }
+char   *calloc(n,s) unsigned n, s; { static char c[1]; return(c); }
+char   *malloc(n) unsigned n; {static char c; return(&c);}
+char   *realloc(p, n) char *p; unsigned n; { static char c; return(&c);}
+       free(p) char *p; {;}
+       fclose(f) FILE *f; {return(0);}
+       fflush(f) FILE *f; {return(0);}
+char   *fgets( s, l, f ) char *s; FILE *f; { return(s); }
+FILE   *fopen(s,m) char *s, *m; { return(stdin); }
+FILE   *freopen(s, m, f) char *s, *m; FILE *f; { return(stdin); }
+FILE   *fdopen(fd, m) char *m; { return(stdin);}
+       /* VARARGS */
+       fprintf( f, s ) FILE *f; char *s; {;}
+       fputs(s,f) char *s; FILE *f; {;}
+       fread( p, s, n, f ) char *p; FILE *f; {return(1);}
+       /* VARARGS */
+       fscanf( f, s ) FILE *f; char *s; {return(1);}
+int    fwrite( p, s, n, f ) char *p; FILE *f; {return(0);}
+       intss(){return(1); }
+       /* VARARGS */
+       printf( s ) char *s; {;}
+       rewind(f) FILE *f; {;}
+       /* VARARGS */
+       scanf( f ) char *f; {return(1); }
+       setbuf( f, b ) FILE *f; char *b; {;}
+       /* VARARGS */
+char   *sprintf( s, f ) char *s, *f; { return(s);}
+       /* VARARGS */
+       sscanf( s, f ) char *s, *f; { return(1); }
+       ungetc( c, f ) FILE *f; {  return(c); }
+char   *ctime(c) time_t *c;{ return(""); }
+struct tm *localtime(c) time_t *c; { return localtime(c); }
+struct tm *gmtime(c) time_t *c; { return gmtime(c); }
+char   *asctime(t) struct tm *t; { return(""); }
+       abort() {}
+int    abs(i) int i; { return(i); }
+double atof(s) char *s; { return(1.); }
+char   *crypt(k,s) char *k, *s; { return(""); }
+       setkey(k) char *k; {}
+       encrypt(s, i) char *s; {}
+char   *ecvt(v, n, d, s) double v; int *d, *s; { return(""); }
+char   *fcvt(v, n, d, s) double v; int *d, *s; { return(""); }
+char   *gcvt(v, n, b) double v; char *b; { return(""); }
+       monitor(l, h, b, s, n) int (*l)(), (*h)(); short *b; {}
+       perror(s) char *s; {}
+       setjmp(e) int e[3]; { return(0); }
+       sleep(i) unsigned i; {}
+struct _iobuf _iob[_NFILE];
+char   _ctype_[];
diff --git a/usr/src/cmd/lint/llib-port b/usr/src/cmd/lint/llib-port
new file mode 100644 (file)
index 0000000..c4773af
--- /dev/null
@@ -0,0 +1,44 @@
+       /* LINTLIBRARY */
+#include <stdio.h>
+       exit(s) {;}
+long   lseek(f, o, d) long o; { return(0); }
+char   *mktemp(p) char *p; { return(p);}
+int    (*signal(c, f))() int (*f)(); { return(f); }
+char   *strcat(a, b) char *a, *b; { ; }
+int    strcmp(a, b) char *a, *b; { return(1); }
+char   *strcpy(a, b) char *a, *b; { ; }
+int    strlen(s) char *s; { return(1); }
+long   tell(f) { return((long)0); }
+long   time(t) long *t; { return(0);}
+char   *calloc(n,s) unsigned n, s; { static char c[1]; return(c); }
+char   *malloc(n) unsigned n; {static char c; return(&c);}
+char   *realloc(p, n) char *p; unsigned n; { static char c; return(&c);}
+       free(p) char *p; {;}
+       fclose(f) FILE *f; {return(0);}
+       fflush(f) FILE *f; {return(0);}
+char   *fgets( s, l, f ) char *s; FILE *f; { return(s); }
+FILE   *fopen(s,m) char *s, *m; { return(stdin); }
+FILE   *freopen(s, m, f) char *s, *m; FILE *f; { return(stdin); }
+FILE   *fdopen(fd, m) char *m; { return(stdin);}
+       /* VARARGS */
+       fprintf( f, s ) FILE *f; char *s; {;}
+       fputs(s,f) char *s; FILE *f; {;}
+       fread( p, s, n, f ) char *p; FILE *f; {return(1);}
+       /* VARARGS */
+       fscanf( f, s ) FILE *f; char *s; {return(1);}
+int    fwrite( p, s, n, f ) char *p; FILE *f; {return(0);}
+       intss(){return(1); }
+       /* VARARGS */
+       printf( s ) char *s; {;}
+       rewind(f) FILE *f; {;}
+       /* VARARGS */
+       scanf( f ) char *f; {return(1); }
+       setbuf( f, b ) FILE *f; char *b; {;}
+       /* VARARGS */
+char   *sprintf( s, f ) char *s, *f; { return(s);}
+       /* VARARGS */
+       sscanf( s, f ) char *s, *f; { return(1); }
+       ungetc( c, f ) FILE *f; {  return(c); }
+       wdleng(){return(0); }
+struct _iobuf _iob[_NFILE];
+char   _ctype_[129];
diff --git a/usr/src/cmd/lint/lmanifest b/usr/src/cmd/lint/lmanifest
new file mode 100644 (file)
index 0000000..2a6ed88
--- /dev/null
@@ -0,0 +1,18 @@
+/*     the key:
+       LDI     defined and initialized: storage set aside
+       LIB     defined on a library
+       LDC     defined as a common region on UNIX
+       LDX     defined by an extern: if ! pflag, same as LDI
+       LRV     function returns a value
+       LUV     function used in a value context
+       LUE     function used in effects context
+       LUM     mentioned somewhere other than at the declaration
+       */
+# define LDI 01
+# define LIB 02
+# define LDC 04
+# define LDX 010
+# define LRV 020
+# define LUV 040
+# define LUE 0100
+# define LUM 0200
diff --git a/usr/src/cmd/lint/lpass2.c b/usr/src/cmd/lint/lpass2.c
new file mode 100644 (file)
index 0000000..5c20864
--- /dev/null
@@ -0,0 +1,367 @@
+# include "lmanifest"
+# include "manifest"
+
+# define USED 01
+# define VUSED 02
+# define EUSED 04
+# define RVAL 010
+# define VARARGS 0100
+
+typedef struct { TWORD aty; int extra; } atype;
+
+struct line {
+       char name[8];
+       int decflag;
+       atype type;
+       int nargs;
+       atype atyp[50];
+       int fline;
+       char file[100];
+       }
+
+       l1,
+       l2,
+       *pd,    /* pointer to line having definition */
+       *pc,    /* pointer to current line read */
+       *p3;    /* used for swapping pc and pd */
+
+int uses = USED;
+int hflag = 0;
+int pflag = 0;
+int xflag = 0;
+int uflag = 1;
+
+
+main( argc, argv ) char *argv[]; {
+
+       register char *p;
+
+       /* first argument is - options */
+
+       if( argc>=2 && argv[1][0] == '-' ){
+               for( p=argv[1]; *p; ++p ){
+                       switch( *p ){
+
+                       case 'h':
+                               hflag = 1;
+                               break;
+
+                       case 'p':
+                               pflag = 1;
+                               break;
+
+                       case 'x':
+                               xflag = 1;
+                               break;
+
+                       case 'u':
+                               uflag = 0;
+                               break;
+
+                               }
+                       }
+               }
+
+
+
+       pd = &l1;
+       pc = &l2;
+       pd->name[0] = '\0' ;
+       pd->fline = 0;
+       pd->file[0] = '\0';
+       pd->decflag = LDI;
+
+       /* main loop: read a line;
+               if same as last line, check compatibility
+               if not same as last line, becomes df.
+               */
+
+       for(;;){
+               lread();
+               if( steq(pc->name, pd->name) ) chkcompat();
+               else {
+                       lastone();
+                       setuse();
+                       p3=pc;
+                       pc = pd;
+                       pd = p3;
+                       }
+               }
+
+       }
+
+lread(){ /* read a line into pc */
+
+       register i, n;
+
+       getnam( pc->name );
+
+       pc->decflag = rdin10();
+       rdinty( &pc->type );
+       n = pc->nargs = rdin10();
+       if( n<0 ) n = -n;
+
+       for( i=0; i<n; ++i ){
+               rdinty( &pc->atyp[i] );
+               }
+
+       getnam( pc->file );
+       pc->fline = rdin10();
+
+       while( getchar() != '\n' ) ; /* VOID */
+       }
+
+rdin10(){
+       register val, c, s;
+
+       val = 0;
+       s = 1;
+
+       while( (c=getchar()) != '\t' ){
+               if( c <= 0 ) error( "unexpected EOF" );
+               else if( c == '-' ) {
+                       s = -1;
+                       continue;
+                       }
+               else if( c<'0' || c>'9' ) {
+                       error("rotten digit: %o\n", c );
+                       }
+               val = val*10 + c - '0';
+               }
+       return( val*s );
+       }
+
+rdinty( p ) atype *p; {
+       register val, c, s;
+
+       val = 0;
+       s = 1;
+
+       while( (c=getchar()) != '\t' && c!= '<' ){
+               if( c <= 0 ) error( "unexpected EOF" );
+               else if( c == '-' ) {
+                       s = -1;
+                       continue;
+                       }
+               else if( c<'0' || c>'7' ) {
+                       error("rotten digit: %o\n", c );
+                       }
+               val = (val<<3) + c - '0';
+               }
+       p->aty = val*s;
+       if( c == '<' ) p->extra = rdin10();
+       else p->extra = 0;
+       }
+
+getnam(p) char *p; {
+       register c;
+       while( (c=getchar()) != '\t' ){
+               if( c == '\n' ) error( "rotten name\n" );
+               if( c <= 0 ) cleanup();
+               *p++ = c;
+               }
+       *p = '\0';
+       }
+
+/* VARARGS */
+error( s, a ) char *s; {
+
+       fprintf( stderr, "pass 2 error: " );
+       fprintf( stderr, s, a );
+       fprintf( stderr, "\n" );
+       exit(1);
+       }
+
+steq(p,q) char *p,*q; { /* check that the p and q names are the same */
+
+
+       while( *p == *q ){
+               if( *p == 0 ) return(1);
+               ++p;
+               ++q;
+               }
+
+       return(0);
+       }
+
+chkcompat(){
+       /* are the types, etc. in pc and pd compatible */
+       register int i;
+
+       setuse();
+
+       /* argument check */
+
+       if( pd->decflag & (LDI|LIB|LUV|LUE) ){
+               if( pc->decflag & (LUV|LIB|LUE) ){
+                       if( pd->nargs != pc->nargs ){
+                               if( !(uses&VARARGS) ){
+                                       printf( "%.7s: variable # of args.", pd->name );
+                                       viceversa();
+                                       }
+                               if( pc->nargs > pd->nargs ) pc->nargs = pd->nargs;
+                               if( !(pd->decflag & (LDI|LIB) ) ) {
+                                       pd->nargs = pc->nargs;
+                                       uses |= VARARGS;
+                                       }
+                               }
+                       for( i=0; i<pc->nargs; ++i ){
+                               if( chktype(&pd->atyp[i], &pc->atyp[i]) ){
+                                       printf( "%.7s, arg. %d used inconsistently",
+                                               pd->name, i+1 );
+                                       viceversa();
+                                       }
+                               }
+                       }
+               }
+
+       if( (pd->decflag&(LDI|LIB|LUV)) && pc->decflag==LUV ){
+               if( chktype( &pc->type, &pd->type ) ){
+                       printf( "%.7s value used inconsistently", pd->name );
+                       viceversa();
+                       }
+               }
+
+       /* check for multiple declaration */
+
+       if( (pd->decflag&LDI) && (pc->decflag&(LDI|LIB)) ){
+               printf( "%.7s multiply declared", pd->name );
+               viceversa();
+               }
+
+       /* do a bit of checking of definitions and uses... */
+
+       if( (pd->decflag & (LDI|LIB|LDX|LDC)) && (pc->decflag & (LDX|LDC)) && pd->type.aty != pc->type.aty ){
+               printf( "%.7s value declared inconsistently", pd->name );
+               viceversa();
+               }
+
+       /* better not call functions which are declared to be structure or union returning */
+
+       if( (pd->decflag & (LDI|LIB|LDX|LDC)) && (pc->decflag & LUE) && pd->type.aty != pc->type.aty ){
+               /* only matters if the function returns union or structure */
+               TWORD ty;
+               ty = pd->type.aty;
+               if( ISFTN(ty) && ((ty = DECREF(ty))==STRTY || ty==UNIONTY ) ){
+                       printf( "%.7s function value type must be declared before use", pd->name );
+                       viceversa();
+                       }
+               }
+
+       if( pflag && pd->decflag==LDX && pc->decflag == LUM && !ISFTN(pd->type.aty) ){
+               /* make the external declaration go away */
+               /* in effect, it was used without being defined */
+
+               /* swap pc and pd */
+               p3 = pc;
+               pc = pd;
+               pd = p3;
+               }
+
+       }
+
+viceversa(){
+       /* print out file comparison */
+       printf( "       %s(%d)  ::  %s(%d)\n", pd->file, pd->fline, pc->file, pc->fline );
+       }
+
+       /* messages for defintion/use */
+char *
+mess[2][2] = {
+       "",
+       "%.7s used( %s(%d) ), but not defined\n",
+       "%.7s defined( %s(%d) ), but never used\n",
+       "%.7s declared( %s(%d) ), but never used or defined\n"
+       };
+
+lastone(){
+
+       /* called when pc and pd are at last different */
+       register nu, nd;
+
+       nu = nd = 0;
+
+       if( !(uses&USED) && pd->decflag != LIB ) {
+               if( !steq(pd->name,"main") )
+                       nu = 1;
+               }
+
+       if( !ISFTN(pd->type.aty) ){
+               switch( pd->decflag ){
+
+               case LIB:
+                       nu = nd = 0;  /* don't complain about uses on libraries */
+                       break;
+               case LDX:
+                       if( !xflag ) break;
+               case LUV:
+               case LUE:
+               case LUM:
+                       nd = 1;
+                       }
+               }
+
+       if( uflag && ( nu || nd ) ) printf( mess[nu][nd], pd->name, pd->file, pd->fline );
+
+       if( (uses&(RVAL+EUSED)) == (RVAL+EUSED) ){
+               printf( "%.7s returns value which is %s ignored\n", pd->name,
+                       uses&VUSED ? "sometimes" : "always" );
+               }
+
+       if( (uses&(RVAL+VUSED)) == (VUSED) && (pd->decflag&(LDI|LIB)) ){
+               printf( "%.7s value is used, but none returned\n", pd->name );
+               }
+
+       /* clean up pc, in preparation for the next thing */
+
+       uses = 0;
+       if( pc->nargs < 0 ){
+               pc->nargs = -pc->nargs;
+               uses = VARARGS;
+               }
+
+       }
+
+cleanup(){ /* call lastone and die gracefully */
+       lastone();
+       exit(0);
+       }
+
+setuse(){ /* check new type to ensure that it is used */
+
+       switch( pc->decflag ){
+
+       case LRV:
+               uses |= RVAL;
+               return;
+       case LUV:
+               uses |= VUSED+USED;
+               return;
+       case LUE:
+               uses |= EUSED+USED;
+               return;
+       case LUM:
+               uses |= USED;
+               return;
+
+               }
+       }
+
+chktype( pt1, pt2 ) register atype *pt1, *pt2; {
+
+       /* check the two type words to see if they are compatible */
+       /* for the moment, enums are turned into ints, and should be checked as such */
+       if( pt1->aty == ENUMTY ) pt1->aty =  INT;
+       if( pt2->aty == ENUMTY ) pt2->aty = INT;
+
+       if( pt2->extra ){ /* constant passed in */
+               if( pt1->aty == UNSIGNED && pt2->aty == INT ) return( 0 );
+               else if( pt1->aty == ULONG && pt2->aty == LONG ) return( 0 );
+               }
+       else if( pt1->extra ){ /* for symmetry */
+               if( pt2->aty == UNSIGNED && pt1->aty == INT ) return( 0 );
+               else if( pt2->aty == ULONG && pt1->aty == LONG ) return( 0 );
+               }
+
+       return( pt1->aty != pt2->aty );
+       }
diff --git a/usr/src/cmd/lint/macdefs b/usr/src/cmd/lint/macdefs
new file mode 100644 (file)
index 0000000..3ec81bc
--- /dev/null
@@ -0,0 +1,71 @@
+# define makecc(val,i)  lastcon |= val<<(8*i);  /* pdp-11 womp next char  */
+
+# define  ARGINIT 288 /* initial offset for arguments */
+# define  AUTOINIT 0   /* initial automatic offset */
+extern int  SZCHAR;
+extern int  SZINT;
+extern int  SZFLOAT;
+extern int  SZDOUBLE;
+extern int  SZLONG;
+extern int  SZSHORT;
+extern int SZPOINT;
+extern int ALCHAR;
+extern int ALINT;
+extern int ALFLOAT;
+extern int ALDOUBLE;
+extern int ALLONG;
+extern int ALSHORT;
+extern int ALPOINT;
+extern int ALSTRUCT;
+# define SAVEADJUST 0 /* bits of adjustment required for stackframe */
+
+
+/* type (INT OR LONG) big enough to hold pointers */
+
+
+/*     size in which constants are converted */
+/*     should be long if feasable */
+
+# define CONSZ long
+# define CONFMT "%Ld"
+# define CONOFMT "%Lo"
+
+/*     size in which offsets are kept
+/*     should be large enough to cover address space in bits
+*/
+
+# define OFFSZ long
+
+/*     character set macro */
+
+# define  CCTRANS(x) x
+
+/*     register cookie for stack pointer */
+
+# define STKREG 9
+
+/*     maximum and minimum register variable values */
+
+# define MAXRVAR 1000
+# define MINRVAR 1
+
+/* many macro definitions for functions irrelevant to lint */
+
+# define locctr(n) 0
+# define getlab() 10
+# define genswitch( x,y)
+# define bccode()
+# define cendarg()
+# define incode(a,s) (inoff += (s))
+# define fincode(a,s) (inoff += (s) )
+# define vfdzero(n) (inoff += (n))
+# define aobeg()
+# define aoend()
+
+# ifndef unix
+# define NOFORTRAN  {extern int pflag; if(pflag) werror( "fortran keyword nonportable" );}
+# else
+# define NOFORTRAN { werror( "fortran keyword nonportable" ); }
+# endif
+
+# define LINT
diff --git a/usr/src/cmd/m4/m4.c b/usr/src/cmd/m4/m4.c
new file mode 100644 (file)
index 0000000..3e6ce5b
--- /dev/null
@@ -0,0 +1,899 @@
+#include <stdio.h>
+#include <signal.h>
+
+#define ERROR NULL
+#define        READ    "r"
+#define        WRITE   "w"
+
+#define        EOS     0
+int    lpar    = '(';
+#define        LPAR    lpar
+#define        RPAR    ')'
+#define        COMMA   ','
+#define        GRAVE   '`'
+#define        ACUTE   '\''
+#define LBRAK  '['
+#define RBRAK  ']'
+#ifdef  M4
+char   lquote  LBRAK;
+char   rquote  RBRAK;
+#endif
+#ifndef M4
+char   lquote  = GRAVE;
+char   rquote  = ACUTE;
+#endif
+#define        COMMENT '#'
+#define        ALPH    1
+#define        DIG     2
+
+#define        HSHSIZ  199     /* prime */
+#define        STACKS  50
+#define        SAVS    4096
+#define        TOKS    128
+
+#define        putbak(c)       *ip++ = c;
+#define        getchr()        (ip>cur_ip?*--ip: getc(infile[infptr]))
+#define        putchr(c)       if (cp==NULL) {if (curfile)putc(c,curfile);} else *op++ = c
+char   type[] = {
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       0,      0,      0,      0,      0,      0,      0,      0,
+       DIG,    DIG,    DIG,    DIG,    DIG,    DIG,    DIG,    DIG,
+       DIG,    DIG,    0,      0,      0,      0,      0,      0,
+       0,      ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,
+       ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,
+       ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,
+       ALPH,   ALPH,   ALPH,   0,      0,      0,      0,      ALPH,
+       0,      ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,
+       ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,
+       ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,   ALPH,
+       ALPH,   ALPH,   ALPH,   0,      0,      0,      0,      0,
+};
+
+char   token[TOKS];
+char   eoa[]   = "\0";
+struct nlist {
+       char    *name;
+       char    *def;
+       struct  nlist *next;
+};
+
+struct nlist   *hshtab[HSHSIZ];
+char   ibuf[SAVS+TOKS];
+char   obuf[SAVS+TOKS];
+char   *op     = obuf;
+char   *ip     = ibuf;
+char *ip_stk[10] = {ibuf};
+char *cur_ip = ibuf;
+struct call {
+       char    **argp;
+       int     plev;
+};
+struct call    *cp = NULL;
+
+char   *makeloc;
+char   *ifdefloc;
+char   *lenloc;
+char   *undefloc;
+char   *shiftloc;
+char   *cqloc;
+char   *defloc;
+char   *evaloc;
+char   *incrloc;
+char   *substrloc;
+char   *indexloc;
+char   *transloc;
+char   *ifloc;
+char   *divloc;
+char   *divnumloc;
+char   *undivloc;
+char   *dnlloc;
+char   *inclloc;
+char   *sinclloc;
+char   *syscmdloc;
+char   *dumploc;
+char   *errploc;
+
+char   *tempname;
+struct nlist   *lookup();
+char   *install();
+char   *malloc();
+char   *mktemp();
+char   *copy();
+long   ctol();
+int    hshval;
+FILE   *olist[11] = { stdout };
+int    okret;
+int    curout  = 0;
+FILE   *curfile = { stdout };
+FILE   *infile[10] = { stdin };
+int    infptr  = 0;
+
+main(argc, argv)
+char **argv;
+{
+       char *argstk[STACKS+10];
+       struct call callst[STACKS];
+       register char *tp, **ap;
+       int delexit(), catchsig();
+       register t;
+       int i;
+
+#ifdef gcos
+#ifdef M4
+       install("GCOS", eoa);
+#endif
+#ifndef M4
+       install("gcos", eoa);
+#endif
+#endif
+#ifdef unix
+#ifdef M4
+       install("UNIX", eoa);
+#endif
+#ifndef M4
+       install("unix", eoa);
+#endif
+#endif
+
+#ifdef M4
+       makeloc = install("MAKETEMP", eoa);
+       ifdefloc = install("IFDEF", eoa);
+       lenloc = install("LEN", eoa);
+       undefloc = install("UNDEFINE", eoa);
+       shiftloc = install("SHIFT", eoa);
+       cqloc = install("CHANGEQUOTE", eoa);
+       defloc = install("DEFINE", eoa);
+       evaloc = install("EVAL", eoa);
+       inclloc = install("INCLUDE", eoa);
+       sinclloc = install("SINCLUDE", eoa);
+       syscmdloc = install("SYSCMD", eoa);
+       dumploc = install("DUMPDEF", eoa);
+       errploc = install("ERRPRINT", eoa);
+       incrloc = install("INCR", eoa);
+       substrloc = install("SUBSTR", eoa);
+       indexloc = install("INDEX", eoa);
+       transloc = install("TRANSLIT", eoa);
+       ifloc = install("IFELSE", eoa);
+       divloc = install("DIVERT", eoa);
+       divnumloc = install("DIVNUM", eoa);
+       undivloc = install("UNDIVERT", eoa);
+       dnlloc = install("DNL", eoa);
+#endif
+
+#ifndef M4
+       makeloc = install("maketemp", eoa);
+       ifdefloc = install("ifdef", eoa);
+       lenloc = install("len", eoa);
+       undefloc = install("undefine", eoa);
+       shiftloc = install("shift", eoa);
+       cqloc = install("changequote", eoa);
+       defloc = install("define", eoa);
+       evaloc = install("eval", eoa);
+       inclloc = install("include", eoa);
+       sinclloc = install("sinclude", eoa);
+       syscmdloc = install("syscmd", eoa);
+       dumploc = install("dumpdef", eoa);
+       errploc = install("errprint", eoa);
+       incrloc = install("incr", eoa);
+       substrloc = install("substr", eoa);
+       indexloc = install("index", eoa);
+       transloc = install("translit", eoa);
+       ifloc = install("ifelse", eoa);
+       divloc = install("divert", eoa);
+       divnumloc = install("divnum", eoa);
+       undivloc = install("undivert", eoa);
+       dnlloc = install("dnl", eoa);
+#endif
+       ap = argstk;
+#ifndef gcos
+       if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
+               signal(SIGHUP, catchsig);
+       if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+               signal(SIGINT, catchsig);
+       tempname = mktemp("/tmp/m4aXXXXX");
+       close(creat(tempname, 0));
+#endif
+#ifdef gcos
+       tempname = "m4.tempa";
+#endif
+       if (argc>1)
+               putbak(0);
+       for (;;) {
+               tp = token;
+               *tp++ = t = getchr();
+               *tp = EOS;
+               if (t<=0) {
+                       if (infptr > 0) {
+                               fclose(infile[infptr]);
+                               infptr--;
+                               cur_ip = ip_stk[infptr];
+                               continue;
+                       }
+                       if (argc<=1)
+                               break;
+                       argc--;
+                       argv++;
+                       if (infile[infptr]!=stdin)
+                               fclose(infile[infptr]);
+                       if (**argv=='-')
+                               infile[infptr] = stdin;
+                       else if ((infile[infptr]=fopen(argv[0], READ))==ERROR) {
+                               fprintf(stderr, "m4: file not found: %s\n", argv[0]);
+                               delexit();
+                       }
+                       continue;
+               }
+               if (type[t]==ALPH) {
+                       while ((t=type[*tp++=getchr()])==ALPH||t==DIG);
+                       putbak(*--tp);
+                       *tp = EOS;
+                       if (*ap = lookup(token)->def) {
+                               if (++ap >= &argstk[STACKS]) {
+                                       fprintf(stderr, "m4: arg stack overflow\n");
+                                       delexit();
+                               }
+                               if (cp==NULL)
+                                       cp = callst;
+                               else if (++cp > &callst[STACKS]) {
+                                       fprintf(stderr, "m4: call stack overflow\n");
+                                       delexit();
+                               }
+                               cp->argp = ap;
+                               *ap++ = op;
+                               puttok();
+                               *op++ = '\0';
+                               t = getchr();
+                               putbak(t);
+                               if (t!=LPAR) {
+                                       /* if (t!=' ' && t!='\t') */
+                                               putbak(')');
+                                       putbak('(');
+                               }
+                               else    /* try to fix arg count */
+                                       *ap++ = op;
+                               cp->plev = 0;
+                       } else
+                               puttok();
+               } else if (t==lquote) {
+                       i = 1;
+                       for (;;) {
+                               t = getchr();
+                               if (t==rquote) {
+                                       i--;
+                                       if (i==0)
+                                               break;
+                               } else if (t==lquote)
+                                       i++;
+                               else if (t<0) {
+                                       fprintf(stderr, "m4: EOF in string\n");
+                                       delexit();
+                               }
+                               putchr(t);
+                       }
+               } else if (t==COMMENT) {
+                       putbak(t);
+                       while ((t = getchr())!='\n'&& t>=0)
+                               if (cp==NULL)
+                                       putchr(t);
+                       putbak(t);
+               } else if (cp==NULL) {
+                       puttok();
+               } else if (t==LPAR) {
+                       if (cp->plev)
+                               *op++ = t;
+                       cp->plev++;
+                       while ( (t=getchr())==' ' || t=='\t' || t=='\n')
+                               ;       /* skip leading white space during arg collection */
+                       putbak(t);
+/*
+               } else if (t==' ' || t=='\t' || t=='\n') {
+                       continue;
+*/
+               } else if (t==RPAR) {
+                       cp->plev--;
+                       if (cp->plev==0) {
+                               *op++ = '\0';
+                               expand(cp->argp, ap-cp->argp-1);
+                               op = *cp->argp;
+                               ap = cp->argp-1;
+                               cp--;
+                               if (cp < callst)
+                                       cp = NULL;
+                       } else
+                               *op++ = t;
+               } else if (t==COMMA && cp->plev<=1) {
+                       *op++ = '\0';
+                       *ap++ = op;
+                       while ((t=getchr())==' ' || t=='\t' || t=='\n')
+                               ;       /* skip leading white space during arg collection */
+                       putbak(t);
+               } else
+                       *op++ = t;
+       }
+       if (cp!=NULL) {
+               fprintf(stderr, "m4: unexpected EOF\n");
+               delexit();
+       }
+       okret = 1;
+       delexit();
+}
+
+catchsig()
+{
+       okret = 0;
+       delexit();
+}
+
+delexit()
+{
+       register FILE *fp;
+       register i, c;
+
+       if (!okret) {
+               signal(SIGHUP, SIG_IGN);
+               signal(SIGINT, SIG_IGN);
+       }
+       for (i=1; i<10; i++) {
+               if (olist[i]==NULL)
+                       continue;
+               fclose(olist[i]);
+               tempname[7] = 'a'+i;
+               if (okret) {
+                       fp = fopen(tempname, READ);
+                       while ((c = getc(fp)) > 0)
+                               putchar(c);
+                       fclose(fp);
+               }
+               unlink(tempname);
+       }
+       tempname[7] = 'a';
+       unlink(tempname);
+       exit(1-okret);
+}
+
+puttok()
+{
+       register char *tp;
+
+       tp = token;
+       if (cp) {
+               if (op >= &obuf[SAVS]) {
+                       fprintf(stderr, "m4: argument overflow\n");
+                       delexit();
+               }
+               while (*tp)
+                       *op++ = *tp++;
+       } else if (curfile)
+               while (*tp)
+                       putc(*tp++, curfile);
+}
+
+pbstr(str)
+register char *str;
+{
+       register char *p;
+
+       p = str;
+       while (*p++);
+       --p;
+       if (ip >= &ibuf[SAVS]) {
+               fprintf(stderr, "m4: pushback overflow\n");
+               delexit();
+       }
+       while (p > str)
+               putbak(*--p);
+}
+
+expand(a1, c)
+register char **a1;
+{
+       register char *dp;
+       register n;
+
+       dp = a1[-1];
+       if (dp==defloc)
+               dodef(a1, c);
+       else if (dp==evaloc)
+               doeval(a1, c);
+       else if (dp==inclloc)
+               doincl(a1, c, 1);
+       else if (dp==sinclloc)
+               doincl(a1, c, 0);
+       else if (dp==makeloc)
+               domake(a1, c);
+       else if (dp==syscmdloc)
+               dosyscmd(a1, c);
+       else if (dp==incrloc)
+               doincr(a1, c);
+       else if (dp==substrloc)
+               dosubstr(a1, c);
+       else if (dp==indexloc)
+               doindex(a1, c);
+       else if (dp==transloc)
+               dotransl(a1, c);
+       else if (dp==ifloc)
+               doif(a1, c);
+       else if (dp==divloc)
+               dodiv(a1, c);
+       else if (dp==divnumloc)
+               dodivnum(a1, c);
+       else if (dp==undivloc)
+               doundiv(a1, c);
+       else if (dp==dnlloc)
+               dodnl(a1, c);
+       else if (dp==dumploc)
+               dodump(a1, c);
+       else if (dp==errploc)
+               doerrp(a1, c);
+       else if (dp==lenloc)
+               dolen(a1, c);
+       else if (dp==ifdefloc)
+               doifdef(a1, c);
+       else if (dp==undefloc)
+               doundef(a1, c);
+       else if (dp==shiftloc)
+               doshift(a1, c);
+       else if (dp==cqloc)
+               docq(a1, c);
+       else {
+               while (*dp++);
+               for (dp--; dp>a1[-1]; ) {
+                       if (--dp>a1[-1] && dp[-1]=='$') {
+                               n = *dp-'0';
+                               if (n>=0 && n<=9) {
+                                       if (n <= c)
+                                               pbstr(a1[n]);
+                                       dp--;
+                               } else
+                                       putbak(*dp);
+                       } else
+                               putbak(*dp);
+               }
+       }
+}
+
+struct nlist *lookup(str)
+char *str;
+{
+       register char *s1, *s2;
+       register struct nlist *np;
+       static struct nlist nodef;
+
+       s1 = str;
+       for (hshval = 0; *s1; )
+               hshval += *s1++;
+       hshval %= HSHSIZ;
+       for (np = hshtab[hshval]; np!=NULL; np = np->next) {
+               s1 = str;
+               s2 = np->name;
+               while (*s1++ == *s2)
+                       if (*s2++ == EOS)
+                               return(np);
+       }
+       return(&nodef);
+}
+
+char *install(nam, val)
+char *nam, *val;
+{
+       register struct nlist *np;
+
+       if ((np = lookup(nam))->name == NULL) {
+               np = (struct nlist *)malloc(sizeof(*np));
+               if (np == NULL) {
+                       fprintf(stderr, "m4: no space for alloc\n");
+                       exit(1);
+               }
+               np->name = copy(nam);
+               np->def = copy(val);
+               np->next = hshtab[hshval];
+               hshtab[hshval] = np;
+               return(np->def);
+       }
+       free(np->def);
+       np->def = copy(val);
+       return(np->def);
+}
+
+doundef(ap, c)
+char **ap;
+{
+       register struct nlist *np, *tnp;
+
+       if (c < 1 || (np = lookup(ap[1]))->name == NULL)
+               return;
+       tnp = hshtab[hshval];   /* lookup sets hshval */
+       if (tnp == np)  /* it's in first place */
+               hshtab[hshval] = np->next;
+       else {
+               for ( ; tnp->next != np; tnp = tnp->next)
+                       ;
+               tnp->next = np->next;
+       }
+       free(np->name);
+       free(np->def);
+       free((char *)np);
+}
+
+char *copy(s)
+register char *s;
+{
+       register char *p, *s1;
+
+       p = s1 = malloc((unsigned)strlen(s)+1);
+       if (p == NULL) {
+               fprintf(stderr, "m4: no space for alloc\n");
+               exit(1);
+       }
+       while (*s1++ = *s++);
+       return(p);
+}
+
+dodef(ap, c)
+char **ap;
+{
+       if (c >= 2) {
+               if (strcmp(ap[1], ap[2]) == 0) {
+                       fprintf(stderr, "m4: %s defined as itself\n", ap[1]);
+                       delexit();
+               }
+               install(ap[1], ap[2]);
+       }
+       else if (c == 1)
+               install(ap[1], "");
+}
+
+doifdef(ap, c)
+char **ap;
+{
+       register struct nlist *np;
+
+       if (c < 2)
+               return;
+       if (lookup(ap[1])->name != NULL)
+               pbstr(ap[2]);
+       else if (c >= 3)
+               pbstr(ap[3]);
+}
+
+dolen(ap, c)
+char **ap;
+{
+       putnum((long) strlen(ap[1]));
+}
+
+docq(ap, c)
+char **ap;
+{
+       if (c > 1) {
+               lquote = *ap[1];
+               rquote = *ap[2];
+       } else if (c == 1) {
+               lquote = rquote = *ap[1];
+       } else {
+#ifndef M4
+               lquote = GRAVE;
+               rquote = ACUTE;
+#endif
+#ifdef M4
+               lquote = LBRAK;
+               rquote = RBRAK;
+#endif
+       }
+}
+
+doshift(ap, c)
+char **ap;
+{
+       fprintf(stderr, "m4: shift not yet implemented\n");
+}
+
+dodump(ap, c)
+char **ap;
+{
+       int i;
+       register struct nlist *np;
+
+       if (c > 0)
+               while (c--) {
+                       if ((np = lookup(*++ap))->name != NULL)
+                               fprintf(stderr, "`%s'   `%s'\n", np->name, np->def);
+               }
+       else
+               for (i=0; i<HSHSIZ; i++)
+                       for (np=hshtab[i]; np!=NULL; np=np->next)
+                               fprintf(stderr, "`%s'   `%s'\n", np->name, np->def);
+}
+
+doerrp(ap, c)
+char **ap;
+{
+       if (c > 0) {
+               fprintf(stderr, ap[1], ap[2], ap[3], ap[4], ap[5], ap[6]);
+               fprintf(stderr, "\n");
+       }
+}
+
+
+long   evalval;        /* return value from yacc stuff */
+char   *pe;    /* used by grammar */
+
+doeval(ap, c)
+char **ap;
+{
+
+       if (c > 0) {
+               pe = ap[1];
+               if (yyparse() == 0)
+                       putnum(evalval);
+               else
+                       fprintf(stderr, "m4: invalid expression in eval: %s\n", ap[1]);
+       }
+}
+
+doincl(ap, c, noisy)
+char **ap;
+{
+       if (c > 0 && strlen(ap[1]) > 0) {
+               infptr++;
+               ip_stk[infptr] = cur_ip = ip;
+               if ((infile[infptr] = fopen(ap[1], READ))==ERROR) {
+                       if (noisy) {
+                               fprintf(stderr, "m4: file not found: %s\n", ap[1]);
+                               delexit();
+                       }
+                       else
+                               infptr--;
+               }
+       }
+}
+
+dosyscmd(ap, c)
+char **ap;
+{
+       if (c > 0)
+               system(ap[1]);
+}
+
+domake(ap, c)
+char **ap;
+{
+       if (c > 0)
+               pbstr(mktemp(ap[1]));
+}
+
+doincr(ap, c)
+char **ap;
+{
+       if (c >= 1)
+               putnum(ctol(ap[1])+1);
+}
+
+putnum(num)
+long num;
+{
+       register sign;
+
+       sign = (num < 0) ? '-' : '\0';
+       if (num < 0)
+               num = -num;
+       do {
+               putbak(num%10+'0');
+               num = num/10;
+       } while (num!=0);
+       if (sign == '-')
+               putbak('-');
+}
+
+dosubstr(ap, c)
+char **ap;
+{
+       int nc;
+       register char *sp, *fc;
+
+       if (c<2)
+               return;
+       if (c<3)
+               nc = TOKS;
+       else
+               nc = ctoi(ap[3]);
+       fc = ap[1] + max(0, min(ctoi(ap[2]), strlen(ap[1])));
+       sp = fc + min(nc, strlen(fc));
+       while (sp > fc)
+               putbak(*--sp);
+}
+
+doindex(ap, c)
+char **ap;
+{
+       if (c >= 2)
+               putnum((long) strindex(ap[1], ap[2]));
+}
+
+strindex(p1, p2)
+char *p1, *p2;
+{
+       register m;
+       register char *s, *t, *p;
+
+       for (p=p1; *p; p++) {
+               s = p;
+               m = 1;
+               for (t=p2; *t; )
+                       if (*t++ != *s++)
+                               m = 0;
+               if (m == 1)
+                       return(p-p1);
+       }
+       return(-1);
+}
+
+dotransl(ap, c)
+char **ap;
+{
+       register char *s, *fr, *to;
+
+       if (c <= 1) return;
+
+       if (c == 2) {
+               register int i;
+               to = ap[1];
+               for (s = ap[1]; *s; s++) {
+                       i = 0;
+                       for (fr = ap[2]; *fr; fr++)
+                               if (*s == *fr) {
+                                       i++;
+                                       break;
+                               }
+                       if (i == 0)
+                               *to++ = *s;
+               }
+               *to = '\0';
+       }
+
+       if (c >= 3) {
+               for (s = ap[1]; *s; s++)
+                       for (fr = ap[2], to = ap[3]; *fr && *to; fr++, to++)
+                               if (*s == *fr)
+                                       *s = *to;
+       }
+
+       pbstr(ap[1]);
+}
+
+doif(ap, c)
+register char **ap;
+{
+       if (c < 3)
+               return;
+       while (c >= 3) {
+               if (strcmp(ap[1], ap[2]) == 0) {
+                       pbstr(ap[3]);
+                       return;
+               }
+               c -= 3;
+               ap += 3;
+       }
+       if (c > 0)
+               pbstr(ap[1]);
+}
+
+dodiv(ap, c)
+register char **ap;
+{
+       register int f;
+
+       if (c<1)
+               f = 0;
+       else
+               f = ctoi(ap[1]);
+       if (f>=10 || f<0) {
+               curfile = NULL;
+               return;
+       }
+       tempname[7] = 'a' + f;
+       if (olist[f] || (olist[f]=fopen(tempname, WRITE))) {
+               curout = f;
+               curfile = olist[f];
+       }
+}
+
+doundiv(ap, c)
+char **ap;
+{
+       register FILE *fp;
+       register int i, ch;
+       int j;
+
+       if (c == 0) {
+               for (i=1; i<10; i++) {
+                       if (i==curout || olist[i]==NULL)
+                               continue;
+                       fclose(olist[i]);
+                       tempname[7] = 'a'+i;
+                       fp = fopen(tempname, READ);
+                       if (curfile != NULL)
+                               while ((ch = getc(fp)) > 0)
+                                       putc(ch, curfile);
+                       fclose(fp);
+                       unlink(tempname);
+                       olist[i] = NULL;
+               }
+
+       }
+       else {
+               for (j = 1; j <= c; j++) {
+                       i = ctoi(*++ap);
+                       if (i<1 || i>9 || i==curout || olist[i]==NULL)
+                               continue;
+                       fclose(olist[i]);
+                       tempname[7] = 'a'+i;
+                       fp = fopen(tempname, READ);
+                       if (curfile != NULL)
+                               while ((ch = getc(fp)) > 0)
+                                       putc(ch, curfile);
+                       fclose(fp);
+                       unlink(tempname);
+                       olist[i] = NULL;
+               }
+       }
+}
+
+dodivnum(ap, c)
+char **ap;
+{
+       putnum((long) curout);
+}
+
+dodnl(ap, c)
+char **ap;
+{
+       register t;
+
+       while ((t=getchr())!='\n' && t>=0)
+               ;
+}
+
+long ctol(str)
+register char *str;
+{
+       register sign;
+       long num;
+
+       while (*str==' ' || *str=='\t' || *str=='\n')
+               str++;
+       num = 0;
+       if (*str == '-') {
+               sign = -1;
+               str++;
+       }
+       else
+               sign = 1;
+       while (*str>='0' && *str<='9')
+               num = num*10 + *str++ - '0';
+       return(sign * num);
+}
+
+ctoi(s)
+char *s;
+{
+       return(ctol(s));
+}
+
+min(a, b)
+{
+       if (a>b)
+               return(b);
+       return(a);
+}
+
+max(a, b)
+{
+       if (a>b)
+               return(a);
+       return(b);
+}
diff --git a/usr/src/cmd/m4/m4y.y b/usr/src/cmd/m4/m4y.y
new file mode 100644 (file)
index 0000000..40f5a3b
--- /dev/null
@@ -0,0 +1,94 @@
+%{
+extern long    evalval;
+#define        YYSTYPE long
+%}
+
+%term DIGITS
+%left '|'
+%left '&'
+%right '!'
+%nonassoc GT GE LT LE NE EQ
+%left '+' '-'
+%left '*' '/' '%'
+%right POWER
+%right UMINUS
+%%
+
+s      : e     ={ evalval = $1; }
+       |       ={ evalval = 0; }
+       ;
+
+e      : e '|' e       ={ $$ = ($1!=0 || $3!=0) ? 1 : 0; }
+       | e '&' e       ={ $$ = ($1!=0 && $3!=0) ? 1 : 0; }
+       | '!' e         ={ $$ = $2 == 0; }
+       | e EQ e        ={ $$ = $1 == $3; }
+       | e NE e        ={ $$ = $1 != $3; }
+       | e GT e        ={ $$ = $1 > $3; }
+       | e GE e        ={ $$ = $1 >= $3; }
+       | e LT e        ={ $$ = $1 < $3; }
+       | e LE e        ={ $$ = $1 <= $3; }
+       | e '+' e       ={ $$ = ($1+$3); }
+       | e '-' e       ={ $$ = ($1-$3); }
+       | e '*' e       ={ $$ = ($1*$3); }
+       | e '/' e       ={ $$ = ($1/$3); }
+       | e '%' e       ={ $$ = ($1%$3); }
+       | '(' e ')'     ={ $$ = ($2); }
+       | e POWER e     ={ for ($$=1; $3-->0; $$ *= $1); }      
+       | '-' e %prec UMINUS    ={ $$ = $2-1; $$ = -$2; }
+       | '+' e %prec UMINUS    ={ $$ = $2-1; $$ = $2; }
+       | DIGITS        ={ $$ = evalval; }
+       ;
+
+%%
+
+yylex() {
+       extern char *pe;
+
+       while (*pe==' ' || *pe=='\t' || *pe=='\n')
+               pe++;
+       switch(*pe) {
+       case '\0':
+       case '+':
+       case '-':
+       case '/':
+       case '%':
+       case '(':
+       case ')':
+               return(*pe++);
+       case '^':
+               pe++;
+               return(POWER);
+       case '*':
+               return(peek('*', POWER, '*'));
+       case '>':
+               return(peek('=', GE, GT));
+       case '<':
+               return(peek('=', LE, LT));
+       case '=':
+               return(peek('=', EQ, EQ));
+       case '|':
+               return(peek('|', '|', '|'));
+       case '&':
+               return(peek('&', '&', '&'));
+       case '!':
+               return(peek('=', NE, '!'));
+       default:
+               evalval = 0;
+               while (*pe >= '0' && *pe <= '9')
+                       evalval = evalval*10 + *pe++ - '0';
+               return(DIGITS);
+       }
+}
+
+peek(c, r1, r2)
+{
+       if (*++pe != c)
+               return(r2);
+       ++pe;
+       return(r1);
+}
+
+yyerror(s)
+char *s;
+{
+}
diff --git a/usr/src/cmd/neqn/diacrit.c b/usr/src/cmd/neqn/diacrit.c
new file mode 100644 (file)
index 0000000..d38d24d
--- /dev/null
@@ -0,0 +1,44 @@
+# include "e.h"
+# include "e.def"
+
+diacrit(p1, type) int p1, type; {
+       int c, t;
+
+       c = oalloc();
+       t = oalloc();
+       nrwid(p1, ps, p1);
+       printf(".nr 10 %du\n", max(eht[p1]-ebase[p1]-VERT(2),0));
+       switch(type) {
+               case VEC:       /* vec */
+               case DYAD:      /* dyad */
+                       printf(".ds %d \\v'-1'_\\v'1'\n", c);
+                       break;
+               case HAT:
+                       printf(".ds %d ^\n", c);
+                       break;
+               case TILDE:
+                       printf(".ds %d ~\n", c);
+                       break;
+               case DOT:
+                       printf(".ds %d \\v'-1'.\\v'1'\n", c);
+                       break;
+               case DOTDOT:
+                       printf(".ds %d \\v'-1'..\\v'1'\n", c);
+                       break;
+               case BAR:
+                       printf(".ds %d \\v'-1'\\l'\\n(%du'\\v'1'\n", 
+                               c, p1);
+                       break;
+               case UNDER:
+                       printf(".ds %d \\l'\\n(%du'\n", c, p1);
+                       break;
+               }
+       nrwid(c, ps, c);
+       printf(".as %d \\h'-\\n(%du-\\n(%du/2u'\\v'0-\\n(10u'\\*(%d", 
+               p1, p1, c, c);
+       printf("\\v'\\n(10u'\\h'-\\n(%du+\\n(%du/2u'\n", c, p1);
+       if (type != UNDER)
+               eht[p1] += VERT(1);
+       if (dbg) printf(".\tdiacrit: %c over S%d, h=%d, b=%d\n", type, p1, eht[p1], ebase[p1]);
+       ofree(c); ofree(t);
+}
diff --git a/usr/src/cmd/neqn/e.h b/usr/src/cmd/neqn/e.h
new file mode 100644 (file)
index 0000000..4722f6b
--- /dev/null
@@ -0,0 +1,42 @@
+#include <stdio.h>
+
+#define        FATAL   1
+#define        ROM     '1'
+#define        ITAL    '1'
+#define        BLD     '1'
+
+#define        VERT(n) (20 * (n))
+#define        EFFPS(p)        ((p) >= 6 ? (p) : 6)
+
+extern int     dbg;
+extern int     ct;
+extern int     lp[];
+extern int     used[]; /* available registers */
+extern int     ps;     /* dflt init pt size */
+extern int     deltaps;        /* default change in ps */
+extern int     gsize;  /* global size */
+extern int     gfont;  /* global font */
+extern int     ft;     /* dflt font */
+extern FILE    *curfile;       /* current input file */
+extern int     ifile;  /* input file number */
+extern int     linect; /* line number in current file */
+extern int     eqline; /* line where eqn started */
+extern int     svargc;
+extern char    **svargv;
+extern int     eht[];
+extern int     ebase[];
+extern int     lfont[];
+extern int     rfont[];
+extern int     yyval;
+extern int     *yypv;
+extern int     yylval;
+extern int     eqnreg, eqnht;
+extern int     lefteq, righteq;
+extern int     lastchar;       /* last character read by lex */
+extern int     markline;       /* 1 if this EQ/EN contains mark or lineup */
+
+typedef struct s_tbl {
+       char    *name;
+       char    *defn;
+       struct s_tbl *next;
+} tbl;
diff --git a/usr/src/cmd/neqn/e.y b/usr/src/cmd/neqn/e.y
new file mode 100644 (file)
index 0000000..f294e59
--- /dev/null
@@ -0,0 +1,166 @@
+%{#
+#include "e.h"
+#
+int    fromflg;
+%}
+%term  CONTIG QTEXT SPACE THIN TAB
+%term  MATRIX LCOL CCOL RCOL COL
+%term  MARK LINEUP
+%term  SUM INT PROD UNION INTER
+%term  LPILE PILE CPILE RPILE ABOVE
+%term  DEFINE TDEFINE NDEFINE DELIM GSIZE GFONT INCLUDE
+%right FROM TO
+%left  OVER SQRT
+%right SUP SUB
+%right SIZE FONT ROMAN ITALIC BOLD FAT
+%right UP DOWN BACK FWD
+%left  LEFT RIGHT
+%right DOT DOTDOT HAT TILDE BAR UNDER VEC DYAD
+
+%%
+
+stuff  : eqn   { putout($1); }
+       | error { error(!FATAL, "syntax error"); }
+       |       { eqnreg = 0; }
+       ;
+
+eqn    : box
+       | eqn box       { eqnbox($1, $2, 0); }
+       | eqn lineupbox { eqnbox($1, $2, 1); }
+       | LINEUP        { lineup(0); }
+       ;
+
+lineupbox: LINEUP box  { $$ = $2; lineup(1); }
+       ;
+
+matrix : MATRIX        { $$ = ct; } ;
+
+collist        : column
+       | collist column
+       ;
+
+column : lcol '{' list '}'     { column('L', $1); }
+       | ccol '{' list '}'     { column('C', $1); }
+       | rcol '{' list '}'     { column('R', $1); }
+       | col '{' list '}'      { column('-', $1); }
+       ;
+
+lcol   : LCOL          { $$ = ct++; } ;
+ccol   : CCOL          { $$ = ct++; } ;
+rcol   : RCOL          { $$ = ct++; } ;
+col    : COL           { $$ = ct++; } ;
+
+sbox   : sup box       %prec SUP       { $$ = $2; }
+       ;
+
+tbox   : to box        %prec TO        { $$ = $2; }
+       |               %prec FROM      { $$ = 0; }
+       ;
+
+box    : box OVER box  { boverb($1, $3); }
+       | MARK box      { mark($2); }
+       | size box      %prec SIZE      { size($1, $2); }
+       | font box      %prec FONT      { font($1, $2); }
+       | FAT box       { fatbox($2); }
+       | SQRT box      { sqrt($2); }
+       | lpile '{' list '}'    { lpile('L', $1, ct); ct = $1; }
+       | cpile '{' list '}'    { lpile('C', $1, ct); ct = $1; }
+       | rpile '{' list '}'    { lpile('R', $1, ct); ct = $1; }
+       | pile '{' list '}'     { lpile('-', $1, ct); ct = $1; }
+       | box sub box sbox      %prec SUB       { shift2($1, $3, $4); }
+       | box sub box           %prec SUB       { bshiftb($1, $2, $3); }
+       | box sup box           %prec SUP       { bshiftb($1, $2, $3); }
+       | int sub box sbox      %prec SUB       { integral($1, $3, $4); }
+       | int sub box           %prec SUB       { integral($1, $3, 0); }
+       | int sup box           %prec SUP       { integral($1, 0, $3); }
+       | int                                   { integral($1, 0, 0); }
+       | left eqn right        { paren($1, $2, $3); }
+       | pbox
+       | box from box tbox     %prec FROM      { fromto($1, $3, $4); fromflg=0; }
+       | box to box    %prec TO        { fromto($1, 0, $3); }
+       | box diacrit   { diacrit($1, $2); }
+       | fwd box       %prec UP        { move(FWD, $1, $2); }
+       | up box        %prec UP        { move(UP, $1, $2); }
+       | back box      %prec UP        { move(BACK, $1, $2); }
+       | down box      %prec UP        { move(DOWN, $1, $2); }
+       | matrix '{' collist '}'        { matrix($1); }
+       ;
+
+int    : INT   { setintegral(); }
+       ;
+
+fwd    : FWD text      { $$ = atoi((char *) $1); } ;
+up     : UP text       { $$ = atoi((char *) $1); } ;
+back   : BACK text     { $$ = atoi((char *) $1); } ;
+down   : DOWN text     { $$ = atoi((char *) $1); } ;
+
+diacrit        : HAT   { $$ = HAT; }
+       | VEC   { $$ = VEC; }
+       | DYAD  { $$ = DYAD; }
+       | BAR   { $$ = BAR; }
+       | UNDER { $$ = UNDER; } /* under bar */
+       | DOT   { $$ = DOT; }
+       | TILDE { $$ = TILDE; }
+       | DOTDOT        { $$ = DOTDOT; } /* umlaut = double dot */
+       ;
+
+from   : FROM  { $$=ps; ps -= 3; fromflg = 1;
+               if(dbg)printf(".\tfrom: old ps %d, new ps %d, fflg %d\n", $$, ps, fromflg);
+               }
+       ;
+
+to     : TO    { $$=ps; if(fromflg==0)ps -= 3; 
+                       if(dbg)printf(".\tto: old ps %d, new ps %d\n", $$, ps);
+               }
+       ;
+
+left   : LEFT text     { $$ = ((char *)$2)[0]; }
+       | LEFT '{'      { $$ = '{'; }
+       ;
+
+right  : RIGHT text    { $$ = ((char *)$2)[0]; }
+       | RIGHT '}'     { $$ = '}'; }
+       |               { $$ = 0; }
+       ;
+
+list   : eqn   { lp[ct++] = $1; }
+       | list ABOVE eqn        { lp[ct++] = $3; }
+       ;
+
+lpile  : LPILE { $$ = ct; } ;
+cpile  : CPILE { $$ = ct; } ;
+pile   : PILE  { $$ = ct; } ;
+rpile  : RPILE { $$ = ct; } ;
+
+size   : SIZE text     { $$ = ps; setsize((char *) $2); }
+       ;
+
+font   : ROMAN         { setfont(ROM); }
+       | ITALIC        { setfont(ITAL); }
+       | BOLD          { setfont(BLD); }
+       | FONT text     { setfont(((char *)$2)[0]); }
+       ;
+
+sub    : SUB   { shift(SUB); }
+       ;
+
+sup    : SUP   { shift(SUP); }
+       ;
+
+pbox   : '{' eqn '}'   { $$ = $2; }
+       | QTEXT         { text(QTEXT, (char *) $1); }
+       | CONTIG        { text(CONTIG, (char *) $1); }
+       | SPACE         { text(SPACE, 0); }
+       | THIN          { text(THIN, 0); }
+       | TAB           { text(TAB, 0); }
+       | SUM           { funny(SUM); }
+       | PROD          { funny(PROD); }
+       | UNION         { funny(UNION); }
+       | INTER         { funny(INTER); }       /* intersection */
+       ;
+
+text   : CONTIG
+       | QTEXT
+       ;
+
+%%
diff --git a/usr/src/cmd/neqn/eqnbox.c b/usr/src/cmd/neqn/eqnbox.c
new file mode 100644 (file)
index 0000000..2aea8da
--- /dev/null
@@ -0,0 +1,25 @@
+# include "e.h"
+
+eqnbox(p1, p2, lu) {
+       int b, h;
+       char *sh;
+
+       yyval = p1;
+       b = max(ebase[p1], ebase[p2]);
+       eht[yyval] = h = b + max(eht[p1]-ebase[p1], 
+               eht[p2]-ebase[p2]);
+       ebase[yyval] = b;
+       if(dbg)printf(".\te:eb: S%d <- S%d S%d; b=%d, h=%d\n", 
+               yyval, p1, p2, b, h);
+       if (rfont[p1] == ITAL && lfont[p2] == ROM)
+               sh = "\\|";
+       else
+               sh = "";
+       if (lu) {
+               printf(".nr %d \\w'\\s%d\\*(%d%s'\n", p1, ps, p1, sh);
+               printf(".ds %d \\h'|\\n(97u-\\n(%du'\\*(%d\n", p1, p1, p1);
+       }
+       printf(".as %d \"%s\\*(%d\n", yyval, sh, p2);
+       rfont[p1] = rfont[p2];
+       ofree(p2);
+}
diff --git a/usr/src/cmd/neqn/font.c b/usr/src/cmd/neqn/font.c
new file mode 100644 (file)
index 0000000..e4e026e
--- /dev/null
@@ -0,0 +1,59 @@
+# include "e.h"
+
+setfont(ch1) char ch1; {
+       /* use number '1', '2', '3' for roman, italic, bold */
+       yyval = ft;
+       if (ch1 == 'r' || ch1 == 'R')
+               ft = ROM;
+       else if (ch1 == 'i' || ch1 == 'I')
+               ft = ITAL;
+       else if (ch1 == 'b' || ch1 == 'B')
+               ft = BLD;
+       else
+               ft = ch1;
+       printf(".ft %c\n", ft);
+       if(dbg)printf(".\tsetfont %c\n", ft);
+}
+
+font(p1, p2) int p1, p2; {
+               /* old font in p1, new in ft */
+       yyval = p2;
+       lfont[yyval] = rfont[yyval] = ft==ITAL ? ITAL : ROM;
+       if(dbg)printf(".\tb:fb: S%d <- \\f%c S%d \\f%c b=%d,h=%d,lf=%c,rf=%c\n", 
+               yyval, ft, p2, p1, ebase[yyval], eht[yyval], lfont[yyval], rfont[yyval]);
+       printf(".ds %d \\f%c\\*(%d\\f%c\n", 
+               yyval, ft, p2, p1);
+       ft = p1;
+       printf(".ft %c\n", ft);
+}
+
+fatbox(p) int p; {
+       int sh;
+
+       yyval = p;
+       sh = ps / 4;
+       nrwid(p, ps, p);
+       printf(".ds %d \\*(%d\\h'-\\n(%du+%du'\\*(%d\n", p, p, p, sh, p);
+       if(dbg)printf(".\tfat %d, sh=%d\n", p, sh);
+}
+
+globfont() {
+       char temp[20];
+
+       getstr(temp, 20);
+       yyval = eqnreg = 0;
+       gfont = temp[0];
+       switch (gfont) {
+       case 'r': case 'R':
+               gfont = '1';
+               break;
+       case 'i': case 'I':
+               gfont = '2';
+               break;
+       case 'b': case 'B':
+               gfont = '3';
+               break;
+       }
+       printf(".ft %c\n", gfont);
+       ft = gfont;
+}
diff --git a/usr/src/cmd/neqn/fromto.c b/usr/src/cmd/neqn/fromto.c
new file mode 100644 (file)
index 0000000..d792d1e
--- /dev/null
@@ -0,0 +1,45 @@
+# include "e.h"
+
+fromto(p1, p2, p3) int p1, p2, p3; {
+       int b, h1, b1, pss;
+       yyval = oalloc();
+       lfont[yyval] = rfont[yyval] = 0;
+       h1 = eht[yyval] = eht[p1];
+       b1 = ebase[p1];
+       b = 0;
+       pss = EFFPS(ps);
+       ps += 3;
+       nrwid(p1, ps, p1);
+       printf(".nr %d \\n(%d\n", yyval, p1);
+       if( p2>0 ) {
+               nrwid(p2, pss, p2);
+               printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, yyval, yyval, p2);
+               eht[yyval] += eht[p2];
+               b = eht[p2];
+       }
+       if( p3>0 ) {
+               nrwid(p3, pss, p3);
+               printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p3, yyval, yyval, p3);
+               eht[yyval] += eht[p3];
+       }
+       printf(".ds %d ", yyval);       /* bottom of middle box */
+       if( p2>0 ) {
+               printf("\\v'%du'\\h'\\n(%du-\\n(%du/2u'\\s%d\\*(%d\\s%d", 
+                       eht[p2]-ebase[p2]+b1, yyval, p2, pss, p2, EFFPS(ps));
+               printf("\\h'-\\n(%du-\\n(%du/2u'\\v'%du'\\\n", 
+                       yyval, p2, -(eht[p2]-ebase[p2]+b1));
+       }
+       printf("\\h'\\n(%du-\\n(%du/2u'\\*(%d\\h'\\n(%du-\\n(%du+2u/2u'\\\n", 
+               yyval, p1, p1, yyval, p1);
+       if( p3>0 ) {
+               printf("\\v'%du'\\h'-\\n(%du-\\n(%du/2u'\\s%d\\*(%d\\s%d\\h'\\n(%du-\\n(%du/2u'\\v'%du'\\\n", 
+                       -(h1-b1+ebase[p3]), yyval, p3, pss, p3, EFFPS(ps), yyval, p3, (h1-b1+ebase[p3]));
+       }
+       printf("\n");
+       ebase[yyval] = b + b1;
+       if(dbg)printf(".\tfrom to: S%d <- %d f %d t %d; h=%d b=%d\n", 
+               yyval, p1, p2, p3, eht[yyval], ebase[yyval]);
+       ofree(p1);
+       if( p2>0 ) ofree(p2);
+       if( p3>0 ) ofree(p3);
+}
diff --git a/usr/src/cmd/neqn/funny.c b/usr/src/cmd/neqn/funny.c
new file mode 100644 (file)
index 0000000..1b93818
--- /dev/null
@@ -0,0 +1,26 @@
+# include "e.h"
+# include "e.def"
+
+funny(n) int n; {
+       char *f;
+
+       yyval = oalloc();
+       switch(n) {
+       case SUM:
+               f = "\\(*S"; break;
+       case UNION:
+               f = "\\(cu"; break;
+       case INTER:     /* intersection */
+               f = "\\(ca"; break;
+       case PROD:
+               f = "\\(*P"; break;
+       default:
+               error(FATAL, "funny type %d in funny", n);
+       }
+       printf(".ds %d %s\n", yyval, f);
+       eht[yyval] = VERT(2);
+       ebase[yyval] = 0;
+       if(dbg)printf(".\tfunny: S%d <- %s; h=%d b=%d\n", 
+               yyval, f, eht[yyval], ebase[yyval]);
+       lfont[yyval] = rfont[yyval] = ROM;
+}
diff --git a/usr/src/cmd/neqn/glob.c b/usr/src/cmd/neqn/glob.c
new file mode 100644 (file)
index 0000000..834a33f
--- /dev/null
@@ -0,0 +1,27 @@
+#include "e.h"
+
+int    dbg;    /* debugging print if non-zero */
+int    lp[80]; /* stack for things like piles and matrices */
+int    ct;     /* pointer to lp */
+int    used[100];      /* available registers */
+int    ps;     /* default init point size */
+int    deltaps = 3;    /* default change in ps */
+int    gsize   = 10;   /* default initial point size */
+int    gfont   = ITAL; /* italic */
+int    ft;     /* default font */
+FILE   *curfile;       /* current input file */
+int    ifile;
+int    linect; /* line number in file */
+int    eqline; /* line where eqn started */
+int    svargc;
+char   **svargv;
+int    eht[100];
+int    ebase[100];
+int    lfont[100];
+int    rfont[100];
+int    eqnreg; /* register where final string appears */
+int    eqnht;  /* inal height of equation */
+int    lefteq  = '\0'; /* left in-line delimiter */
+int    righteq = '\0'; /* right in-line delimiter */
+int    lastchar;       /* last character read by lex */
+int    markline        = 0;    /* 1 if this EQ/EN contains mark or lineup */
diff --git a/usr/src/cmd/neqn/integral.c b/usr/src/cmd/neqn/integral.c
new file mode 100644 (file)
index 0000000..1247250
--- /dev/null
@@ -0,0 +1,31 @@
+# include "e.h"
+# include "e.def"
+
+integral(p, p1, p2) {
+#ifndef        NEQN
+       if (p1 != 0)
+               printf(".ds %d \\h'-0.4m'\\v'0.4m'\\*(%d\\v'-0.4m'\n", p1, p1);
+       if (p2 != 0)
+               printf(".ds %d \\v'-0.3m'\\*(%d\\v'0.3m'\n", p2, p2);
+#endif
+       if (p1 != 0 && p2 != 0)
+               shift2(p, p1, p2);
+       else if (p1 != 0)
+               bshiftb(p, SUB, p1);
+       else if (p2 != 0)
+               bshiftb(p, SUP, p2);
+       if(dbg)printf(".\tintegral: S%d; h=%d b=%d\n", 
+               p, eht[p], ebase[p]);
+       lfont[p] = ROM;
+}
+
+setintegral() {
+       char *f;
+
+       yyval = oalloc();
+       f = "\\(is";
+       printf(".ds %d %s\n", yyval, f);
+       eht[yyval] = VERT(2);
+       ebase[yyval] = 0;
+       lfont[yyval] = rfont[yyval] = ROM;
+}
diff --git a/usr/src/cmd/neqn/io.c b/usr/src/cmd/neqn/io.c
new file mode 100644 (file)
index 0000000..541d31d
--- /dev/null
@@ -0,0 +1,195 @@
+# include "e.h"
+#define        MAXLINE 1200    /* maximum input line */
+
+char   in[MAXLINE];    /* input buffer */
+int    eqnexit();
+int noeqn;
+
+main(argc,argv) int argc; char *argv[];{
+
+       eqnexit(eqn(argc, argv));
+}
+
+eqnexit(n) {
+#ifdef gcos
+       if (n)
+               fprintf(stderr, "run terminated due to eqn error\n");
+       exit(0);
+#endif
+       exit(n);
+}
+
+eqn(argc,argv) int argc; char *argv[];{
+       int i, type;
+
+       setfile(argc,argv);
+       init_tbl();     /* install keywords in tables */
+       while ((type=getline(in)) != EOF) {
+               eqline = linect;
+               if (in[0]=='.' && in[1]=='E' && in[2]=='Q') {
+                       for (i=11; i<100; used[i++]=0);
+                       printf("%s",in);
+                       printf(".nr 99 \\n(.s\n.nr 98 \\n(.f\n");
+                       markline = 0;
+                       init();
+                       yyparse();
+                       if (eqnreg>0) {
+                               printf(".nr %d \\w'\\*(%d'\n", eqnreg, eqnreg);
+                               /* printf(".if \\n(%d>\\n(.l .tm too-long eqn, file %s, between lines %d-%d\n", */
+                               /*      eqnreg, svargv[ifile], eqline, linect); */
+                               printf(".nr MK %d\n", markline);        /* for -ms macros */
+                               printf(".if %d>\\n(.v .ne %du\n", eqnht, eqnht);
+                               printf(".rn %d 10\n", eqnreg);
+                               if(!noeqn)printf("\\*(10\n");
+                       }
+                       printf(".ps \\n(99\n.ft \\n(98\n");
+                       printf(".EN");
+                       if (lastchar == EOF) {
+                               putchar('\n');
+                               break;
+                       }
+                       if (putchar(lastchar) != '\n')
+                               while (putchar(gtc()) != '\n');
+               }
+               else if (type == lefteq)
+                       inline();
+               else
+                       printf("%s",in);
+       }
+       return(0);
+}
+
+getline(s) register char *s; {
+       register c;
+       while((*s++=c=gtc())!='\n' && c!=EOF && c!=lefteq)
+               if (s >= in+MAXLINE) {
+                       error( !FATAL, "input line too long: %.20s\n", in);
+                       in[MAXLINE] = '\0';
+                       break;
+               }
+       if (c==lefteq)
+               s--;
+       *s++ = '\0';
+       return(c);
+}
+
+inline() {
+       int ds;
+
+       printf(".nr 99 \\n(.s\n.nr 98 \\n(.f\n");
+       ds = oalloc();
+       printf(".rm %d \n", ds);
+       do{
+               if (*in)
+                       printf(".as %d \"%s\n", ds, in);
+               init();
+               yyparse();
+               if (eqnreg > 0) {
+                       printf(".as %d \\*(%d\n", ds, eqnreg);
+                       ofree(eqnreg);
+               }
+               printf(".ps \\n(99\n.ft \\n(98\n");
+       } while (getline(in) == lefteq);
+       if (*in)
+               printf(".as %d \"%s", ds, in);
+       printf(".ps \\n(99\n.ft \\n(98\n");
+       printf("\\*(%d\n", ds);
+       ofree(ds);
+}
+
+putout(p1) int p1; {
+       extern int gsize, gfont;
+       int before, after;
+       if(dbg)printf(".\tanswer <- S%d, h=%d,b=%d\n",p1, eht[p1], ebase[p1]);
+       eqnht = eht[p1];
+       printf(".ds %d \\x'0'", p1);
+       /* suppposed to leave room for a subscript or superscript */
+       before = eht[p1] - ebase[p1] - VERT(3); /* 3 = 1.5 lines */
+       if (before > 0)
+               printf("\\x'0-%du'", before);
+       printf("\\f%c\\s%d\\*(%d%s\\s\\n(99\\f\\n(98",
+               gfont, gsize, p1, rfont[p1] == ITAL ? "\\|" : "");
+       after = ebase[p1] - VERT(1);
+       if (after > 0)
+               printf("\\x'%du'", after);
+       putchar('\n');
+       eqnreg = p1;
+}
+
+max(i,j) int i,j; {
+       return (i>j ? i : j);
+}
+
+oalloc() {
+       int i;
+       for (i=11; i<100; i++)
+               if (used[i]++ == 0) return(i);
+       error( FATAL, "no eqn strings left", i);
+       return(0);
+}
+
+ofree(n) int n; {
+       used[n] = 0;
+}
+
+setps(p) int p; {
+       printf(".ps %d\n", EFFPS(p));
+}
+
+nrwid(n1, p, n2) int n1, p, n2; {
+       printf(".nr %d \\w'\\s%d\\*(%d'\n", n1, EFFPS(p), n2);
+}
+
+setfile(argc, argv) int argc; char *argv[]; {
+       static char *nullstr = "-";
+
+       svargc = --argc;
+       svargv = argv;
+       while (svargc > 0 && svargv[1][0] == '-') {
+               switch (svargv[1][1]) {
+
+               case 'd': lefteq=svargv[1][2]; righteq=svargv[1][3]; break;
+               case 's': gsize = atoi(&svargv[1][2]); break;
+               case 'p': deltaps = atoi(&svargv[1][2]); break;
+               case 'f': gfont = svargv[1][2]; break;
+               case 'e': noeqn++; break;
+               default: dbg = 1;
+               }
+               svargc--;
+               svargv++;
+       }
+       ifile = 1;
+       linect = 1;
+       if (svargc <= 0) {
+               curfile = stdin;
+               svargv[1] = nullstr;
+       }
+       else if ((curfile = fopen(svargv[1], "r")) == NULL)
+               error( FATAL,"can't open file %s", svargv[1]);
+}
+
+yyerror() {;}
+
+init() {
+       ct = 0;
+       ps = gsize;
+       ft = gfont;
+       setps(ps);
+       printf(".ft %c\n", ft);
+}
+
+error(fatal, s1, s2) int fatal; char *s1, *s2; {
+       if (fatal>0)
+               printf("eqn fatal error: ");
+       printf(s1,s2);
+       printf("\nfile %s, between lines %d and %d\n",
+                svargv[ifile], eqline, linect);
+       fprintf(stderr, "eqn: ");
+       if (fatal>0)
+               fprintf(stderr, "fatal error: ");
+       fprintf(stderr, s1, s2);
+       fprintf(stderr, "\nfile %s, between lines %d and %d\n",
+                svargv[ifile], eqline, linect);
+       if (fatal > 0)
+               eqnexit(1);
+}
diff --git a/usr/src/cmd/neqn/lex.c b/usr/src/cmd/neqn/lex.c
new file mode 100644 (file)
index 0000000..19860a2
--- /dev/null
@@ -0,0 +1,211 @@
+#include "e.h"
+#include "e.def"
+
+#define        SSIZE   400
+char   token[SSIZE];
+int    sp;
+#define        putbak(c)       *ip++ = c;
+#define        PUSHBACK        300     /* maximum pushback characters */
+char   ibuf[PUSHBACK+SSIZE];   /* pushback buffer for definitions, etc. */
+char   *ip     = ibuf;
+
+gtc() {
+  loop:
+       if (ip > ibuf)
+               return(*--ip);  /* already present */
+       lastchar = getc(curfile);
+       if (lastchar=='\n')
+               linect++;
+       if (lastchar != EOF)
+               return(lastchar);
+       if (++ifile > svargc) {
+               return(EOF);
+       }
+       fclose(curfile);
+       linect = 1;
+       if ((curfile=fopen(svargv[ifile], "r")) != NULL)
+               goto loop;
+       error(FATAL, "can't open file %s", svargv[ifile]);
+       return(EOF);
+}
+
+pbstr(str)
+register char *str;
+{
+       register char *p;
+
+       p = str;
+       while (*p++);
+       --p;
+       if (ip >= &ibuf[PUSHBACK])
+               error( FATAL, "pushback overflow");
+       while (p > str)
+               putbak(*--p);
+}
+
+yylex() {
+       register int c;
+       tbl *tp, *lookup();
+       extern tbl **keytbl, **deftbl;
+
+  beg:
+       while ((c=gtc())==' ' || c=='\n')
+               ;
+       yylval=c;
+       switch(c) {
+
+       case EOF:
+               return(EOF);
+       case '~':
+               return(SPACE);
+       case '^':
+               return(THIN);
+       case '\t':
+               return(TAB);
+       case '{':
+               return('{');
+       case '}':
+               return('}');
+       case '"':
+               for (sp=0; (c=gtc())!='"' && c != '\n'; ) {
+                       if (c == '\\')
+                               if ((c = gtc()) != '"')
+                                       token[sp++] = '\\';
+                       token[sp++] = c;
+                       if (sp>=SSIZE)
+                               error(FATAL, "quoted string %.20s... too long", token);
+               }
+               token[sp]='\0';
+               yylval = (int) &token[0];
+               if (c == '\n')
+                       error(!FATAL, "missing \" in %.20s", token);
+               return(QTEXT);
+       }
+       if (c==righteq)
+               return(EOF);
+
+       putbak(c);
+       getstr(token, SSIZE);
+       if (dbg)printf(".\tlex token = |%s|\n", token);
+       if ((tp = lookup(&deftbl, token, NULL)) != NULL) {
+               putbak(' ');
+               pbstr(tp->defn);
+               putbak(' ');
+               if (dbg)
+                       printf(".\tfound %s|=%s|\n", token, tp->defn);
+       }
+       else if ((tp = lookup(&keytbl, token, NULL)) == NULL) {
+               if(dbg)printf(".\t%s is not a keyword\n", token);
+               return(CONTIG);
+       }
+       else if (tp->defn == (char *) DEFINE || tp->defn == (char *) NDEFINE || tp->defn == (char *) TDEFINE)
+               define(tp->defn);
+       else if (tp->defn == (char *) DELIM)
+               delim();
+       else if (tp->defn == (char *) GSIZE)
+               globsize();
+       else if (tp->defn == (char *) GFONT)
+               globfont();
+       else if (tp->defn == (char *) INCLUDE)
+               include();
+       else {
+               return((int) tp->defn);
+       }
+       goto beg;
+}
+
+getstr(s, n) char *s; register int n; {
+       register int c;
+       register char *p;
+
+       p = s;
+       while ((c = gtc()) == ' ' || c == '\n')
+               ;
+       if (c == EOF) {
+               *s = 0;
+               return;
+       }
+       while (c != ' ' && c != '\t' && c != '\n' && c != '{' && c != '}'
+         && c != '"' && c != '~' && c != '^' && c != righteq) {
+               if (c == '\\')
+                       if ((c = gtc()) != '"')
+                               *p++ = '\\';
+               *p++ = c;
+               if (--n <= 0)
+                       error(FATAL, "token %.20s... too long", s);
+               c = gtc();
+       }
+       if (c=='{' || c=='}' || c=='"' || c=='~' || c=='^' || c=='\t' || c==righteq)
+               putbak(c);
+       *p = '\0';
+       yylval = (int) s;
+}
+
+cstr(s, quote, maxs) char *s; int quote; {
+       int del, c, i;
+
+       while((del=gtc()) == ' ' || del == '\t' || del == '\n');
+       if (quote)
+               for (i=0; (c=gtc()) != del && c != EOF;) {
+                       s[i++] = c;
+                       if (i >= maxs)
+                               return(1);      /* disaster */
+               }
+       else {
+               s[0] = del;
+               for (i=1; (c=gtc())!=' ' && c!= '\t' && c!='\n' && c!=EOF;) {
+                       s[i++]=c;
+                       if (i >= maxs)
+                               return(1);      /* disaster */
+               }
+       }
+       s[i] = '\0';
+       if (c == EOF)
+               error(FATAL, "Unexpected end of input at %.20s", s);
+       return(0);
+}
+
+define(type) int type; {
+       char *strsave(), *p1, *p2;
+       tbl *lookup();
+       extern tbl **deftbl;
+
+       getstr(token, SSIZE);   /* get name */
+       if (type != DEFINE) {
+               cstr(token, 1, SSIZE);  /* skip the definition too */
+               return;
+       }
+       p1 = strsave(token);
+       if (cstr(token, 1, SSIZE))
+               error(FATAL, "Unterminated definition at %.20s", token);
+       p2 = strsave(token);
+       lookup(&deftbl, p1, p2);
+       if (dbg)printf(".\tname %s defined as %s\n", p1, p2);
+}
+
+char *strsave(s)
+char *s;
+{
+       char *malloc();
+       register char *q;
+
+       q = malloc(strlen(s)+1);
+       if (q == NULL)
+               error(FATAL, "out of space in strsave on %s", s);
+       strcpy(q, s);
+       return(q);
+}
+
+include() {
+       error(!FATAL, "Include not yet implemented");
+}
+
+delim() {
+       yyval = eqnreg = 0;
+       if (cstr(token, 0, SSIZE))
+               error(FATAL, "Bizarre delimiters at %.20s", token);
+       lefteq = token[0];
+       righteq = token[1];
+       if (lefteq == 'o' && righteq == 'f')
+               lefteq = righteq = '\0';
+}
diff --git a/usr/src/cmd/neqn/lookup.c b/usr/src/cmd/neqn/lookup.c
new file mode 100644 (file)
index 0000000..aa6ea92
--- /dev/null
@@ -0,0 +1,217 @@
+# include "e.h"
+#include "e.def"
+
+#define        TBLSIZE 100
+
+tbl    *keytbl[TBLSIZE];       /* key words */
+tbl    *restbl[TBLSIZE];       /* reserved words */
+tbl    *deftbl[TBLSIZE];       /* user-defined names */
+
+struct {
+       char    *key;
+       int     keyval;
+} keyword[]    ={
+       "sub",  SUB, 
+       "sup",  SUP, 
+       ".EN",  EOF, 
+       "from",         FROM, 
+       "to",   TO, 
+       "sum",  SUM, 
+       "hat",  HAT, 
+       "vec", VEC, 
+       "dyad", DYAD, 
+       "dot",  DOT, 
+       "dotdot",       DOTDOT, 
+       "bar",  BAR, 
+       "tilde",        TILDE, 
+       "under",        UNDER, 
+       "prod",         PROD, 
+       "int",  INT, 
+       "integral",     INT, 
+       "union",        UNION, 
+       "inter",        INTER, 
+       "pile",         PILE, 
+       "lpile",        LPILE, 
+       "cpile",        CPILE, 
+       "rpile",        RPILE, 
+       "over",         OVER, 
+       "sqrt",         SQRT, 
+       "above",        ABOVE, 
+       "size",         SIZE, 
+       "font",         FONT, 
+       "fat", FAT, 
+       "roman",        ROMAN, 
+       "italic",       ITALIC, 
+       "bold",         BOLD, 
+       "left",         LEFT, 
+       "right",        RIGHT, 
+       "delim",        DELIM, 
+       "define",       DEFINE, 
+
+#ifdef NEQN    /* make ndefine synonym for define, tdefine a no-op */
+
+       "tdefine",      TDEFINE,
+       "ndefine",      DEFINE,
+
+#else          /* tdefine = define, ndefine = no-op */
+
+       "tdefine",      DEFINE, 
+       "ndefine",      NDEFINE, 
+
+#endif
+
+       "gsize",        GSIZE, 
+       ".gsize",       GSIZE, 
+       "gfont",        GFONT, 
+       "include",      INCLUDE, 
+       "up",   UP, 
+       "down",         DOWN, 
+       "fwd",  FWD, 
+       "back",         BACK, 
+       "mark",         MARK, 
+       "lineup",       LINEUP, 
+       "matrix",       MATRIX, 
+       "col",  COL, 
+       "lcol",         LCOL, 
+       "ccol",         CCOL, 
+       "rcol",         RCOL, 
+       0,      0
+};
+
+struct {
+       char    *res;
+       char    *resval;
+} resword[]    ={
+       ">=",   "\\(>=",
+       "<=",   "\\(<=",
+       "==",   "\\(==",
+       "!=",   "\\(!=",
+       "+-",   "\\(+-",
+       "->",   "\\(->",
+       "<-",   "\\(<-",
+       "inf",  "\\(if",
+       "infinity",     "\\(if",
+       "partial",      "\\(pd",
+       "half", "\\f1\\(12\\fP",
+       "prime",        "\\f1\\(fm\\fP",
+       "dollar",       "\\f1$\\fP",
+       "nothing",      "",
+       "times",        "\\(mu",
+       "del",  "\\(gr",
+       "grad", "\\(gr",
+#ifdef NEQN
+       "<<",   "<<",
+       ">>",   ">>",
+       "approx",       "~\b\\d~\\u",
+       "cdot", "\\v'-.5'.\\v'.5'",
+       "...",  "...",
+       ",...,",        ",...,",
+#else
+       "<<",   "<\\h'-.3m'<",
+       ">>",   ">\\h'-.3m'>",
+       "approx",       "\\v'-.2m'\\z\\(ap\\v'.25m'\\(ap\\v'-.05m'",
+       "cdot", "\\v'-.3m'.\\v'.3m'",
+       "...",  "\\v'-.3m'\\ .\\ .\\ .\\ \\v'.3m'",
+       ",...,",        ",\\ .\\ .\\ .\\ ,\\|",
+#endif
+
+       "alpha",        "\\(*a",
+       "beta", "\\(*b",
+       "gamma",        "\\(*g",
+       "GAMMA",        "\\(*G",
+       "delta",        "\\(*d",
+       "DELTA",        "\\(*D",
+       "epsilon",      "\\(*e",
+       "EPSILON",      "\\f1E\\fP",
+       "omega",        "\\(*w",
+       "OMEGA",        "\\(*W",
+       "lambda",       "\\(*l",
+       "LAMBDA",       "\\(*L",
+       "mu",   "\\(*m",
+       "nu",   "\\(*n",
+       "theta",        "\\(*h",
+       "THETA",        "\\(*H",
+       "phi",  "\\(*f",
+       "PHI",  "\\(*F",
+       "pi",   "\\(*p",
+       "PI",   "\\(*P",
+       "sigma",        "\\(*s",
+       "SIGMA",        "\\(*S",
+       "xi",   "\\(*c",
+       "XI",   "\\(*C",
+       "zeta", "\\(*z",
+       "iota", "\\(*i",
+       "eta",  "\\(*y",
+       "kappa",        "\\(*k",
+       "rho",  "\\(*r",
+       "tau",  "\\(*t",
+       "omicron",      "\\(*o",
+       "upsilon",      "\\(*u",
+       "UPSILON",      "\\(*U",
+       "psi",  "\\(*q",
+       "PSI",  "\\(*Q",
+       "chi",  "\\(*x",
+       "and",  "\\f1and\\fP",
+       "for",  "\\f1for\\fP",
+       "if",   "\\f1if\\fP",
+       "Re",   "\\f1Re\\fP",
+       "Im",   "\\f1Im\\fP",
+       "sin",  "\\f1sin\\fP",
+       "cos",  "\\f1cos\\fP",
+       "tan",  "\\f1tan\\fP",
+       "arc",  "\\f1arc\\fP",
+       "sinh", "\\f1sinh\\fP",
+       "coth", "\\f1coth\\fP",
+       "tanh", "\\f1tanh\\fP",
+       "cosh", "\\f1cosh\\fP",
+       "lim",  "\\f1lim\\fP",
+       "log",  "\\f1log\\fP",
+       "max",  "\\f1max\\fP",
+       "min",  "\\f1min\\fP",
+       "ln",   "\\f1ln\\fP",
+       "exp",  "\\f1exp\\fP",
+       "det",  "\\f1det\\fP",
+       0,      0
+};
+
+tbl *lookup(tblp, name, defn)  /* find name in tbl. if defn non-null, install */
+tbl **tblp;
+char *name, *defn;
+{
+       register tbl *p;
+       register int h;
+       register char *s = name;
+       char *malloc();
+
+       for (h = 0; *s != '\0'; )
+               h += *s++;
+       h %= TBLSIZE;
+
+       for (p = tblp[h]; p != NULL; p = p->next)
+               if (strcmp(name, p->name) == 0) {       /* found it */
+                       if (defn != NULL)
+                               p->defn = defn;
+                       return(p);
+               }
+       /* didn't find it */
+       if (defn == NULL)
+               return(NULL);
+       p = (tbl *) malloc(sizeof (tbl));
+       if (p == NULL)
+               error(FATAL, "out of space in lookup");
+       p->name = name;
+       p->defn = defn;
+       p->next = tblp[h];
+       tblp[h] = p;
+       return(p);
+}
+
+init_tbl()     /* initialize all tables */
+{
+       int i;
+
+       for (i = 0; keyword[i].key != NULL; i++)
+               lookup(keytbl, keyword[i].key, keyword[i].keyval);
+       for (i = 0; resword[i].res != NULL; i++)
+               lookup(restbl, resword[i].res, resword[i].resval);
+}
diff --git a/usr/src/cmd/neqn/mark.c b/usr/src/cmd/neqn/mark.c
new file mode 100644 (file)
index 0000000..6e03156
--- /dev/null
@@ -0,0 +1,17 @@
+#include "e.h"
+
+mark(p1) int p1; {
+       markline = 1;
+       printf(".ds %d \\k(97\\*(%d\n", p1, p1);
+       yyval = p1;
+       if(dbg)printf(".\tmark %d\n", p1);
+}
+
+lineup(p1) {
+       markline = 1;
+       if (p1 == 0) {
+               yyval = oalloc();
+               printf(".ds %d \\h'|\\n(97u'\n", yyval);
+       }
+       if(dbg)printf(".\tlineup %d\n", p1);
+}
diff --git a/usr/src/cmd/neqn/matrix.c b/usr/src/cmd/neqn/matrix.c
new file mode 100644 (file)
index 0000000..209e37b
--- /dev/null
@@ -0,0 +1,62 @@
+#include "e.h"
+
+column(type, p1) int type, p1; {
+       int i;
+
+       lp[p1] = ct - p1 - 1;
+       if( dbg ){
+               printf(".\t%d column of", type);
+               for( i=p1+1; i<ct; i++ )
+                       printf(" S%d", lp[i]);
+               printf(", rows=%d\n",lp[p1]);
+       }
+       lp[ct++] = type;
+}
+
+matrix(p1) int p1; {
+       int nrow, ncol, i, j, k, hb, b, val[100];
+       char *space;
+
+       space = "\\ \\ ";
+       nrow = lp[p1];  /* disaster if rows inconsistent */
+       ncol = 0;
+       for( i=p1; i<ct; i += lp[i]+2 ){
+               ncol++;
+               if(dbg)printf(".\tcolct=%d\n",lp[i]);
+       }
+       for( k=1; k<=nrow; k++ ) {
+               hb = b = 0;
+               j = p1 + k;
+               for( i=0; i<ncol; i++ ) {
+                       hb = max(hb, eht[lp[j]]-ebase[lp[j]]);
+                       b = max(b, ebase[lp[j]]);
+                       j += nrow + 2;
+               }
+               if(dbg)printf(".\trow %d: b=%d, hb=%d\n", k, b, hb);
+               j = p1 + k;
+               for( i=0; i<ncol; i++ ) {
+                       ebase[lp[j]] = b;
+                       eht[lp[j]] = b + hb;
+                       j += nrow + 2;
+               }
+       }
+       j = p1;
+       for( i=0; i<ncol; i++ ) {
+               lpile(lp[j+lp[j]+1], j+1, j+lp[j]+1);
+               val[i] = yyval;
+               j += nrow + 2;
+       }
+       yyval = oalloc();
+       eht[yyval] = eht[val[0]];
+       ebase[yyval] = ebase[val[0]];
+       lfont[yyval] = rfont[yyval] = 0;
+       if(dbg)printf(".\tmatrix S%d: r=%d, c=%d, h=%d, b=%d\n",
+               yyval,nrow,ncol,eht[yyval],ebase[yyval]);
+       printf(".ds %d \"", yyval);
+       for( i=0; i<ncol; i++ )  {
+               printf("\\*(%d%s", val[i], i==ncol-1 ? "" : space);
+               ofree(val[i]);
+       }
+       printf("\n");
+       ct = p1;
+}
diff --git a/usr/src/cmd/neqn/move.c b/usr/src/cmd/neqn/move.c
new file mode 100644 (file)
index 0000000..2f3076c
--- /dev/null
@@ -0,0 +1,18 @@
+# include "e.h"
+# include "e.def"
+
+move(dir, amt, p) int dir, amt, p; {
+       int a;
+
+       yyval = p;
+       a = VERT( (amt+49)/50 );        /* nearest number of half-lines */
+       printf(".ds %d ", yyval);
+       if( dir == FWD || dir == BACK ) /* fwd, back */
+               printf("\\h'%s%du'\\*(%d\n", (dir==BACK) ? "-" : "", a, p);
+       else if (dir == UP)
+               printf("\\v'-%du'\\*(%d\\v'%du'\n", a, p, a);
+       else if (dir == DOWN)
+               printf("\\v'%du'\\*(%d\\v'-%du'\n", a, p, a);
+       if(dbg)printf(".\tmove %d dir %d amt %d; h=%d b=%d\n", 
+               p, dir, a, eht[yyval], ebase[yyval]);
+}
diff --git a/usr/src/cmd/neqn/over.c b/usr/src/cmd/neqn/over.c
new file mode 100644 (file)
index 0000000..4625e36
--- /dev/null
@@ -0,0 +1,28 @@
+# include "e.h"
+
+boverb(p1, p2) int p1, p2; {
+       int h, b, treg, d;
+
+       treg = oalloc();
+       yyval = p1;
+       d = VERT(1);
+       h = eht[p1] + eht[p2];
+       b = eht[p2] - d;
+       if(dbg)printf(".\tb:bob: S%d <- S%d over S%d; b=%d, h=%d\n", 
+               yyval, p1, p2, b, h);
+       nrwid(p1, ps, p1);
+       nrwid(p2, ps, p2);
+       printf(".nr %d \\n(%d\n", treg, p1);
+       printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, treg, treg, p2);
+       printf(".ds %d \\v'%du'\\h'\\n(%du-\\n(%du/2u'\\*(%d\\\n", 
+               yyval, eht[p2]-ebase[p2]-d, treg, p2, p2);
+       printf("\\h'-\\n(%du-\\n(%du/2u'\\v'%du'\\*(%d\\\n", 
+               p2, p1, -eht[p2]+ebase[p2]-ebase[p1], p1);
+       printf("\\h'-\\n(%du-\\n(%du-2u/2u'\\v'%du'\\l'\\n(%du'\\v'%du'\n", 
+                treg, p1, ebase[p1], treg, d);
+       ebase[yyval] = b;
+       eht[yyval] = h;
+       lfont[yyval] = rfont[yyval] = 0;
+       ofree(p2);
+       ofree(treg);
+}
diff --git a/usr/src/cmd/neqn/paren.c b/usr/src/cmd/neqn/paren.c
new file mode 100644 (file)
index 0000000..58c91bb
--- /dev/null
@@ -0,0 +1,106 @@
+# include "e.h"
+
+paren(leftc, p1, rightc) int p1, leftc, rightc; {
+       int n, m, h1, j, b1, v;
+       h1 = eht[p1]; b1 = ebase[p1];
+       yyval = p1;
+       n = max(b1+VERT(1), h1-b1-VERT(1)) / VERT(1);
+       if( n<2 ) n = 1;
+       m = n-2;
+       if (leftc=='{' || rightc == '}') {
+               n = n%2 ? n : ++n;
+               if( n<3 ) n=3;
+               m = n-3;
+       }
+       eht[yyval] = VERT(2 * n);
+       ebase[yyval] = (n)/2 * VERT(2);
+       if (n%2 == 0)
+               ebase[yyval] -= VERT(1);
+       v = b1 - h1/2 + VERT(1);
+       printf(".ds %d \\|\\v'%du'", yyval, v);
+       switch( leftc ) {
+               case 'n':       /* nothing */
+               case '\0':
+                       break;
+               case 'f':       /* floor */
+                       if (n <= 1)
+                               printf("\\(lf");
+                       else
+                               brack(m, "\\(bv", "\\(bv", "\\(lf");
+                       break;
+               case 'c':       /* ceiling */
+                       if (n <= 1)
+                               printf("\\(lc");
+                       else
+                               brack(m, "\\(lc", "\\(bv", "\\(bv");
+                       break;
+               case '{':
+                       printf("\\b'\\(lt");
+                       for(j = 0; j < m; j += 2) printf("\\(bv");
+                       printf("\\(lk");
+                       for(j = 0; j < m; j += 2) printf("\\(bv");
+                       printf("\\(lb'");
+                       break;
+               case '(':
+                       brack(m, "\\(lt", "\\(bv", "\\(lb");
+                       break;
+               case '[':
+                       brack(m, "\\(lc", "\\(bv", "\\(lf");
+                       break;
+               case '|':
+                       brack(m, "|", "|", "|");
+                       break;
+               default:
+                       brack(m, (char *) &leftc, (char *) &leftc, (char *) &leftc);
+                       break;
+               }
+       printf("\\v'%du'\\*(%d", -v, p1);
+       if( rightc ) {
+               printf("\\|\\v'%du'", v);
+               switch( rightc ) {
+                       case 'f':       /* floor */
+                               if (n <= 1)
+                                       printf("\\(rf");
+                               else
+                                       brack(m, "\\(bv", "\\(bv", "\\(rf");
+                               break;
+                       case 'c':       /* ceiling */
+                               if (n <= 1)
+                                       printf("\\(rc");
+                               else
+                                       brack(m, "\\(rc", "\\(bv", "\\(bv");
+                               break;
+                       case '}':
+                               printf("\\b'\\(rt");
+                               for(j = 0; j< m; j += 2)printf("\\(bv");
+                               printf("\\(rk");
+                               for(j = 0; j< m; j += 2) printf("\\(bv");
+                               printf("\\(rb'");
+                               break;
+                       case ']':
+                               brack(m, "\\(rc", "\\(bv", "\\(rf");
+                               break;
+                       case ')':
+                               brack(m, "\\(rt", "\\(bv", "\\(rb");
+                               break;
+                       case '|':
+                               brack(m, "|", "|", "|");
+                               break;
+                       default:
+                               brack(m, (char *) &rightc, (char *) &rightc, (char *) &rightc);
+                               break;
+               }
+               printf("\\v'%du'", -v);
+       }
+       printf("\n");
+       if(dbg)printf(".\tcurly: h=%d b=%d n=%d v=%d l=%c, r=%c\n", 
+               eht[yyval], ebase[yyval], n, v, leftc, rightc);
+}
+
+brack(m, t, c, b) int m; char *t, *c, *b; {
+       int j;
+       printf("\\b'%s", t);
+       for( j=0; j<m; j++)
+               printf("%s", c);
+       printf("%s'", b);
+}
diff --git a/usr/src/cmd/neqn/pile.c b/usr/src/cmd/neqn/pile.c
new file mode 100644 (file)
index 0000000..c2fca93
--- /dev/null
@@ -0,0 +1,62 @@
+# include "e.h"
+
+lpile(type, p1, p2) int type, p1, p2; {
+       int bi, hi, i, gap, h, b, nlist, nlist2, mid;
+       yyval = oalloc();
+       gap = VERT(1);
+       if( type=='-' ) gap = 0;
+       nlist = p2 - p1;
+       nlist2 = (nlist+1)/2;
+       mid = p1 + nlist2 -1;
+       h = 0;
+       for( i=p1; i<p2; i++ )
+               h += eht[lp[i]];
+       eht[yyval] = h + (nlist-1)*gap;
+       b = 0;
+       for( i=p2-1; i>mid; i-- )
+               b += eht[lp[i]] + gap;
+       ebase[yyval] = (nlist%2) ? b + ebase[lp[mid]]
+                       : b - VERT(1) - gap;
+       if(dbg) {
+               printf(".\tS%d <- %c pile of:", yyval, type);
+               for( i=p1; i<p2; i++)
+                       printf(" S%d", lp[i]);
+               printf(";h=%d b=%d\n", eht[yyval], ebase[yyval]);
+       }
+       nrwid(lp[p1], ps, lp[p1]);
+       printf(".nr %d \\n(%d\n", yyval, lp[p1]);
+       for( i = p1+1; i<p2; i++ ) {
+               nrwid(lp[i], ps, lp[i]);
+               printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", 
+                       lp[i], yyval, yyval, lp[i]);
+       }
+       printf(".ds %d \\v'%du'\\h'%du*\\n(%du'\\\n", yyval, ebase[yyval], 
+               type=='R' ? 1 : 0, yyval);
+       for(i = p2-1; i >=p1; i--) {
+               hi = eht[lp[i]]; 
+               bi = ebase[lp[i]];
+       switch(type) {
+
+       case 'L':
+               printf("\\v'%du'\\*(%d\\h'-\\n(%du'\\v'0-%du'\\\n", 
+                       -bi, lp[i], lp[i], hi-bi+gap);
+               continue;
+       case 'R':
+               printf("\\v'%du'\\h'-\\n(%du'\\*(%d\\v'0-%du'\\\n", 
+                       -bi, lp[i], lp[i], hi-bi+gap);
+               continue;
+       case 'C':
+       case '-':
+               printf("\\v'%du'\\h'\\n(%du-\\n(%du/2u'\\*(%d", 
+                       -bi, yyval, lp[i], lp[i]);
+               printf("\\h'-\\n(%du-\\n(%du/2u'\\v'0-%du'\\\n", 
+                       yyval, lp[i], hi-bi+gap);
+               continue;
+               }
+       }
+       printf("\\v'%du'\\h'%du*\\n(%du'\n", eht[yyval]-ebase[yyval]+gap, 
+               type!='R' ? 1 : 0, yyval);
+       for( i=p1; i<p2; i++ )
+               ofree(lp[i]);
+       lfont[yyval] = rfont[yyval] = 0;
+}
diff --git a/usr/src/cmd/neqn/shift.c b/usr/src/cmd/neqn/shift.c
new file mode 100644 (file)
index 0000000..068cb72
--- /dev/null
@@ -0,0 +1,70 @@
+# include "e.h"
+#include "e.def"
+
+bshiftb(p1, dir, p2) int p1, dir, p2; {
+       int shval, d1, h1, b1, h2, b2;
+       yyval = p1;
+       h1 = eht[p1];
+       b1 = ebase[p1];
+       h2 = eht[p2];
+       b2 = ebase[p2];
+       if( dir == SUB ) {      /* subscript */
+               d1 = VERT(1);
+               shval = - d1 + h2 - b2;
+               if( d1+b1 > h2 ) /* move little sub down */
+                       shval = b1-b2;
+               ebase[yyval] = b1 + max(0, h2-b1-d1);
+               eht[yyval] = h1 + max(0, h2-b1-d1);
+       } else {        /* superscript */
+               d1 = VERT(1);
+               ebase[yyval] = b1;
+               shval = -VERT(1) - b2;
+               if( VERT(1) + h2 < h1-b1 )      /* raise little super */
+                       shval = -(h1-b1) + h2-b2 - d1;
+               eht[yyval] = h1 + max(0, h2 - VERT(1));
+       }
+       if(dbg)printf(".\tb:b shift b: S%d <- S%d vert %d S%d vert %d; b=%d, h=%d\n", 
+               yyval, p1, shval, p2, -shval, ebase[yyval], eht[yyval]);
+       printf(".as %d \\v'%du'\\*(%d\\v'%du'\n", 
+               yyval, shval, p2, -shval);
+       ofree(p2);
+}
+
+shift(p1) int p1; {
+       ps -= deltaps;
+       yyval = p1;
+       if(dbg)printf(".\tshift: %d;ps=%d\n", yyval, ps);
+}
+
+shift2(p1, p2, p3) int p1, p2, p3; {
+       int effps, h1, h2, h3, b1, b2, b3, subsh, d1, d2, supsh;
+       int treg;
+
+       treg = oalloc();
+       yyval = p1;
+       if(dbg)printf(".\tshift2 s%d <- %d %d %d\n", yyval, p1, p2, p3);
+       effps = EFFPS(ps+deltaps);
+       h1 = eht[p1]; b1 = ebase[p1];
+       h2 = eht[p2]; b2 = ebase[p2];
+       h3 = eht[p3]; b3 = ebase[p3];
+       d1 = VERT(1);
+       subsh = -d1+h2-b2;
+       if( d1+b1 > h2 ) /* move little sub down */
+               subsh = b1-b2;
+       supsh = - VERT(1) - b3;
+       d2 = VERT(1);
+       if( VERT(1)+h3 < h1-b1 )
+               supsh = -(h1-b1) + (h3-b3) - d2;
+       eht[yyval] = h1 + max(0, h3-VERT(1)) + max(0, h2-b1-d1);
+       ebase[yyval] = b1+max(0, h2-b1-d1);
+       nrwid(p2, effps, p2);
+       nrwid(p3, effps, p3);
+       printf(".nr %d \\n(%d\n", treg, p3);
+       printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, treg, treg, p2);
+       printf(".as %d \\v'%du'\\*(%d\\h'-\\n(%du'\\v'%du'\\\n", 
+               p1, subsh, p2, p2, -subsh+supsh);
+       printf("\\*(%d\\h'-\\n(%du+\\n(%du'\\v'%du'\n", 
+               p3, p3, treg, -supsh);
+       ps += deltaps;
+       ofree(p2); ofree(p3); ofree(treg);
+}
diff --git a/usr/src/cmd/neqn/size.c b/usr/src/cmd/neqn/size.c
new file mode 100644 (file)
index 0000000..8f99fa6
--- /dev/null
@@ -0,0 +1,46 @@
+# include "e.h"
+
+setsize(p)     /* set size as found in p */
+char *p;
+{
+       if (*p == '+')
+               ps += atoi(p+1);
+       else if (*p == '-')
+               ps -= atoi(p+1);
+       else
+               ps = atoi(p);
+       if(dbg)printf(".\tsetsize %s; ps = %d\n", p, ps);
+}
+
+size(p1, p2) int p1, p2; {
+               /* old size in p1, new in ps */
+       int effps, effp1;
+
+       yyval = p2;
+       if(dbg)printf(".\tb:sb: S%d <- \\s%d S%d \\s%d; b=%d, h=%d\n", 
+               yyval, ps, p2, p1, ebase[yyval], eht[yyval]);
+       effps = EFFPS(ps);
+       effp1 = EFFPS(p1);
+       printf(".ds %d \\s%d\\*(%d\\s%d\n", 
+               yyval, effps, p2, effp1);
+       ps = p1;
+}
+
+globsize() {
+       char temp[20];
+
+       getstr(temp, 20);
+       if (temp[0] == '+')
+               gsize += atoi(temp+1);
+       else if (temp[0] == '-')
+               gsize -= atoi(temp+1);
+       else
+               gsize = atoi(temp);
+       yyval = eqnreg = 0;
+       setps(gsize);
+       ps = gsize;
+       if (gsize >= 12)        /* sub and sup size change */
+               deltaps = gsize / 4;
+       else
+               deltaps = gsize / 3;
+}
diff --git a/usr/src/cmd/neqn/sqrt.c b/usr/src/cmd/neqn/sqrt.c
new file mode 100644 (file)
index 0000000..ea20bea
--- /dev/null
@@ -0,0 +1,12 @@
+# include "e.h"
+
+sqrt(p2) int p2; {
+       yyval = p2;
+       nrwid(p2, ps, p2);
+       printf(".ds %d \\v'%du'\\e\\L'%du'\\l'\\n(%du'",
+               p2, ebase[p2], -eht[p2], p2);
+       printf("\\v'%du'\\h'-\\n(%du'\\*(%d\n", eht[p2]-ebase[p2], p2, p2);
+       eht[p2] += VERT(1);
+       if(dbg)printf(".\tsqrt: S%d <- S%d;b=%d, h=%d\n", 
+               p2, p2, ebase[p2], eht[p2]);
+}
diff --git a/usr/src/cmd/neqn/text.c b/usr/src/cmd/neqn/text.c
new file mode 100644 (file)
index 0000000..0686dca
--- /dev/null
@@ -0,0 +1,170 @@
+# include "e.h"
+# include "e.def"
+
+int    csp;
+int    psp;
+#define        CSSIZE  400
+char   cs[420];
+
+int    lf, rf; /* temporary spots for left and right fonts */
+
+text(t,p1) int t; char *p1; {
+       int c;
+       char *p;
+       tbl *tp, *lookup();
+       extern tbl *restbl;
+
+       yyval = oalloc();
+       ebase[yyval] = 0;
+       eht[yyval] = VERT(2);   /* 2 half-spaces */
+       lfont[yyval] = rfont[yyval] = ROM;
+       if (t == QTEXT)
+               p = p1;
+       else if ( t == SPACE )
+               p = "\\ ";
+       else if ( t == THIN )
+               p = "\\|";
+       else if ( t == TAB )
+               p = "\\t";
+       else if ((tp = lookup(&restbl, p1, NULL)) != NULL)
+               p = tp->defn;
+       else {
+               lf = rf = 0;
+               for (csp=psp=0; (c=p1[psp++])!='\0';) {
+                       rf = trans(c, p1);
+                       if (lf == 0)
+                               lf = rf;        /* save first */
+                       if (csp>CSSIZE)
+                               error(FATAL,"converted token %.25s... too long",p1);
+               }
+               cs[csp] = '\0';
+               p = cs;
+               lfont[yyval] = lf;
+               rfont[yyval] = rf;
+       }
+       if(dbg)printf(".\t%dtext: S%d <- %s; b=%d,h=%d,lf=%c,rf=%c\n",
+               t, yyval, p, ebase[yyval], eht[yyval], lfont[yyval], rfont[yyval]);
+       printf(".ds %d \"%s\n", yyval, p);
+}
+
+trans(c,p1) int c; char *p1; {
+       int f;
+       f = ROM;
+       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 ',':
+               if (rf == ITAL)
+                       shim();
+               roman(c); break;
+       case '.':
+               if (rf == ROM)
+                       roman(c);
+               else
+                       cs[csp++] = c;
+               f = rf;
+               break;
+       case '|':
+               if (rf == ITAL)
+                       shim();
+               shim(); roman(c); shim(); break;
+       case '=':
+               if (rf == ITAL)
+                       shim();
+               name4('e','q');
+               break;
+       case '+':
+               if (rf == ITAL)
+                       shim();
+               name4('p', 'l');
+               break;
+       case '>': case '<':
+               if (rf == ITAL)
+                       shim();
+               if (p1[psp]=='=') {     /* look ahead for == <= >= */
+                       name4(c,'=');
+                       psp++;
+               } else {
+                       cs[csp++] = c;  
+               }
+               break;
+       case '-':
+               if (rf == ITAL)
+                       shim();
+               if (p1[psp]=='>') {
+                       name4('-','>'); psp++;
+               } else {
+                       name4('m','i');
+               }
+               break;
+       case '/':
+               if (rf == ITAL)
+                       shim();
+               name4('s','l');
+               break;
+       case '~': case ' ':
+               shim(); shim(); break;
+       case '^':
+               shim(); break;
+       case '\\':      /* troff - pass 2 or 3 more chars */
+               if (rf == ITAL)
+                       shim();
+               cs[csp++] = c; cs[csp++] = c = p1[psp++]; cs[csp++] = p1[psp++];
+               if (c=='(') cs[csp++] = p1[psp++];
+               if (c=='*' && cs[csp-1] == '(') {
+                       cs[csp++] = p1[psp++];
+                       cs[csp++] = p1[psp++];
+               }
+               break;
+       case '\'':
+               cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = rf==ITAL ? ITAL : ROM;
+               name4('f','m');
+               cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = 'P';
+               f = rf==ITAL ? ITAL : ROM;
+               break;
+
+       case 'f':
+               if (ft == ITAL) {
+                       cs[csp++] = '\\'; cs[csp++] = '^';
+                       cs[csp++] = 'f';
+                       cs[csp++] = '\\'; cs[csp++] = '|';      /* trying | instead of ^ */
+                       f = ITAL;
+               }
+               else
+                       cs[csp++] = 'f';
+               break;
+       case 'j':
+               if (ft == ITAL) {
+                       cs[csp++] = '\\'; cs[csp++] = '^';
+                       cs[csp++] = 'j';
+                       f = ITAL;
+               }
+               else
+                       cs[csp++] = 'j';
+               break;
+       default:
+               cs[csp++] = c;
+               f = ft==ITAL ? ITAL : ROM;
+               break;
+       }
+       return(f);
+}
+
+shim() {
+       cs[csp++] = '\\'; cs[csp++] = '|';
+}
+
+roman(c) int c; {
+       cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = ROM;
+       cs[csp++] = c;
+       cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = 'P';
+}
+
+name4(c1,c2) int c1,c2; {
+       cs[csp++] = '\\';
+       cs[csp++] = '(';
+       cs[csp++] = c1;
+       cs[csp++] = c2;
+}
diff --git a/usr/src/cmd/plot/chrtab.c b/usr/src/cmd/plot/chrtab.c
new file mode 100644 (file)
index 0000000..4d8a81a
--- /dev/null
@@ -0,0 +1,98 @@
+char   chrtab[][16] = {
+0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000, /*, sp, */
+0010,0010,0010,0010,0010,0010,0010,0010,0000,0000,0010,0000,0000,0000,0000,0000, /*, !, */
+0024,0024,0024,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000, /*, ", */
+0000,0000,0000,0044,0044,0176,0044,0044,0176,0044,0044,0000,0000,0000,0000,0000, /*, #, */
+0000,0010,0010,0010,0076,0101,0100,0076,0001,0101,0076,0010,0010,0000,0000,0000, /*, $, */
+0000,0000,0000,0141,0142,0004,0010,0010,0020,0043,0103,0000,0000,0000,0000,0000, /*, %, */
+0000,0000,0070,0104,0110,0060,0060,0111,0106,0106,0071,0000,0000,0000,0000,0000, /*, &, */
+0004,0010,0020,0040,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000, /*, ', */
+0000,0004,0010,0020,0040,0040,0040,0040,0040,0040,0020,0010,0004,0000,0000,0000, /*, (, */
+0000,0040,0020,0010,0004,0004,0004,0004,0004,0004,0010,0020,0040,0000,0000,0000, /*, ), */
+0000,0000,0000,0010,0111,0052,0034,0177,0034,0052,0111,0010,0000,0000,0000,0000, /*, *, */
+0000,0000,0000,0000,0010,0010,0010,0177,0010,0010,0010,0000,0000,0000,0000,0000, /*, +, */
+0000,0000,0000,0000,0000,0000,0000,0000,0000,0030,0030,0010,0020,0000,0000,0000, /*, ,, */
+0000,0000,0000,0000,0000,0000,0000,0176,0000,0000,0000,0000,0000,0000,0000,0000, /*, -, */
+0000,0000,0000,0000,0000,0000,0000,0000,0000,0030,0030,0000,0000,0000,0000,0000, /*, ., */
+0000,0000,0001,0002,0004,0010,0010,0010,0020,0040,0100,0000,0000,0000,0000,0000, /*, /, */
+0000,0030,0044,0102,0102,0102,0102,0102,0102,0044,0030,0000,0000,0000,0000,0000, /*, 0, */
+0000,0010,0030,0010,0010,0010,0010,0010,0010,0010,0034,0000,0000,0000,0000,0000, /*, 1, */
+0000,0070,0104,0004,0004,0010,0020,0040,0100,0100,0174,0000,0000,0000,0000,0000, /*, 2, */
+0000,0176,0004,0004,0010,0014,0002,0002,0002,0104,0070,0000,0000,0000,0000,0000, /*, 3, */
+0000,0004,0014,0024,0044,0104,0176,0004,0004,0004,0004,0000,0000,0000,0000,0000, /*, 4, */
+0000,0174,0100,0100,0130,0144,0002,0002,0102,0044,0030,0000,0000,0000,0000,0000, /*, 5, */
+0000,0074,0102,0100,0130,0144,0102,0102,0102,0044,0030,0000,0000,0000,0000,0000, /*, 6, */
+0000,0176,0004,0004,0010,0010,0020,0020,0040,0040,0040,0000,0000,0000,0000,0000, /*, 7, */
+0000,0034,0042,0101,0042,0076,0101,0101,0101,0101,0076,0000,0000,0000,0000,0000, /*, 8, */
+0000,0034,0042,0101,0101,0101,0043,0036,0004,0010,0020,0040,0000,0000,0000,0000, /*, 9, */
+0000,0000,0000,0000,0000,0000,0030,0030,0000,0030,0030,0000,0000,0000,0000,0000, /*, :, */
+0000,0000,0000,0000,0000,0000,0030,0030,0000,0030,0030,0020,0040,0000,0000,0000, /*, ;, */
+0002,0004,0010,0020,0040,0100,0040,0020,0010,0004,0002,0000,0000,0000,0000,0000, /*, <, */
+0000,0000,0000,0000,0177,0000,0177,0000,0000,0000,0000,0000,0000,0000,0000,0000, /*, =, */
+0100,0040,0020,0010,0004,0002,0004,0010,0020,0040,0100,0000,0000,0000,0000,0000, /*, >, */
+0000,0030,0044,0102,0001,0002,0004,0010,0010,0000,0010,0000,0000,0000,0000,0000, /*, ?, */
+0000,0074,0102,0101,0115,0123,0121,0121,0121,0111,0046,0000,0000,0000,0000,0000, /*, @, */
+0000,0010,0024,0042,0101,0101,0177,0101,0101,0101,0101,0000,0000,0000,0000,0000, /*, A, */
+0000,0176,0101,0101,0101,0176,0101,0101,0101,0101,0176,0000,0000,0000,0000,0000, /*, B, */
+0000,0076,0101,0100,0100,0100,0100,0100,0100,0101,0076,0000,0000,0000,0000,0000, /*, C, */
+0000,0176,0101,0101,0101,0101,0101,0101,0101,0101,0176,0000,0000,0000,0000,0000, /*, D, */
+0000,0176,0100,0100,0100,0170,0100,0100,0100,0100,0177,0000,0000,0000,0000,0000, /*, E, */
+0000,0177,0100,0100,0100,0174,0100,0100,0100,0100,0100,0000,0000,0000,0000,0000, /*, F, */
+0000,0076,0101,0100,0100,0117,0101,0101,0101,0101,0076,0000,0000,0000,0000,0000, /*, G, */
+0000,0101,0101,0101,0101,0176,0101,0101,0101,0101,0101,0000,0000,0000,0000,0000, /*, H, */
+0000,0034,0010,0010,0010,0010,0010,0010,0010,0010,0034,0000,0000,0000,0000,0000, /*, I, */
+0000,0016,0004,0004,0004,0004,0004,0004,0104,0104,0070,0000,0000,0000,0000,0000, /*, J, */
+0000,0101,0102,0104,0110,0120,0160,0110,0104,0102,0101,0000,0000,0000,0000,0000, /*, K, */
+0000,0100,0100,0100,0100,0100,0100,0100,0100,0100,0177,0000,0000,0000,0000,0000, /*, L, */
+0000,0101,0143,0125,0111,0101,0101,0101,0101,0101,0101,0000,0000,0000,0000,0000, /*, M, */
+0000,0101,0141,0121,0111,0105,0103,0101,0101,0101,0101,0000,0000,0000,0000,0000, /*, N, */
+0000,0076,0101,0101,0101,0101,0101,0101,0101,0101,0076,0000,0000,0000,0000,0000, /*, O, */
+0000,0176,0101,0101,0101,0176,0100,0100,0100,0100,0100,0000,0000,0000,0000,0000, /*, P, */
+0000,0076,0101,0101,0101,0101,0101,0101,0131,0105,0076,0002,0001,0000,0000,0000, /*, Q, */
+0000,0176,0101,0101,0101,0176,0104,0102,0101,0101,0101,0000,0000,0000,0000,0000, /*, R, */
+0000,0076,0101,0100,0100,0076,0001,0001,0001,0101,0076,0000,0000,0000,0000,0000, /*, S, */
+0000,0177,0010,0010,0010,0010,0010,0010,0010,0010,0010,0000,0000,0000,0000,0000, /*, T, */
+0000,0101,0101,0101,0101,0101,0101,0101,0101,0101,0076,0000,0000,0000,0000,0000, /*, U, */
+0000,0101,0101,0101,0101,0101,0101,0101,0042,0024,0010,0000,0000,0000,0000,0000, /*, V, */
+0000,0101,0101,0101,0101,0111,0111,0125,0143,0101,0101,0000,0000,0000,0000,0000, /*, W, */
+0000,0101,0101,0042,0024,0010,0024,0042,0101,0101,0101,0000,0000,0000,0000,0000, /*, X, */
+0000,0101,0042,0024,0010,0010,0010,0010,0010,0010,0010,0000,0000,0000,0000,0000, /*, Y, */
+0000,0177,0001,0002,0004,0010,0020,0040,0100,0100,0177,0000,0000,0000,0000,0000, /*, Z, */
+0000,0034,0020,0020,0020,0020,0020,0020,0020,0020,0020,0034,0000,0000,0000,0000, /*, [, */
+0000,0000,0100,0040,0020,0010,0010,0010,0004,0002,0001,0000,0000,0000,0000,0000, /*, , \, */
+0000,0070,0010,0010,0010,0010,0010,0010,0010,0010,0010,0070,0000,0000,0000,0000, /*, ], */
+0010,0024,0042,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000, /*, ^, */
+0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0377,0000,0000, /*, _, */
+0040,0020,0010,0004,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000, /*, `, */
+0000,0000,0000,0000,0000,0074,0002,0076,0102,0102,0076,0000,0000,0000,0000,0000, /*, a, */
+0000,0100,0100,0100,0100,0174,0102,0102,0102,0102,0174,0000,0000,0000,0000,0000, /*, b, */
+0000,0000,0000,0000,0000,0074,0102,0100,0100,0102,0074,0000,0000,0000,0000,0000, /*, c, */
+0002,0002,0002,0002,0002,0076,0102,0102,0102,0102,0076,0000,0000,0000,0000,0000, /*, d, */
+0000,0000,0000,0000,0000,0074,0102,0174,0100,0102,0074,0000,0000,0000,0000,0000, /*, e, */
+0000,0016,0020,0020,0020,0176,0020,0020,0020,0020,0020,0000,0000,0000,0000,0000, /*, f, */
+0000,0000,0000,0000,0000,0076,0102,0102,0102,0102,0076,0002,0002,0102,0076,0000, /*, g, */
+0000,0100,0100,0100,0100,0174,0102,0102,0102,0102,0102,0000,0000,0000,0000,0000, /*, h, */
+0000,0000,0000,0010,0000,0030,0010,0010,0010,0010,0034,0000,0000,0000,0000,0000, /*, i, */
+0000,0000,0000,0010,0000,0030,0010,0010,0010,0010,0010,0010,0010,0050,0020,0000, /*, j, */
+0000,0100,0100,0100,0100,0106,0110,0120,0160,0110,0106,0000,0000,0000,0000,0000, /*, k, */
+0000,0030,0010,0010,0010,0010,0010,0010,0010,0010,0034,0000,0000,0000,0000,0000, /*, l, */
+0000,0000,0000,0000,0000,0166,0111,0111,0111,0111,0111,0000,0000,0000,0000,0000, /*, m, */
+0000,0000,0000,0000,0100,0174,0102,0102,0102,0102,0102,0000,0000,0000,0000,0000, /*, n, */
+0000,0000,0000,0000,0000,0074,0102,0102,0102,0102,0074,0000,0000,0000,0000,0000, /*, o, */
+0000,0000,0000,0000,0000,0174,0102,0102,0102,0102,0174,0100,0100,0100,0100,0000, /*, p, */
+0000,0000,0000,0000,0000,0076,0102,0102,0102,0102,0076,0002,0002,0002,0002,0000, /*, q, */
+0000,0000,0000,0000,0000,0134,0142,0100,0100,0100,0100,0000,0000,0000,0000,0000, /*, r, */
+0000,0000,0000,0000,0000,0076,0100,0074,0002,0102,0074,0000,0000,0000,0000,0000, /*, s, */
+0000,0020,0020,0020,0020,0176,0020,0020,0020,0020,0014,0000,0000,0000,0000,0000, /*, t, */
+0000,0000,0000,0000,0000,0102,0102,0102,0102,0102,0075,0000,0000,0000,0000,0000, /*, u, */
+0000,0000,0000,0000,0000,0101,0101,0101,0042,0024,0010,0000,0000,0000,0000,0000, /*, v, */
+0000,0000,0000,0000,0000,0111,0111,0111,0111,0111,0066,0000,0000,0000,0000,0000, /*, w, */
+0000,0000,0000,0000,0000,0102,0044,0030,0030,0044,0102,0000,0000,0000,0000,0000, /*, x, */
+0000,0000,0000,0000,0000,0102,0102,0102,0042,0024,0010,0020,0040,0100,0000,0000, /*, y, */
+0000,0000,0000,0000,0000,0176,0004,0010,0020,0040,0176,0000,0000,0000,0000,0000, /*, z, */
+0000,0014,0020,0020,0020,0020,0040,0020,0020,0020,0020,0014,0000,0000,0000,0000, /*, {, */
+0000,0010,0010,0010,0010,0000,0000,0010,0010,0010,0010,0000,0000,0000,0000,0000, /*, |, */
+0000,0030,0010,0010,0010,0010,0004,0010,0010,0010,0010,0030,0000,0000,0000,0000, /*, }, */
+0020,0052,0004,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000, /*, ~, */
+0000,0176,0176,0176,0176,0176,0176,0176,0176,0176,0176,0000,0000,0000,0000,0000, /*, del, */
+};
diff --git a/usr/src/cmd/plot/driver.c b/usr/src/cmd/plot/driver.c
new file mode 100644 (file)
index 0000000..52d0b1f
--- /dev/null
@@ -0,0 +1,128 @@
+#include <stdio.h>
+
+float deltx;
+float delty;
+
+main(argc,argv)  char **argv; {
+       int std=1;
+       FILE *fin;
+
+       while(argc-- > 1) {
+               if(*argv[1] == '-')
+                       switch(argv[1][1]) {
+                               case 'l':
+                                       deltx = atoi(&argv[1][2]) - 1;
+                                       break;
+                               case 'w':
+                                       delty = atoi(&argv[1][2]) - 1;
+                                       break;
+                               }
+
+               else {
+                       std = 0;
+                       if ((fin = fopen(argv[1], "r")) == NULL) {
+                               fprintf(stderr, "can't open %s\n", argv[1]);
+                               exit(1);
+                               }
+                       fplt(fin);
+                       }
+               argv++;
+               }
+       if (std)
+               fplt( stdin );
+       exit(0);
+       }
+
+
+fplt(fin)  FILE *fin; {
+       int c;
+       char s[256];
+       int xi,yi,x0,y0,x1,y1,r,dx,n,i;
+       int pat[256];
+
+       openpl();
+       while((c=getc(fin)) != EOF){
+               switch(c){
+               case 'm':
+                       xi = getsi(fin);
+                       yi = getsi(fin);
+                       move(xi,yi);
+                       break;
+               case 'l':
+                       x0 = getsi(fin);
+                       y0 = getsi(fin);
+                       x1 = getsi(fin);
+                       y1 = getsi(fin);
+                       line(x0,y0,x1,y1);
+                       break;
+               case 't':
+                       gets(s,fin);
+                       label(s);
+                       break;
+               case 'e':
+                       erase();
+                       break;
+               case 'p':
+                       xi = getsi(fin);
+                       yi = getsi(fin);
+                       point(xi,yi);
+                       break;
+               case 'n':
+                       xi = getsi(fin);
+                       yi = getsi(fin);
+                       cont(xi,yi);
+                       break;
+               case 's':
+                       x0 = getsi(fin);
+                       y0 = getsi(fin);
+                       x1 = getsi(fin);
+                       y1 = getsi(fin);
+                       space(x0,y0,x1,y1);
+                       break;
+               case 'a':
+                       xi = getsi(fin);
+                       yi = getsi(fin);
+                       x0 = getsi(fin);
+                       y0 = getsi(fin);
+                       x1 = getsi(fin);
+                       y1 = getsi(fin);
+                       arc(xi,yi,x0,y0,x1,y1);
+                       break;
+               case 'c':
+                       xi = getsi(fin);
+                       yi = getsi(fin);
+                       r = getsi(fin);
+                       circle(xi,yi,r);
+                       break;
+               case 'f':
+                       gets(s,fin);
+                       linemod(s);
+                       break;
+               case 'd':
+                       xi = getsi(fin);
+                       yi = getsi(fin);
+                       dx = getsi(fin);
+                       n = getsi(fin);
+                       for(i=0; i<n; i++)pat[i] = getsi(fin);
+                       dot(xi,yi,dx,n,pat);
+                       break;
+                       }
+               }
+       closepl();
+       }
+getsi(fin)  FILE *fin; {       /* get an integer stored in 2 ascii bytes. */
+       short a, b;
+       if((b = getc(fin)) == EOF)
+               return(EOF);
+       if((a = getc(fin)) == EOF)
+               return(EOF);
+       a = a<<8;
+       return(a|b);
+}
+gets(s,fin)  char *s;  FILE *fin; {
+       for( ; *s = getc(fin); s++)
+               if(*s == '\n')
+                       break;
+       *s = '\0';
+       return;
+}
diff --git a/usr/src/cmd/plot/vplot.c b/usr/src/cmd/plot/vplot.c
new file mode 100644 (file)
index 0000000..8fbaed0
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * Reads standard graphics input
+ * Makes a plot on a 200 dot-per-inch 11" wide
+ * Versatek plotter.
+ *
+ * Creates and leaves /usr/tmp/raster (1000 blocks)
+ * which is the bitmap
+ */
+#include "stdio.h"
+#include <signal.h>
+
+#define        NB      88
+#define BSIZ   512
+#define        mapx(x) ((1536*((x)-botx)/del)+centx)
+#define        mapy(y) ((1536*(del-(y)+boty)/del)-centy)
+#define SOLID -1
+#define DOTTED 014
+#define SHORTDASHED 034
+#define DOTDASHED 054
+#define LONGDASHED 074
+#define        SETSTATE        (('v'<<8)+1)
+
+int    linmod  = SOLID;
+int    again;
+int    done1;
+char   chrtab[][16];
+int    plotcom[]       = { 0200, 0, 0};
+int    eotcom[]                = { 0210, 0, 0};
+char   blocks  [NB][BSIZ];
+int    obuf[264];
+int    lastx;
+int    lasty;
+double topx    = 1536;
+double topy    = 1536;
+double botx    = 0;
+double boty    = 0;
+int    centx;
+int    centy;
+double delx    = 1536;
+double dely    = 1536;
+double del     = 1536;
+
+struct buf {
+       int     bno;
+       char    *block;
+};
+struct buf     bufs[NB];
+
+int    in, out;
+char *picture = "/usr/tmp/raster";
+
+main(argc, argv)
+char **argv;
+{
+       extern int onintr();
+       register i;
+
+       if (argc>1) {
+               in = open(argv[1], 0);
+               putpict();
+               exit(0);
+       }
+       signal(SIGTERM, onintr);
+       if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+               signal(SIGINT, onintr);
+another:
+       for (i=0; i<NB; i++) {
+               bufs[i].bno = -1;
+               bufs[i].block = blocks[i];
+       }
+       out = creat(picture, 0666);
+       in = open(picture, 0);
+       zseek(out, 32*32);
+       write(out, blocks[0], BSIZ);
+/*delete following code when filsys deals properly with
+holes in files*/
+       for(i=0;i<512;i++)
+               blocks[0][i] = 0;
+       zseek(out, 0);
+       for(i=0;i<32*32;i++)
+               write(out,blocks[0],512);
+/**/
+       getpict();
+       for (i=0; i<NB; i++)
+               if (bufs[i].bno != -1) {
+                       zseek(out, bufs[i].bno);
+                       write(out, bufs[i].block, BSIZ);
+               }
+       putpict();
+       if (again) {
+               close(in);
+               close(out);
+               goto another;
+       }
+       exit(0);
+}
+
+getpict()
+{
+       register x1, y1;
+
+       again = 0;
+       for (;;) switch (x1 = getc(stdin)) {
+
+       case 's':
+               botx = getw(stdin);
+               boty = getw(stdin);
+               topx = getw(stdin);
+               topy = getw(stdin);
+               delx = topx-botx;
+               dely = topy-boty;
+               if (dely/delx > 1536./2048.)
+                       del = dely;
+               else
+                       del = delx * (1566./2048.);
+               centx = 0;
+               centx = (2048 - mapx(topx)) / 2;
+               centy = 0;
+               centy = mapy(topy) / 2;
+               continue;
+
+       case 'l':
+               done1 |= 01;
+               x1 = mapx(getw(stdin));
+               y1 = mapy(getw(stdin));
+               lastx = mapx(getw(stdin));
+               lasty = mapy(getw(stdin));
+               line(x1, y1, lastx, lasty);
+               continue;
+
+       case 'm':
+               lastx = mapx(getw(stdin));
+               lasty = mapy(getw(stdin));
+               continue;
+
+       case 't':
+               done1 |= 01;
+               while ((x1 = getc(stdin)) != '\n')
+                       plotch(x1);
+               continue;
+
+       case 'e':
+               if (done1) {
+                       again++;
+                       return;
+               }
+               continue;
+
+       case 'p':
+               done1 |= 01;
+               lastx = mapx(getw(stdin));
+               lasty = mapy(getw(stdin));
+               point(lastx, lasty);
+               point(lastx+1, lasty);
+               point(lastx, lasty+1);
+               point(lastx+1, lasty+1);
+               continue;
+
+       case 'n':
+               done1 |= 01;
+               x1 = mapx(getw(stdin));
+               y1 = mapy(getw(stdin));
+               line(lastx, lasty, x1, y1);
+               lastx = x1;
+               lasty = y1;
+               continue;
+
+       case 'f':
+               getw(stdin);
+               getc(stdin);
+               switch(getc(stdin)) {
+               case 't':
+                       linmod = DOTTED;
+                       break;
+               default:
+               case 'i':
+                       linmod = SOLID;
+                       break;
+               case 'g':
+                       linmod = LONGDASHED;
+                       break;
+               case 'r':
+                       linmod = SHORTDASHED;
+                       break;
+               case 'd':
+                       linmod = DOTDASHED;
+                       break;
+               }
+               while((x1=getc(stdin))!='\n')
+                       if(x1==-1) return;
+               continue;
+
+       case 'd':
+               getw(stdin);
+               getw(stdin);
+               getw(stdin);
+               x1 = getw(stdin);
+               while (--x1 >= 0)
+                       getw(stdin);
+               continue;
+
+       case -1:
+               return;
+
+       default:
+               printf("Botch\n");
+               return;
+       }
+}
+
+plotch(c)
+register c;
+{
+       register j;
+       register char *cp;
+       int i;
+
+       if (c<' ' || c >0177)
+               return;
+       cp = chrtab[c-' '];
+       for (i = -16; i<16; i += 2) {
+               c = *cp++;
+               for (j=7; j>=0; --j)
+                       if ((c>>j)&1) {
+                               point(lastx+6-j*2, lasty+i);
+                               point(lastx+7-j*2, lasty+i);
+                               point(lastx+6-j*2, lasty+i+1);
+                               point(lastx+7-j*2, lasty+i+1);
+                       }
+       }
+       lastx += 16;
+}
+
+int    f; /* versatec file number */
+putpict()
+{
+       register x, *ip, *op;
+       int y;
+
+       if (f==0){
+               f = open("/dev/vp0", 1);
+               if (f < 0) {
+                       printf("Cannot open vp\n");
+                       exit(1);
+               }
+               ioctl(f, SETSTATE, plotcom);
+       }
+       op = obuf;
+       lseek(in, 0L, 0);
+       for (y=0; y<2048; y++) {
+               if ((y&077) == 0)
+                       read(in, blocks[0], 32*BSIZ);
+               for (x=0; x<32; x++)  {
+                       ip = (int *)&blocks[x][(y&077)<<3];
+                       *op++ = *ip++;
+                       *op++ = *ip++;
+                       *op++ = *ip++;
+                       *op++ = *ip++;
+               }
+               *op++ = 0;
+               *op++ = 0;
+               *op++ = 0;
+               *op++ = 0;
+               if (y&1) {
+                       write(f, (char *)obuf, sizeof(obuf));
+                       op = obuf;
+               }
+       }
+}
+
+line(x0, y0, x1, y1)
+register x0, y0;
+{
+       int dx, dy;
+       int xinc, yinc;
+       register res1;
+       int res2;
+       int slope;
+
+       xinc = 1;
+       yinc = 1;
+       if ((dx = x1-x0) < 0) {
+               xinc = -1;
+               dx = -dx;
+       }
+       if ((dy = y1-y0) < 0) {
+               yinc = -1;
+               dy = -dy;
+       }
+       slope = xinc*yinc;
+       res1 = 0;
+       res2 = 0;
+       if (dx >= dy) while (x0 != x1) {
+       if((x0+slope*y0)&linmod)
+       if (((x0>>6) + ((y0&~077)>>1)) == bufs[0].bno)
+               bufs[0].block[((y0&077)<<3)+((x0>>3)&07)] |= 1 << (7-(x0&07));
+       else
+               point(x0, y0);
+               if (res1 > res2) {
+                       res2 += dx - res1;
+                       res1 = 0;
+                       y0 += yinc;
+               }
+               res1 += dy;
+               x0 += xinc;
+       } else while (y0 != y1) {
+       if((x0+slope*y0)&linmod)
+       if (((x0>>6) + ((y0&~077)>>1)) == bufs[0].bno)
+               bufs[0].block[((y0&077)<<3)+((x0>>3)&07)] |= 1 << (7-(x0&07));
+       else
+               point(x0, y0);
+               if (res1 > res2) {
+                       res2 += dy - res1;
+                       res1 = 0;
+                       x0 += xinc;
+               }
+               res1 += dx;
+               y0 += yinc;
+       }
+       if((x1+slope*y1)&linmod)
+       if (((x1>>6) + ((y1&~077)>>1)) == bufs[0].bno)
+               bufs[0].block[((y1&077)<<3)+((x1>>3)&07)] |= 1 << (7-(x1&07));
+       else
+               point(x1, y1);
+}
+
+point(x, y)
+register x, y;
+{
+       register bno;
+
+       bno = ((x&03700)>>6) + ((y&03700)>>1);
+       if (bno != bufs[0].bno) {
+               if (bno < 0 || bno >= 1024)
+                       return;
+               getblk(bno);
+       }
+       bufs[0].block[((y&077)<<3)+((x>>3)&07)] |= 1 << (7-(x&07));
+}
+
+getblk(b)
+register b;
+{
+       register struct buf *bp1, *bp2;
+       register char *tp;
+
+loop:
+       for (bp1 = bufs; bp1 < &bufs[NB]; bp1++) {
+               if (bp1->bno == b || bp1->bno == -1) {
+                       tp = bp1->block;
+                       for (bp2 = bp1; bp2>bufs; --bp2) {
+                               bp2->bno = (bp2-1)->bno;
+                               bp2->block = (bp2-1)->block;
+                       }
+                       bufs[0].bno = b;
+                       bufs[0].block = tp;
+                       return;
+               }
+       }
+       zseek(out, bufs[NB-1].bno);
+       write(out, bufs[NB-1].block, BSIZ);
+       zseek(in, b);
+       read(in, bufs[NB-1].block, BSIZ);
+       bufs[NB-1].bno = b;
+       goto loop;
+}
+
+onintr()
+{
+       exit(1);
+}
+
+zseek(a, b)
+{
+       return(lseek(a, (long)b*512, 0));
+}
diff --git a/usr/src/cmd/prof/prof.c b/usr/src/cmd/prof/prof.c
new file mode 100644 (file)
index 0000000..519c1ec
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ *  Print execution profile
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <a.out.h>
+
+typedef        short UNIT;             /* unit of profiling */
+
+struct stat stbuf;
+struct nl {
+       char    name[8];
+       unsigned value;
+       float   time;
+       long    ncall;
+};
+
+struct hdr {
+       short   *lowpc;
+       short   *highpc;
+       int     ncount;
+};
+
+struct nl nl[600];
+
+struct cnt {
+       unsigned cvalue;
+       long    cncall;
+} cbuf[350];
+
+FILE   *pfile, *nfile;
+unsigned highpc;
+unsigned lowpc;
+double ransca;
+double ranoff;
+int    pcl;
+int    pch;
+unsigned       bufs;
+int    nname;
+double time;
+double actime;
+double totime;
+double maxtime;
+double scale;
+double lastx;
+double lasty;
+struct nl *np;
+struct nl *npe;
+int    aflg;
+int    vflg;
+int    lflg;
+long   symoff;
+
+main(argc, argv)
+char **argv;
+{
+       char *namfil;
+       int timcmp(), valcmp(), cntcmp();
+       int i, overlap;
+       long pfpos;
+       double lastsx;
+       struct cnt *cp;
+       double tx, ty;
+       struct exec xbuf;
+       struct hdr {
+               UNIT    *lowpc;
+               UNIT    *highpc;
+               int     ncount;
+       } h;
+
+       lowpc = -1;
+       highpc = -1;
+       argv++;
+       namfil = "a.out";
+       while (argc>1) {
+               if (**argv == '-') {
+                       if (*++*argv == 'l')
+                               lflg++;
+                       if (**argv == 'a')
+                               aflg = 040;
+                       if(**argv == 'v')
+                               vflg++;
+                       if(**argv >= '0' && **argv <= '9') {
+                               i = atoi(*argv);
+                               if(lowpc == -1)
+                                       lowpc = i;
+                               else
+                                       highpc = i;
+                       }
+               } else
+                       namfil = *argv;
+               argc--;
+               argv++;
+       }
+       if (lowpc >= 100)
+               lowpc = 0;
+       if(highpc <= lowpc || highpc > 100)
+               highpc = 100;
+       ransca = 100./(highpc-lowpc);
+       ranoff = 2040. + 40.8*lowpc*ransca;
+       if((nfile=fopen(namfil,"r"))==NULL) {
+               fprintf(stderr, "%s: not found\n", namfil);
+               done();
+       }
+       fread(&xbuf, 1, sizeof(xbuf), nfile);
+       if (xbuf.a_magic!=A_MAGIC1 && xbuf.a_magic!=A_MAGIC2 && xbuf.a_magic!=A_MAGIC3) {
+               fprintf(stderr, "%s: bad format\n", namfil);
+               done();
+       }
+       symoff = (long)xbuf.a_text + xbuf.a_data + xbuf.a_trsize + xbuf.a_drsize;
+       fseek(nfile, symoff+sizeof(xbuf), 0);
+       if((pfile = fopen("mon.out","r")) == NULL) {
+               fprintf(stderr, "No mon.out\n");
+               done();
+       }
+       fstat(fileno(pfile), &stbuf);
+       fread(&h, sizeof(struct hdr), 1, pfile);
+       lowpc = h.lowpc - (UNIT *)0;
+       highpc = h.highpc - (UNIT *)0;
+       bufs = stbuf.st_size - sizeof(struct hdr) - h.ncount*sizeof(struct cnt);
+       fread(cbuf, sizeof(struct cnt), h.ncount, pfile);
+       pfpos = ftell(pfile);
+       npe = nl;
+       for (nname = 0; xbuf.a_syms > 0; xbuf.a_syms -= sizeof(struct nlist)) {
+               struct nlist nbuf;
+               fread(&nbuf, sizeof(nbuf), 1, nfile);
+               if (nbuf.n_type!=N_TEXT && nbuf.n_type!=N_TEXT+N_EXT)
+                       continue;
+               if (aflg==0 && nbuf.n_type!=N_TEXT+N_EXT)
+                       continue;
+               npe->value = nbuf.n_value/sizeof(UNIT);
+               for (i=8; --i>=0;)
+                       npe->name[i] = nbuf.n_name[i];
+               npe++;
+               nname++;
+       }
+       if (nname == 0) {
+               fprintf(stderr, "%s: no symbols\n", namfil);
+               done();
+       }
+       npe->value = -1;
+       npe++;
+       cp = &cbuf[h.ncount]; while ((--cp)->cvalue==0); ++cp; h.ncount=cp-cbuf;
+       for (;--cp>=cbuf;) cp->cvalue /= sizeof(UNIT);
+       qsort(cbuf, h.ncount, sizeof(struct cnt), cntcmp);
+       qsort(nl, nname, sizeof(struct nl), valcmp);
+       cp = &cbuf[h.ncount-1]; np = npe;
+       while (--np>=nl) {
+               if (cp<cbuf || np->value > cp->cvalue) continue;
+               while (cp>=cbuf && cp->cvalue - np->value >11) --cp;
+               if (cp->cvalue >= np->value) {np->ncall = cp->cncall; --cp;}
+       }
+       scale = highpc - lowpc;
+       scale /= bufs/sizeof(UNIT);
+       for(i=0;;i++) {
+               register j;
+               unsigned UNIT ccnt;
+               fread(&ccnt, sizeof(ccnt), 1, pfile);
+               if(feof(pfile))
+                       break;
+               if (ccnt == 0)
+                       continue;
+               pcl = lowpc + scale*i;
+               pch = lowpc + scale*(i+1);
+               time = ccnt;
+               totime += time;
+               if(time > maxtime)
+                       maxtime = time;
+               for (j=0; j<nname; j++) {
+                       if (pch < nl[j].value)
+                               break;
+                       if (pcl >= nl[j+1].value)
+                               continue;
+                       overlap=(min(pch,nl[j+1].value)-max(pcl,nl[j].value));
+                       if (overlap>0) nl[j].time += overlap*time/scale;
+               }
+       }
+       if (totime==0.0) {
+               fprintf(stderr, "No time accumulated\n");
+/*
+               done();
+ */
+               totime=1.0;
+       }
+#ifdef plot
+       if(!vflg)
+               goto print;
+       openpl();
+       erase();
+       space(-2048, -2048, 2048, 2048);
+       line(-2040, -2040, -2040, 2040);
+       line(0, 2040, 0, -2040);
+       for(i=0; i<11; i++)
+               line(-2040, 2040-i*408, 0, 2040-i*408);
+       lastx = 0.;
+       lasty = ranoff;
+       scale = (4080.*ransca)/(bufs/sizeof(UNIT));
+       fclose(pfile);  /*to turn off eof*/
+       pfile = fopen("mon.out", "r");
+       fseek(pfile, pfpos, 0);
+       lastsx = 0.0;
+       for(;;) {
+               unsigned UNIT ccnt;
+               fread(&ccnt, sizeof(ccnt), 1, pfile);
+               if(feof(pfile))
+                       break;
+               time = ccnt;
+               tx = lastsx;
+               ty = lasty;
+               lastsx =- 2000.*time/totime;
+               lasty =- scale;
+               if(lasty >= -2040. && ty <= 2040.) {
+                       line((int)tx, (int)ty, (int)lastsx, (int)lasty);
+                       if (ccnt!=0 || lastx!=0.0) {
+                               tx = lastx;
+                               lastx = -time*2000./maxtime;
+                               ty =+ scale/2;
+                               line(0, (int)ty, (int)tx, (int)ty);
+                       }
+               }
+       }
+       scale = (4080.*ransca)/(highpc-lowpc);
+       lastx = 50.;
+       for(np = nl; np<npe;  np++) {
+               if(np->value < lowpc)
+                       continue;
+               if(np->value >= highpc)
+                       continue;
+               time = np->time/totime;
+               lasty = ranoff - (np->value - lowpc)*scale;
+               if(lasty >= -2040. && lasty <= 2040.) {
+                       char bufl[8+3], *namp;
+                       register j;
+                       line(0, (int)lasty, 50, (int)lasty);
+                       line((int)(lastx-50),(int)lasty,(int)lastx,(int)lasty);
+                       point((int)(lastx+30), (int)(lasty+10));
+                       namp = bufl;
+                       for(j=0; j<8; j++)
+                               if(np->name[j] != '_')
+                                       *namp++ = np->name[j];
+                       *namp++ = '\n';
+                       *namp++ = 0;
+                       label(bufl);
+               }
+               lastx =+ 500.;
+               if(lastx > 2000.)
+                       lastx = 50.;
+       }
+       done();
+
+print:
+#endif
+       actime = 0;
+       printf("    name %%time  cumsecs  #call  ms/call\n");
+       if (!lflg)
+               qsort(nl, nname, sizeof(struct nl), timcmp);
+       for (np = nl; np<npe-1; np++) {
+               time = np->time/totime;
+               actime += np->time;
+               printf("%8.8s%6.1f%9.2f", np->name, 100*time, actime/60);
+               if(np->ncall!=0) {
+                       printf("%7ld", np->ncall);
+                       printf(" %8.2f\n", np->time/(np->ncall*.06));
+               } else
+                       printf("\n");
+       }
+       done();
+}
+
+min(a, b)
+{
+       if (a<b)
+               return(a);
+       return(b);
+}
+
+max(a, b)
+{
+       if (a>b)
+               return(a);
+       return(b);
+}
+
+valcmp(p1, p2)
+struct nl *p1, *p2;
+{
+       return(p1->value - p2->value);
+}
+
+timcmp(p1, p2)
+struct nl *p1, *p2;
+{
+       float d;
+
+       d = p2->time - p1->time;
+       if (d > 0.0)
+               return(1);
+       if (d < 0.0)
+               return(-1);
+       return(0);
+}
+
+cntcmp(p1, p2)
+struct cnt *p1, *p2;
+{
+       return(p1->cvalue - p2->cvalue);
+}
+
+done()
+{
+
+#ifdef plot
+       if(vflg) {
+               point(0, -2040);
+               closepl();
+       }
+#endif
+       exit(0);
+}
diff --git a/usr/src/cmd/ratfor/r.g b/usr/src/cmd/ratfor/r.g
new file mode 100644 (file)
index 0000000..c692f2c
--- /dev/null
@@ -0,0 +1,66 @@
+%{
+extern int transfer;
+extern int     indent;
+%}
+
+%term  IF ELSE FOR WHILE BREAK NEXT 
+%term  DIGITS DO
+%term  GOK DEFINE INCLUDE
+%term  REPEAT UNTIL
+%term  RETURN
+%term  SWITCH CASE DEFAULT
+%%
+
+statl  : statl  stat
+       |
+       ;
+stat   : if stat       ={ indent--; outcont($1); }
+       | ifelse stat   ={ indent--; outcont($1+1); }
+       | switch fullcase '}'   ={ endsw($1, $2); }
+       | while stat    ={ whilestat($1); }
+       | for stat      ={ forstat($1); }
+       | repeat stat UNTIL     ={ untils($1,1); }
+       | repeat stat           ={ untils($1,0); }
+       | BREAK ={ breakcode(); }
+       | NEXT          ={ nextcode(); }
+       | do stat       ={ dostat($1); }
+       | GOK           ={ gokcode($1); }
+       | RETURN        ={ retcode(); }
+       | ';'
+       | '{' statl '}'
+       | label stat
+       | error         ={ errcode(); yyclearin; }
+       ;
+switch : sw '{'
+       ;
+sw     : SWITCH        ={ swcode(); }
+       ;
+fullcase: caselist     ={ $$ = 0; }
+       | caselist defpart      ={ $$ = 1; }
+       ;
+caselist: casepart
+       | caselist casepart
+       ;
+defpart        : default statl
+       ;
+default        : DEFAULT       ={ getdefault(); }
+       ;
+casepart: case statl
+       ;
+case   : CASE  ={ getcase(); }
+       ;
+label  : DIGITS        ={ transfer = 0; outcode($1); }
+       ;
+if     : IF            ={ ifcode(); }
+       ;
+ifelse : if stat ELSE  ={ elsecode($1); }
+       ;
+while  : WHILE ={ whilecode(); }
+       ;
+for    : FOR           ={ forcode(); }
+       ;
+repeat : REPEAT        ={ repcode(); }
+       ;
+do     : DO            ={ docode(); }
+       ;
+%%
diff --git a/usr/src/cmd/ratfor/r.h b/usr/src/cmd/ratfor/r.h
new file mode 100644 (file)
index 0000000..47a6ee7
--- /dev/null
@@ -0,0 +1,64 @@
+#include <stdio.h>
+#include "y.tab.h"
+
+#
+#define        putbak(c)       *ip++ = c
+/*     #define getchr()        (ip>ibuf?*--ip: getc(infile[infptr]))   */
+
+#define        LET     1
+#define        DIG     2
+#define        CRAP    3
+#define        COMMENT '#'
+#define        QUOTE   '"'
+
+extern int     transfer;
+
+#define        INDENT  3       /* indent delta */
+#ifdef gcos
+#define        CONTFLD 6
+#endif
+#ifdef unix
+#define        CONTFLD 1
+#endif
+extern int     contfld;        /* column for continuation char */
+extern int     contchar;
+extern int     dbg;
+extern int     yyval;
+extern int     *yypv;
+extern int     yylval;
+extern int     errorflag;
+
+extern char    comment[];      /* save input comments here */
+extern int     comptr; /* next free slot in comment */
+extern int     printcom;       /* print comments, etc., if on */
+extern int     indent; /* level of nesting for indenting */
+
+extern char    ibuf[];
+extern char    *ip;
+
+extern FILE    *outfil;        /* output file id */
+extern FILE    *infile[];
+extern char    *curfile[];
+extern int     infptr;
+extern int     linect[];
+
+extern char    fcname[];
+
+extern int     svargc;
+extern char    **svargv;
+
+#define EOS 0
+#define        HSHSIZ  101
+struct nlist {
+       char    *name;
+       char    *def;
+       int     ydef;
+       struct  nlist *next;
+};
+
+struct nlist   *lookup();
+char   *install();
+char   *malloc();
+extern char    *fcnloc;
+
+extern char    type[];
diff --git a/usr/src/cmd/ratfor/r0.c b/usr/src/cmd/ratfor/r0.c
new file mode 100644 (file)
index 0000000..3d84e70
--- /dev/null
@@ -0,0 +1,83 @@
+#include "r.h"
+
+int    swlevel = -1;
+int    swexit[5];
+int    nextcase[5];
+
+swcode() {
+       transfer = 0;
+       putcom("switch");
+       swlevel++;
+       if (swlevel >= 5)
+               error("Switches nested > 5");
+       swexit[swlevel] = yyval = genlab(1);
+       outcode("\tI");
+       outnum(yyval);
+       outcode(" = ");
+       balpar();
+       outdon();
+       nextcase[swlevel] = 0;
+       indent++;
+}
+
+getcase() {
+       int t, lpar;
+       char token[100];
+
+       if (nextcase[swlevel] != 0) {
+               outgoto(swexit[swlevel]);
+               outcont(nextcase[swlevel]);
+       }
+       indent--;
+       outcode("\tif(.not.(");
+       do {
+               outcode("I");
+               outnum(swexit[swlevel]);
+               outcode(".eq.(");
+               lpar = 0;
+               do {
+                       if ((t=gtok(token)) == ':')
+                               break;
+                       if (t == '(')
+                               lpar++;
+                       else if (t == ')')
+                               lpar--;
+                       else if (t == ',') {
+                               if (lpar == 0)
+                                       break;
+                               }
+                       outcode(token);
+               } while (lpar >= 0);
+               if (lpar < 0)
+                       error("Missing left parenthesis in case");
+               if (t == ',')
+                       outcode(").or.");
+       } while (t != ':');
+       if (lpar != 0)
+               error("Missing parenthesis in case");
+       outcode(")))");
+       nextcase[swlevel] = genlab(1);
+       outgoto(nextcase[swlevel]);
+       indent++;
+}
+
+getdefault() {
+       char token[20];
+       if (gnbtok(token) != ':')
+               error("Missing colon after default");
+       outgoto(swexit[swlevel]);
+       outcont(nextcase[swlevel]);
+       indent--;
+       putcom("default");
+       indent++;
+}
+
+endsw(n, def) {
+       if (def == 0)
+               outcont(nextcase[swlevel]);
+       swlevel--;
+       if (swlevel < -1)
+               error("Switches unwound too far");
+       indent--;
+       outcont(n);
+}
diff --git a/usr/src/cmd/ratfor/r1.c b/usr/src/cmd/ratfor/r1.c
new file mode 100644 (file)
index 0000000..b43b8c0
--- /dev/null
@@ -0,0 +1,371 @@
+#include "r.h"
+
+#define        wasbreak        brkused[brkptr]==1 || brkused[brkptr]==3
+#define        wasnext brkused[brkptr]==2 || brkused[brkptr]==3
+
+int    transfer        = 0;    /* 1 if just finished retrun, break, next */
+
+char   fcname[10];
+char   scrat[500];
+
+int    brkptr  = -1;
+int    brkstk[10];     /* break label */
+int    typestk[10];    /* type of loop construct */
+int    brkused[10];    /* loop contains BREAK or NEXT */
+
+int    forptr  = 0;
+char   *forstk[10];
+
+repcode() {
+       transfer = 0;
+       outcont(0);
+       putcom("repeat");
+       yyval = genlab(3);
+       indent++;
+       outcont(yyval);
+       brkstk[++brkptr] = yyval+1;
+       typestk[brkptr] = REPEAT;
+       brkused[brkptr] = 0;
+}
+
+untils(p1,un) int p1,un; {
+       outnum(p1+1);
+       outtab();
+       if (un > 0) {
+               outcode("if(.not.");
+               balpar();
+               outcode(")");
+       }
+       transfer = 0;
+       outgoto(p1);
+       indent--;
+       if (wasbreak)
+               outcont(p1+2);
+       brkptr--;
+}
+
+ifcode() {
+       transfer = 0;
+       outtab();
+       outcode("if(.not.");
+       balpar();
+       outcode(")");
+       outgoto(yyval=genlab(2));
+       indent++;
+}
+
+elsecode(p1) {
+       outgoto(p1+1);
+       indent--;
+       putcom("else");
+       indent++;
+       outcont(p1);
+}
+
+whilecode() {
+       transfer = 0;
+       outcont(0);
+       putcom("while");
+       brkstk[++brkptr] = yyval = genlab(2);
+       typestk[brkptr] = WHILE;
+       brkused[brkptr] = 0;
+       outnum(yyval);
+       outtab();
+       outcode("if(.not.");
+       balpar();
+       outcode(")");
+       outgoto(yyval+1);
+       indent++;
+}
+
+whilestat(p1) int p1; {
+       outgoto(p1);
+       indent--;
+       putcom("endwhile");
+       outcont(p1+1);
+       brkptr--;
+}
+
+balpar() {
+       register c, lpar;
+       while ((c=gtok(scrat)) == ' ' || c == '\t')
+               ;
+       if (c != '(') {
+               error("missing left paren");
+               return;
+       }
+       outcode(scrat);
+       lpar = 1;
+       do {
+               c = gtok(scrat);
+               if (c==';' || c=='{' || c=='}' || c==EOF) {
+                       pbstr(scrat);
+                       break;
+               }
+               if (c=='(')
+                       lpar++;
+               else if (c==')')
+                       lpar--;
+               else if (c == '\n') {
+                       while ((c = gtok(scrat)) == ' ' || c=='\t' || c=='\n')
+                               ;
+                       pbstr(scrat);
+                       continue;
+               }
+               else if (c == '=' && scrat[1] == '\0')
+                       error("assigment inside conditional");
+               outcode(scrat);
+       } while (lpar > 0);
+       if (lpar != 0)
+               error("missing parenthesis");
+}
+
+int    labval  = 23000;
+
+genlab(n){
+       labval += n;
+       return(labval-n);
+}
+
+gokcode(p1) {
+       transfer = 0;
+       outtab();
+       outcode(p1);
+       eatup();
+       outdon();
+}
+
+eatup() {
+       int t, lpar;
+       char temp[100];
+       lpar = 0;
+       do {
+               if ((t = gtok(scrat)) == ';' || t == '\n')
+                       break;
+               if (t == '{' || t == '}' || t == EOF) {
+                       pbstr(scrat);
+                       break;
+               }
+               if (t == ',' || t == '+' || t == '-' || t == '*' || t == '('
+                 || t == '&' || t == '|' || t == '=') {
+                       while (gtok(temp) == '\n')
+                               ;
+                       pbstr(temp);
+               }
+               if (t == '(')
+                       lpar++;
+               else if (t==')') {
+                       lpar--;
+                       if (lpar < 0) {
+                               error("missing left paren");
+                               return(1);
+                       }
+               }
+               outcode(scrat);
+       } while (lpar >= 0);
+       if (lpar > 0) {
+               error("missing right paren");
+               return(1);
+       }
+       return(0);
+}
+
+forcode(){
+       int lpar, t;
+       char *ps, *qs;
+
+       transfer = 0;
+       outcont(0);
+       putcom("for");
+       yyval = genlab(3);
+       brkstk[++brkptr] = yyval+1;
+       typestk[brkptr] = FOR;
+       brkused[brkptr] = 0;
+       forstk[forptr++] = malloc(1);
+       if ((t = gnbtok(scrat)) != '(') {
+               error("missing left paren in FOR");
+               pbstr(scrat);
+               return;
+       }
+       if (gnbtok(scrat) != ';') {     /* real init clause */
+               pbstr(scrat);
+               outtab();
+               if (eatup() > 0) {
+                       error("illegal FOR clause");
+                       return;
+               }
+               outdon();
+       }
+       if (gnbtok(scrat) == ';')       /* empty condition */
+               outcont(yyval);
+       else {  /* non-empty condition */
+               pbstr(scrat);
+               outnum(yyval);
+               outtab();
+               outcode("if(.not.(");
+               for (lpar=0; lpar >= 0;) {
+                       if ((t = gnbtok(scrat)) == ';')
+                               break;
+                       if (t == '(')
+                               lpar++;
+                       else if (t == ')') {
+                               lpar--;
+                               if (lpar < 0) {
+                                       error("missing left paren in FOR clause");
+                                       return;
+                               }
+                       }
+                       if (t != '\n')
+                               outcode(scrat);
+               }
+               outcode("))");
+               outgoto(yyval+2);
+               if (lpar < 0)
+                       error("invalid FOR clause");
+       }
+       ps = scrat;
+       for (lpar=0; lpar >= 0;) {
+               if ((t = gtok(ps)) == '(')
+                       lpar++;
+               else if (t == ')')
+                       lpar--;
+               if (lpar >= 0 && t != '\n')
+                       while(*ps)
+                               ps++;
+       }
+       *ps = '\0';
+       qs = forstk[forptr-1] = malloc((unsigned)(ps-scrat+1));
+       ps = scrat;
+       while (*qs++ = *ps++)
+               ;
+       indent++;
+}
+
+forstat(p1) int p1; {
+       char *bp, *q;
+       bp = forstk[--forptr];
+       if (wasnext)
+               outnum(p1+1);
+       if (nonblank(bp)){
+               outtab();
+               outcode(bp);
+               outdon();
+       }
+       outgoto(p1);
+       indent--;
+       putcom("endfor");
+       outcont(p1+2);
+       for (q=bp; *q++;);
+       free(bp);
+       brkptr--;
+}
+
+retcode() {
+       register c;
+       if ((c = gnbtok(scrat)) != '\n' && c != ';' && c != '}') {
+               pbstr(scrat);
+               outtab();
+               outcode(fcname);
+               outcode(" = ");
+               eatup();
+               outdon();
+       }
+       else if (c == '}')
+               pbstr(scrat);
+       outtab();
+       outcode("return");
+       outdon();
+       transfer = 1;
+}
+
+docode() {
+       transfer = 0;
+       outtab();
+       outcode("do ");
+       yyval = genlab(2);
+       brkstk[++brkptr] = yyval;
+       typestk[brkptr] = DO;
+       brkused[brkptr] = 0;
+       outnum(yyval);
+       eatup();
+       outdon();
+       indent++;
+}
+
+dostat(p1) int p1; {
+       outcont(p1);
+       indent--;
+       if (wasbreak)
+               outcont(p1+1);
+       brkptr--;
+}
+
+#ifdef gcos
+#define        atoi(s) (*s-'0')        /* crude!!! */
+#endif
+
+breakcode() {
+       int level, t;
+
+       level = 0;
+       if ((t=gnbtok(scrat)) == DIG)
+               level = atoi(scrat) - 1;
+       else if (t != ';')
+               pbstr(scrat);
+       if (brkptr-level < 0)
+               error("illegal BREAK");
+       else {
+               outgoto(brkstk[brkptr-level]+1);
+               brkused[brkptr-level] |= 1;
+       }
+       transfer = 1;
+}
+
+nextcode() {
+       int level, t;
+
+       level = 0;
+       if ((t=gnbtok(scrat)) == DIG)
+               level = atoi(scrat) - 1;
+       else if (t != ';')
+               pbstr(scrat);
+       if (brkptr-level < 0)
+               error("illegal NEXT");
+       else {
+               outgoto(brkstk[brkptr-level]);
+               brkused[brkptr-level] |= 2;
+       }
+       transfer = 1;
+}
+
+nonblank(s) char *s; {
+       int c;
+       while (c = *s++)
+               if (c!=' ' && c!='\t' && c!='\n')
+                       return(1);
+       return(0);
+}
+
+int    errorflag       = 0;
+
+error(s1) char *s1; {
+       if (errorflag == 0)
+               fprintf(stderr, "ratfor:");
+       fprintf(stderr, "error at line %d, file %s: ",linect[infptr],curfile[infptr]);
+       fprintf(stderr, s1);
+       fprintf(stderr, "\n");
+       errorflag = 1;
+}
+
+errcode() {
+       int c;
+       if (errorflag == 0)
+               fprintf(stderr, "******\n");
+       fprintf(stderr, "*****F ratfor:");
+       fprintf(stderr, "syntax error, line %d, file %s\n", linect[infptr], curfile[infptr]);
+       while ((c=getchr())!=';' && c!='}' && c!='\n' && c!=EOF && c!='\0')
+               ;
+       if (c == EOF || c == '\0')
+               putbak(c);
+       errorflag = 1;
+}
diff --git a/usr/src/cmd/ratfor/r2.c b/usr/src/cmd/ratfor/r2.c
new file mode 100644 (file)
index 0000000..435933c
--- /dev/null
@@ -0,0 +1,210 @@
+#include "r.h"
+
+extern int hollerith;
+
+char   outbuf[80];
+int    outp    = 0;
+int    cont    = 0;
+int    contchar        = '&';
+
+char   comment[320];
+int    comptr  = 0;
+int    indent  = 0;
+
+outdon() {
+       outbuf[outp] = '\0';
+       if (outp > 0)
+               fprintf(outfil, "%s\n", outbuf);
+       outp = cont = 0;
+}
+
+putcom(s) char *s; {
+       if (printcom) {
+               ptc('c');
+               outtab();
+               pts(s);
+               outdon();
+       }
+}
+
+outcode(xp) char *xp; {
+       register c, c1, j;
+       char *q, *p;
+
+       p = (char *) xp;        /* shut lint up */
+       if (cont == 0 && comptr > 0)    /* flush comment if not on continuation */
+               flushcom();
+       while( (c = *p++) ){
+               c1 = *p;
+               if (type[c] == LET || type[c] == DIG) {
+                       pts(p-1);
+                       break;
+               }
+               switch(c){
+
+               case '"': case '\'':
+                       j = 0;
+                       for (q=p; *q; q++) {
+                               if (*q == '\\')
+                                       q++;
+                               j++;
+                       }
+                       if (outp+j+2 > 71)
+                               contcard();
+                       if (hollerith) {
+                               outnum(--j);
+                               ptc('h');
+                       } else
+                               ptc(c);
+                       while (*p != c) {
+                               if (*p == '\\')
+                                       p++;
+                               ptc(*p++);
+                       }
+                       if (!hollerith)
+                               ptc(c);
+                       p++;
+                       break;
+               case '$': case '\\':
+                       if (strlen(p-1)+outp > 71)
+                               contcard();
+                       if (c1 == '"' || c1 == '\'') {
+                               ptc(c1);
+                               p++;
+                       } else
+                               for (p--; *p; p++)
+                                       ptc(*p);
+                       break;
+               case '%':
+                       outp = 0;
+                       while (*p)
+                               ptc(*p++);
+                       break;
+               case '>':
+                       if( c1=='=' ){
+                               pts(".ge."); p++;
+                       } else
+                               pts(".gt.");
+                       break;
+               case '<':
+                       if( c1=='=' ){
+                               pts(".le."); p++;
+                       } else if( c1=='>' ){
+                               pts(".ne."); p++;
+                       } else
+                               pts(".lt.");
+                       break;
+               case '=':
+                       if( c1=='=' ){
+                               pts(".eq."); p++;
+                       } else
+                               ptc('=');
+                       break;
+               case '!': case '^':
+                       if( c1=='=' ){
+                               pts(".ne."); p++;
+                       } else
+                               pts(".not.");
+                       break;
+               case '&':
+                       if( c1=='&' )
+                               p++;
+                       pts(".and.");
+                       break;
+               case '|':
+                       if( c1=='|' )
+                               p++;
+                       pts(".or.");
+                       break;
+               case '\t':
+                       outtab();
+                       break;
+               case '\n':
+                       ptc(' ');
+                       break;
+               default:
+                       ptc(c);
+                       break;
+               }
+       }
+}
+
+ptc(c) char c; {
+       if( outp > 71 )
+               contcard();
+       outbuf[outp++] = c;
+}
+
+pts(s) char *s; {
+       if (strlen(s)+outp > 71)
+               contcard();
+       while(*s)
+               ptc(*s++);
+}
+
+contcard(){
+       int n;
+       outbuf[outp] = '\0';
+       fprintf(outfil, "%s\n", outbuf);
+       n = 6;
+       if (printcom) {
+               n += INDENT * indent + 1;
+               if (n > 35) n = 35;
+       }
+       for( outp=0; outp<n; outbuf[outp++] = ' ' );
+       outbuf[contfld-1] = contchar;
+       cont++;
+       if (cont > 19)
+               error("more than 19 continuation cards");
+}
+
+outtab(){
+       int n;
+       n = 6;
+       if (printcom) {
+               n += INDENT * indent;
+               if (n > 35) n = 35;
+       }
+       while (outp < n)
+               ptc(' ');
+}
+
+outnum(n) int n; {
+       int a;
+       if( a = n/10 )
+               outnum(a);
+       ptc(n%10 + '0');
+}
+
+outcont(n) int n; {
+       transfer = 0;
+       if (n == 0 && outp == 0)
+               return;
+       if( n > 0 )
+               outnum(n);
+       outcode("\tcontinue");
+       outdon();
+}
+
+outgoto(n) int n; {
+       if (transfer != 0)
+               return;
+       outcode("\tgoto ");
+       outnum(n);
+       outdon();
+}
+
+flushcom() {
+       int i, j;
+       if (printcom == 0)
+               comptr = 0;
+       else if (cont == 0 && comptr > 0) {
+               for (i=j=0; i < comptr; i++)
+                       if (comment[i] == '\n') {
+                               comment[i] = '\0';
+                               fprintf(outfil, "%s\n", &comment[j]);
+                               j = i + 1;
+                       }
+               comptr = 0;
+       }
+}
diff --git a/usr/src/cmd/ratfor/rlex.c b/usr/src/cmd/ratfor/rlex.c
new file mode 100644 (file)
index 0000000..c150d24
--- /dev/null
@@ -0,0 +1,244 @@
+# include "r.h"
+
+char *keyword [] = {
+       "do",
+       "if",
+       "else",
+       "for",
+       "repeat",
+       "until",
+       "while",
+       "break",
+       "next",
+       "define",
+       "include",
+       "return",
+       "switch",
+       "case",
+       "default",
+       0};
+
+int keytran[] = {
+       DO,
+       IF,
+       ELSE,
+       FOR,
+       REPEAT,
+       UNTIL,
+       WHILE,
+       BREAK,
+       NEXT,
+       DEFINE,
+       INCLUDE,
+       RETURN,
+       SWITCH,
+       CASE,
+       DEFAULT,
+       0};
+
+char   *fcnloc;        /* spot for "function" */
+
+int    svargc;
+char   **svargv;
+char   *curfile[10]    = { "" };
+int    infptr  = 0;
+FILE   *outfil = { stdout };
+FILE   *infile[10]     = { stdin };
+int    linect[10];
+
+int    contfld = CONTFLD;      /* place to put continuation char */
+int    printcom        = 0;    /* print comments if on */
+int    hollerith       = 0;    /* convert "..." to 27H... if on */
+
+#ifdef gcos
+char   *ratfor "tssrat";
+int    bcdrat[2];
+char   *bwkmeter       ".           bwkmeter    ";
+int    bcdbwk[5];
+#endif
+
+main(argc,argv) int argc; char **argv; {
+       int i;
+       while(argc>1 && argv[1][0]=='-') {
+               if(argv[1][1]=='6') {
+                       contfld=6;
+                       if (argv[1][2]!='\0')
+                               contchar = argv[1][2];
+               } else if (argv[1][1] == 'C')
+                       printcom++;
+               else if (argv[1][1] == 'h')
+                       hollerith++;
+               argc--;
+               argv++;
+       }
+
+#ifdef gcos
+       if (!intss()) {
+               _fixup();
+               ratfor = "batrat";
+       }
+       ascbcd(ratfor,bcdrat,6);
+       ascbcd(bwkmeter,bcdbwk,24);
+       acdata(bcdrat[0],1);
+       acupdt(bcdbwk[0]);
+       if (!intss()) {
+               if ((infile[infptr]=fopen("s*", "r")) == NULL)
+                       cant("s*");
+               if ((outfil=fopen("*s", "w")) == NULL)
+                       cant("*s");
+       }
+#endif
+
+       svargc = argc;
+       svargv = argv;
+       if (svargc > 1)
+               putbak('\0');
+       for (i=0; keyword[i]; i++)
+               install(keyword[i], "", keytran[i]);
+       fcnloc = install("function", "", 0);
+       yyparse();
+#ifdef gcos
+       if (!intss())
+               bexit(errorflag);
+#endif
+       exit(errorflag);
+}
+
+#ifdef gcos
+bexit(status) {
+       /* this is the batch version of exit for gcos tss */
+       FILE *inf, *outf;
+       char c;
+
+       fclose(stderr); /* make sure diagnostics get flushed */
+       if (status) /* abort */
+               _nogud();
+
+       /* good: copy output back to s*, call forty */
+
+       fclose(outfil,"r");
+       fclose(infile[0],"r");
+       inf = fopen("*s", "r");
+       outf = fopen("s*", "w");
+       while ((c=getc(inf)) != EOF)
+               putc(c, outf);
+       fclose(inf,"r");
+       fclose(outf,"r");
+       __imok();
+}
+#endif
+
+cant(s) char *s; {
+       linect[infptr] = 0;
+       curfile[infptr] = s;
+       error("can't open");
+       exit(1);
+}
+
+inclstat() {
+       int c;
+       char *ps;
+       char fname[100];
+       while ((c = getchr()) == ' ' || c == '\t');
+       if (c == '(') {
+               for (ps=fname; (*ps=getchr()) != ')'; ps++);
+               *ps = '\0';
+       } else if (c == '"' || c == '\'') {
+               for (ps=fname; (*ps=getchr()) != c; ps++);
+               *ps = '\0';
+       } else {
+               putbak(c);
+               for (ps=fname; (*ps=getchr()) != ' ' &&*ps!='\t' && *ps!='\n' && *ps!=';'; ps++);
+               *ps = '\0';
+       }
+       if ((infile[++infptr] = fopen(fname,"r")) == NULL) {
+               cant(fname);
+               exit(1);
+       }
+       linect[infptr] = 0;
+       curfile[infptr] = fname;
+}
+
+char   str[500];
+int    nstr;
+
+yylex() {
+       int c, t;
+       for (;;) {
+               while ((c=gtok(str))==' ' || c=='\n' || c=='\t')
+                       ;
+               yylval = c;
+               if (c==';' || c=='{' || c=='}')
+                       return(c);
+               if (c==EOF)
+                       return(0);
+               yylval = (int) str;
+               if (c == DIG)
+                       return(DIGITS);
+               t = lookup(str)->ydef;
+               if (t==DEFINE)
+                       defstat();
+               else if (t==INCLUDE)
+                       inclstat();
+               else if (t > 0)
+                       return(t);
+               else
+                       return(GOK);
+       }
+}
+
+int    dbg     = 0;
+
+yyerror(p) char *p; {;}
+
+
+defstat() {
+       int c,i,val,t,nlp;
+       extern int nstr;
+       extern char str[];
+       while ((c=getchr())==' ' || c=='\t');
+       if (c == '(') {
+               t = '(';
+               while ((c=getchr())==' ' || c=='\t');
+               putbak(c);
+       }
+       else {
+               t = ' ';
+               putbak(c);
+       }
+       for (nstr=0; c=getchr(); nstr++) {
+               if (type[c] != LET && type[c] != DIG)
+                       break;
+               str[nstr] = c;
+       }
+       putbak(c);
+       str[nstr] = '\0';
+       if (c != ' ' && c != '\t' && c != '\n' && c != ',') {
+               error("illegal define statement");
+               return;
+       }
+       val = nstr+1;
+       if (t == ' ') {
+               while ((c=getchr())==' ' || c=='\t');
+               putbak(c);
+               for (i=val; (c=getchr())!='\n' && c!='#' && c!='\0'; i++)
+                       str[i] = c;
+               putbak(c);
+       } else {
+               while ((c=getchr())==' ' || c=='\t' || c==',' || c=='\n');
+               putbak(c);
+               nlp  = 0;
+               for (i=val; nlp>=0 && (c=str[i]=getchr()); i++)
+                       if (c == '(')
+                               nlp++;
+                       else if (c == ')')
+                               nlp--;
+               i--;
+       }
+       for ( ; i>0; i--)
+               if (str[i-1] != ' ' && str[i-1] != '\t')
+                       break;
+       str[i] = '\0';
+       install(str, &str[val], 0);
+}
+
diff --git a/usr/src/cmd/ratfor/rlook.c b/usr/src/cmd/ratfor/rlook.c
new file mode 100644 (file)
index 0000000..0ebf64a
--- /dev/null
@@ -0,0 +1,67 @@
+#define NULL 0
+#define EOS 0
+#define        HSHSIZ  101
+struct nlist {
+       char    *name;
+       char    *def;
+       int     ydef;
+       struct  nlist *next;
+};
+
+struct nlist   *hshtab[HSHSIZ];
+struct nlist   *lookup();
+char   *install();
+char   *malloc();
+char   *copy();
+int    hshval;
+
+struct nlist *lookup(str)
+char *str;
+{
+       register char *s1, *s2;
+       register struct nlist *np;
+       static struct nlist nodef;
+
+       s1 = str;
+       for (hshval = 0; *s1; )
+               hshval += *s1++;
+       hshval %= HSHSIZ;
+       for (np = hshtab[hshval]; np!=NULL; np = np->next) {
+               s1 = str;
+               s2 = np->name;
+               while (*s1++ == *s2)
+                       if (*s2++ == EOS)
+                               return(np);
+       }
+       return(&nodef);
+}
+
+char *install(nam, val, tran)
+char *nam, *val;
+int tran;
+{
+       register struct nlist *np;
+
+       if ((np = lookup(nam))->name == NULL) {
+               np = (struct nlist *)malloc(sizeof(*np));
+               np->name = copy(nam);
+               np->def = copy(val);
+               np->ydef = tran;
+               np->next = hshtab[hshval];
+               hshtab[hshval] = np;
+               return(np->def);
+       }
+       free(np->def);
+       np->def = copy(val);
+       return(np->def);
+}
+
+char *copy(s)
+register char *s;
+{
+       register char *p, *s1;
+
+       p = s1 = (char *) malloc((unsigned)strlen(s)+1);
+       while (*s1++ = *s++);
+       return(p);
+}
diff --git a/usr/src/cmd/refer/Makefile b/usr/src/cmd/refer/Makefile
new file mode 100644 (file)
index 0000000..ad96bcc
--- /dev/null
@@ -0,0 +1,52 @@
+DESTDIR=
+CFLAGS = -O
+
+all:   mkey inv hunt refer
+
+mkey: mkey1.o mkey2.o mkey3.o deliv2.o
+       cc mkey?.o deliv2.o -o mkey
+inv: inv1.o inv2.o inv3.o inv5.o inv6.o deliv2.o
+       cc inv?.o deliv2.o -o inv
+hunt: hunt1.o hunt2.o hunt3.o hunt5.o hunt6.o hunt7.o glue5.o
+hunt: refer3.o hunt9.o shell.o deliv2.o hunt8.o glue4.o
+       cc hunt?.o refer3.o glue5.o glue4.o shell.o deliv2.o -o hunt
+deliv: deliv1.o deliv2.o
+       cc deliv?.o  -o deliv
+refpart: refer0.o refer1.o refer2.o refer3.o refer4.o refer5.o
+refpart: refer6.o refer7.o refer8.o deliv2.o glue4.o
+       cc refer?.o deliv2.o glue4.o  -o refpart
+refer0.o: refer..c
+refer1.o: refer..c
+refer2.o: refer..c
+refer3.o: refer..c
+refer4.o: refer..c
+refer6.o: refer..c
+refer: glue1.o refer1.o refer2.o refer4.o refer5.o refer6.o mkey3.o
+refer: refer7.o refer8.o hunt2.o hunt3.o deliv2.o hunt5.o hunt6.o hunt8.o
+refer: glue3.o hunt7.o hunt9.o glue2.o glue4.o glue5.o refer0.o shell.o
+       cc glue?.o refer[01245678].o hunt[2356789].o mkey3.o shell.o deliv2.o -o refer
+refer-test:
+       /usr/bin/refer test >junk1a
+       refer test >junk1b
+       if cmp -s junk1a junk1b; then echo ok; else echo bad; fi
+       /usr/bin/refer -e test >junk1a
+       refer -e test >junk1b
+       if cmp -s junk1a junk1b; then echo ok; else echo bad; fi
+       /usr/bin/refer -s test >junk1a
+       refer -s test >junk1b
+       if cmp -s junk1a junk1b; then echo ok; else echo bad; fi
+       /usr/bin/refer -s -l test >junk1a
+       refer -s -l test >junk1b
+       if cmp -s junk1a junk1b; then echo ok; else echo bad; fi
+       rm junk1a junk1b
+whatabout: what1.o what2.o what3.o what4.o shell.o mkey3.o
+       cc what?.o shell.o mkey3.o  -o whatabout
+
+install: all
+       install -s refer $(DESTDIR)/usr/bin
+       install -s inv $(DESTDIR)/usr/lib/refer
+       install -s hunt $(DESTDIR)/usr/lib/refer
+       install -s mkey $(DESTDIR)/usr/lib/refer
+clean:
+       rm -f refer inv hunt mkey *.o
+
diff --git a/usr/src/cmd/refer/deliv1.c b/usr/src/cmd/refer/deliv1.c
new file mode 100644 (file)
index 0000000..ae4a57b
--- /dev/null
@@ -0,0 +1,45 @@
+# include "stdio.h"
+main(argc,argv)
+       char *argv[];
+{
+/* goes from file:begin,l to actual characters */
+char line[750], *p, name[100];
+FILE *fa NULL;
+long lp;
+int len;
+
+if (argc>1 && argv[1] && argv[1][0])
+       chdir (argv[1]);
+name[0]="";
+while (gets(line))
+       {
+       if (line[0]=='$' && line[1]=='$') 
+               {
+               chdir(line+2);
+               continue;
+               }
+       for(p=line; *p!= ':'; p++)
+               ;
+       *p++ = 0;
+       sscanf(p, "%ld,%d", &lp, &len);
+       if (p==line)
+               fa = stdin;
+       else
+       if (strcmp (name, line) != 0)
+               {
+               if (fa != NULL)
+                       fclose(fa);
+               fa = fopen(line, "r");
+               if (fa == NULL)
+                       err("Can't open %s", line);
+               strcpy(name, line);
+               }
+       if (fa != NULL)
+               {
+               fseek (fa, lp, 0);
+               fread (line, 1, len, fa);
+               line[len] = 0;
+               fputs(line, stdout);
+               }
+       }
+}
diff --git a/usr/src/cmd/refer/deliv2.c b/usr/src/cmd/refer/deliv2.c
new file mode 100644 (file)
index 0000000..2405991
--- /dev/null
@@ -0,0 +1,47 @@
+# include "stdio.h"
+hash (s)
+       char *s;
+{
+int c, n;
+for(n=0; c= *s; s++)
+       n += (c*n+ c << (n%4));
+return(n>0 ? n : -n);
+}
+err (s, a)
+       char *s;
+{
+fprintf(stderr, "Error: ");
+fprintf(stderr, s, a);
+putc('\n', stderr);
+exit(1);
+}
+prefix(t, s)
+       char *t, *s;
+{
+int c, d;
+while ( (c= *t++) == *s++)
+       if (c==0) return(1);
+return(c==0 ? 1: 0);
+}
+char *
+mindex(s, c)
+       char *s;
+{
+register char *p;
+for( p=s; *p; p++)
+       if (*p ==c)
+               return(p);
+return(0);
+}
+zalloc(m,n)
+{
+       int t;
+# if D1
+fprintf(stderr, "calling calloc for %d*%d bytes\n",m,n);
+# endif
+t = calloc(m,n);
+# if D1
+fprintf(stderr, "calloc returned %o\n", t);
+# endif
+return(t);
+}
diff --git a/usr/src/cmd/refer/flagger.c b/usr/src/cmd/refer/flagger.c
new file mode 100644 (file)
index 0000000..435cd5a
--- /dev/null
@@ -0,0 +1,163 @@
+# include "stdio.h"
+char wds[100][40];
+int synwd[100];
+int mark[100];
+int justw 0;
+extern int comcount;
+int blank[100];
+int wdp, wdf;
+int bl;
+int sargc; char **sargv;
+FILE *inf;
+main(argc,argv)
+       char *argv[];
+{
+int i;
+while (--argc && **++argv== '-')
+       switch(argv[0][1])
+               {
+               case 'w': justw=1; break;
+               case 'c': comcount=atoi(argv[0]+2); break;
+               }
+wdp=wdf=0;
+if (argc>0)
+       {
+       argc--;
+       inf = fopen(argv[0], "r");
+       if (inf==NULL) exit(0);
+       argv++;
+       }
+else
+       inf=stdin;
+sargc=argc;  sargv= argv;
+while ( gw (wds[wdp = next(wdp)], &bl))
+       {
+       blank[wdp] = bl;
+       mark[wdp]=0;
+       synwd[wdp] = common(upcase(wds[wdp]));
+       if (common(sstrip(upcase(wds[wdp]))))
+               synwd[wdp]=1;
+       if (allpunct(wds[wdp]))
+               synwd[wdp]=1;
+       if (strlen(wds[wdp])<3)
+               synwd[wdp]=1;
+       if (synwd[wdp]==1)
+               {
+               for(i=wdp; i!=wdf; i=prev(i))
+                       {
+                       if (synwd[i]>0)
+                               continue;
+                       mark[i]=1;
+                       break;
+                       }
+               }
+       }
+if (wdp<0) return(0);
+i=wdf -1;
+i = next(i);
+while (i != wdp)
+       i= next(i);
+}
+next(i)
+{
+int j;
+j = (i+1) % 100;
+if (j==wdf)
+       {
+       if (justw==0)
+               {
+               if (mark[j] ) putchar('*');
+               printf("%s",wds[j]);
+               if (blank[j]) putchar(' ');
+               }
+       else
+               if (mark[j]) printf("%s\n", wds[j]);
+       wdf = (wdf+1)%100;
+       }
+return(j);
+}
+prev(i)
+{
+i = (i-1)%100;
+return(i);
+}
+allpunct(s)
+ char *s;
+{
+int c;
+while (c = *s++)
+       if (isalpha(c))
+               return(0);
+return(1);
+}
+gw(s, b)
+       char *s;
+       int *b;
+{
+int c, type, nt;
+c = getc(inf);
+while (c==EOF)
+       {
+       fclose(inf);
+       inf=NULL;
+       if (sargc-->0)
+               {
+               inf = fopen ( *sargv++, "r");
+               }
+       if (inf==NULL) return(0);
+       c = getc(inf);
+       }
+*s++ = c;
+type = isalpha(c) || isdigit(c);
+while ( (c = getc(inf)) != EOF )
+       {
+       nt = isalpha(c) || isdigit(c);
+       if (nt==type)
+               *s++= c;
+       else
+               break;
+       }
+*s=0;
+if (c== ' ')
+       {
+       *b = 1;
+       return(1);
+       }
+while (c==EOF)
+       {
+       fclose(inf); inf=NULL;
+       if (sargc-- > 0)
+               {
+               inf= fopen( *sargv++, "r");
+               }
+       if (inf==NULL) return(0);
+       c = getc(inf);
+       }
+ungetc(c, inf);
+*b=0;
+return(1);
+}
+trimnl(s)
+ char *s;
+{
+while (*s) s++;
+if (*--s=='\n') *s=0;
+}
+upcase(s)
+ char *s;
+{
+static char buf[100];
+strcpy (buf, s);
+for(s=buf; *s; s++)
+       if (isupper(*s))
+               *s = *s-'A'+'a';
+return(buf);
+}
+sstrip(s)
+ char *s;
+{
+char *p ; p=s;
+while (*s) s++;
+if (*--s=='s') *s=0;
+return(p);
+}
diff --git a/usr/src/cmd/refer/glue1.c b/usr/src/cmd/refer/glue1.c
new file mode 100644 (file)
index 0000000..076fbbe
--- /dev/null
@@ -0,0 +1,259 @@
+# include "stdio.h"
+# define unopen(fil) {if (fil!=NULL) {fclose(fil); fil=NULL;}}
+extern char refdir[];
+int lmaster = 1000;
+int reached = 0;
+FILE *fd = 0;
+int *hfreq, hfrflg;
+int colevel = 0;
+static union firetruck {unsigned *a; long *b;} master;
+int iflong;
+extern char *fgnames[], **fgnamp;
+extern FILE *iopen();
+char *todir();
+int prfreqs = 0;
+int typeindex = 0;
+char usedir[100];
+static int full = 1000;
+static int tags = 0;
+char *sinput, *soutput, *tagout;
+long indexdate = 0, gdate();
+int soutlen = 1000;
+int taglen = 1000;
+
+huntmain(argc,argv)
+       char *argv[];
+{
+/* read query from stdin, expect name of indexes in argv[1] */
+static FILE *fa, *fb, *fc;
+char indexname[100], *qitem[100], *rprog = 0;
+char grepquery[200];
+static char oldname[30] ;
+static int nhash = 0;
+static int maxhash = 0;
+int falseflg = 0, nitem, nfound, frtbl;
+static long *hpt = 0;
+# if D1
+fprintf(stderr, "in glue1 argc %d argv %o %o\n", argc, argv[0],argv[1]);
+# endif
+savedir();
+while (argv[1][0] == '-')
+       {
+# if D1
+fprintf(stderr, "argv.1 is %s\n",argv[1]);
+# endif
+       switch(argv[1][1])
+               {
+               case 'a': /* all output, incl. false drops */
+                       falseflg = 1; break;
+               case 'r':
+                       argc--; argv++;
+                       rprog = argv[1];
+                       break;
+               case 'F': /* put out full text */
+                       full = setfrom(argv[1][2]);
+                       break;
+               case 'T': /* put out tags */
+                       tags = setfrom(argv[1][2]);
+                       break;
+               case 'i': /* input in argument string */
+                       argc--; argv++;
+                       sinput = argv[1];
+                       break;
+               case 's': /*text output to string */
+               case 'o':
+                       argc--; argv++;
+                       soutput = argv[1];
+                       if (argv[2]<16000)
+                               {
+                               soutlen = argv[2];
+                               argc--; argv++;
+                               }
+                       break;
+               case 't': /*tag output to string */
+                       argc--; argv++;
+                       tagout = argv[1];
+                       if (argv[2]<16000)
+                               {
+                               taglen = argv[2];
+                               argc--; argv++;
+                               }
+                       break;
+               case 'l': /* specify length of lists */
+                       argc--; argv++;
+                       lmaster = atoi(argv[1]);
+# if D1
+                       fprintf(stderr, "lmaster now %d\n",lmaster);
+# endif
+                       break;
+               case 'C': 
+                       argc--; argv++;
+                       colevel = atoi(argv[1]);
+                       break;
+               }
+       argc--; argv++;
+       }
+strcpy (indexname, todir(argv[1]));
+# if D1
+fprintf(stderr, "in huntmain indexname %s typeindex %d\n", indexname, typeindex);
+# endif
+if (typeindex == 0 || strcmp (oldname, indexname) !=0)
+       {
+       strcpy (oldname, indexname);
+       unopen(fa); unopen(fb); unopen(fc);
+
+       if (ckexist(indexname, ".ib"))
+               {
+# if D1
+               fprintf(stderr, "found old index\n");
+# endif
+               fa = iopen(indexname, ".ia");
+               fb = iopen(indexname, ".ib");
+               fc = iopen(indexname, ".ic");
+               typeindex =1;
+# if D1
+               fprintf(stderr, "opened f's as %o %o %o\n",fa,fb,fc);
+# endif
+               indexdate = gdate(fb);
+               fread (&nhash, sizeof(nhash), 1, fa);
+               fread (&iflong, sizeof(iflong), 1, fa);
+               if (nhash > maxhash)
+                       {
+                       if (hpt)
+                               free (hpt, maxhash, sizeof(*hpt));
+                       hpt=0;
+                       if (hfreq)
+                               free(hfreq, maxhash, sizeof(*hfreq));
+                       hfreq=0;
+                       maxhash=nhash;
+# if D1
+                       fprintf(stderr, "Freed if needed maxhash %d\n",maxhash);
+# endif
+                       }
+               if (hpt==0)
+               hpt = zalloc(nhash, sizeof(*hpt));
+# if D1
+               fprintf(stderr, "hpt now %o\n",hpt);
+# endif
+               if (hpt == NULL)
+                       err ("No space for hash list (%d)", nhash);
+               fread( hpt, sizeof(*hpt), nhash, fa);
+               if (hfreq==0)
+               hfreq=zalloc(nhash, sizeof(*hfreq));
+               if (hfreq==NULL)
+                       err ("No space for hash frequencies (%d)", nhash);
+               frtbl = fread(hfreq, sizeof(*hfreq), nhash, fa);
+               hfrflg = (frtbl == nhash);
+# if D1
+               fprintf(stderr,"Read pointer files\n");
+# endif
+               if (master.a == NULL)
+                       if (iflong)
+                               master.b = zalloc(lmaster, sizeof(long));
+                       else
+                               master.a = zalloc(lmaster, sizeof(int));
+               if (master.a == NULL)
+                       err ("no space for answer list",0);
+               }
+       else
+       if (makefgrep(indexname))
+               typeindex=2;
+       else
+               {
+               err ("No files %s\n",indexname);
+               exit(1);
+               }
+       }
+
+# if D1
+fprintf(stderr, "typeindex now %d\n",typeindex);
+# endif
+tagout[0]=0;
+if (typeindex==2)
+       {
+       grepcall(sinput, tagout, indexname);
+# if D1
+       fprintf(stderr, " back from grepcall\n");
+# endif
+       restodir();
+       return;
+       }
+nitem = getq(qitem);
+# if D1
+fprintf(stderr, "approaching doquery fb %o\n", fb);
+# endif
+nfound = doquery(hpt, nhash, fb, nitem, qitem, master);
+# ifdef D1
+       fprintf(stderr, "return from doquery with nfound %d\n", nfound);
+# endif
+if (falseflg == 0)
+       nfound = baddrop(master, nfound, fc, nitem, qitem, rprog, full);
+# ifdef D1
+       fprintf(stderr, "after baddrop with nfound %d\n",nfound);
+       fprintf(stderr, "tagout is /%s/, sout /%s/\n",tagout, soutput);
+# endif
+if (tags)
+       result (master, nfound >tags ? tags : nfound, fc);
+# if D1
+fprintf(stderr, "done with huntmain\n");
+fprintf(stderr, "tagout is /%s/\n", tagout);
+fprintf(stderr, "string out is /%s/\n", soutput);
+# endif
+if (fgnamp>fgnames)
+       {
+       char **fgp;
+       int k;
+# if D1
+       fprintf(stderr, "were %d bad files\n", fgnamp-fgnames);
+# endif
+       grepquery[0]=0;
+       for(k=0; k<nitem; k++)
+               {
+               strcat(grepquery, " ");
+               strcat(grepquery, qitem[k]);
+               }
+       for(fgp=fgnames; fgp<fgnamp; fgp++)
+               {
+# if D1
+               fprintf(stderr, "Now on %s query /%s/\n", *fgp, grepquery);
+# endif
+               makefgrep(*fgp);
+               grepcall(grepquery, tagout, *fgp);
+# if D1
+               fprintf(stderr, "tagout now /%s/\n", tagout);
+# endif
+               }
+       }
+restodir();
+}
+
+char *
+todir(t)
+       char *t;
+{
+       char *s;
+       s=t;
+       while (*s) s++;
+       while (s>=t && *s != '/') s--;
+       if (s<t) return(t);
+*s++ = 0;
+t = (*t ? t : "/");
+chdir (t);
+strcpy (usedir,t);
+return(s);
+}
+setfrom(c)
+{
+switch(c)
+       {
+       case 'y': case '\0':
+       default:
+               return(1000);
+       case '1':
+       case '2': case '3': case '4': case '5':
+       case '6': case '7': case '8': case '9':
+               return(c-'0');
+       case 'n': case '0':
+               return(0);
+       }
+}
diff --git a/usr/src/cmd/refer/glue2.c b/usr/src/cmd/refer/glue2.c
new file mode 100644 (file)
index 0000000..0225278
--- /dev/null
@@ -0,0 +1,11 @@
+ char refdir[50];
+savedir()
+{
+if (refdir[0]==0)
+       corout ("", refdir, "/bin/pwd", "", 50);
+trimnl(refdir);
+}
+restodir()
+{
+chdir(refdir);
+}
diff --git a/usr/src/cmd/refer/glue3.c b/usr/src/cmd/refer/glue3.c
new file mode 100644 (file)
index 0000000..8f6c171
--- /dev/null
@@ -0,0 +1,69 @@
+# include "refer..c"
+corout(in, out, rprog, arg, outlen)
+       char *in, *out, *rprog;
+{
+# define move(x, y) close(y); dup(x); close(x);
+int pipev[2], fr1, fr2, fw1, fw2, n;
+
+if (strcmp (rprog, "hunt") ==0)
+       return(callhunt(in, out, arg, outlen));
+if (strcmp (rprog, "deliv")==0)
+       return(dodeliv(in, out, arg, outlen));
+pipe (pipev); fr1= pipev[0]; fw1 = pipev[1];
+pipe (pipev); fr2= pipev[0]; fw2 = pipev[1];
+if (fork()==0)
+       {
+       close (fw1); close (fr2);
+       move (fr1, 0);
+       move (fw2, 1);
+       if (rprog[0]!= '/')
+               chdir("/usr/lib/refer");
+       execl(rprog, "deliv", arg, 0);
+       err ("Can't run %s", rprog);
+       }
+close(fw2); close(fr1);
+write (fw1, in , strlen(in));
+close(fw1);
+wait(0);
+n = read (fr2, out, outlen);
+out[n]=0;
+close(fr2);
+}
+callhunt(in, out, arg, outlen)
+       char *in, *out, *arg;
+{
+# define ALEN 50
+char *argv[20], abuff[ALEN];
+extern int typeindex;
+int argc;
+extern char one[];
+extern int onelen;
+argv[0] = "hunt";
+argv[1] = "-i";
+argv[2] = in;
+argv[3] = "-t";
+argv[4] = out;
+argv[5] = outlen;
+argv[6] = "-T";
+argv[7] = "-F1";
+argv[8] = "-o";
+argv[9] = one;
+argv[10] = onelen;
+argv[11] = abuff; strcpy (abuff,arg);
+if (strlen(abuff) > ALEN)
+       err("abuff not big enough %d", strlen(abuff));
+argc = 6;
+huntmain (argc,argv);
+return(0);
+}
+dodeliv(in, out, arg, outlen)
+       char *in, *out, *arg;
+{
+# if D1
+fprintf(stderr, "in dodeliv, arg /%s/\n", arg?arg:"");
+# endif
+if (arg && arg[0])
+       chdir(arg);
+findline(in, out, outlen, 0L);
+restodir();
+}
diff --git a/usr/src/cmd/refer/glue4.c b/usr/src/cmd/refer/glue4.c
new file mode 100644 (file)
index 0000000..53cfaac
--- /dev/null
@@ -0,0 +1,96 @@
+# include "stdio.h"
+# include "ctype.h"
+
+grepcall (in, out, arg)
+       char *in, *out, *arg;
+{
+char line[200], *s, argig[100], *cv[50];
+char *inp, inb[500];
+extern char gfile[];
+FILE *qf, *gf;
+int c, oldc = 0, alph = 0, nv = 0;
+int sv0, sv1;
+strcpy (argig, arg); strcat(argig, ".ig");
+strcpy (inp=inb, in);
+if (gfile[0]==0)
+       sprintf(gfile, "/tmp/rj%dg", getpid());
+# if D1
+fprintf(stderr, "in grepcall, gfile %s in %o out %o\n", gfile,in,out);
+# endif
+for(cv[nv++] = "fgrep"; c = *inp; inp++)
+       {
+       if (c== ' ')
+               c = *inp = 0;
+       else if (isupper(c))
+               *inp = tolower(c);
+       alph = (c==0) ? 0 : alph+1;
+       if (alph == 1)
+               cv[nv++] = inp;
+       if (alph > 6)
+               *inp = 0;
+       oldc=c;
+       }
+# if D1
+fprintf(stderr, "%d args set up\n", nv);
+# endif
+       {
+       sv0 = dup(0);
+       close(0);
+       if (open (argig, 0) != 0)
+               err("Can't read fgrep index %s", argig);
+       sv1 = dup(1);
+       close(1);
+       if (creat(gfile, 0666) != 1)
+               err("Can't write fgrep output %s", gfile);
+       fgrep(nv, cv);
+# if D1
+fprintf(stderr, "fgrep returned, output is..\n");
+# endif
+       close (0); dup(sv0); close(sv0);
+       close (1); dup(sv1); close(sv1);
+       }
+
+# if D1
+fprintf(stderr, "back from fgrep\n");
+# endif
+gf = fopen(gfile, "r");
+if (gf==NULL)
+       err("can't read fgrep output %s", gfile);
+while (fgets(line, 100, gf) == line)
+       {
+       line[100]=0;
+# if D1
+fprintf(stderr, "read line as //%s//\n",line);
+# endif
+       for(s=line; *s && (*s != '\t'); s++);
+       if (*s == '\t')
+               {
+               *s++ = '\n';
+               *s++ = 0;
+               }
+       if (line[0])
+               strcat(out, line);
+# if D1
+fprintf(stderr, "out now /%s/\n",out);
+# endif
+       while (*s) s++;
+# if D1
+fprintf(stderr, "line %o s %o s-1 %o\n",line,s,s[-1]);
+# endif
+       if (s[-1]!= '\n')
+               while (!feof(gf) && getc(gf)!= '\n') ;
+       }
+fclose(gf);
+# if D1
+       fprintf(stderr, "back from reading %, out %s\n",out);
+# else
+unlink (gfile);
+# endif
+return(0);
+}
+
+clfgrep()
+{
+if (gfile[0])
+       unlink(gfile);
+}
diff --git a/usr/src/cmd/refer/hunt1.c b/usr/src/cmd/refer/hunt1.c
new file mode 100644 (file)
index 0000000..6c6ddc9
--- /dev/null
@@ -0,0 +1,227 @@
+# include "stdio.h"
+# include "assert.h"
+extern char refdir[];
+extern int keepold;
+extern char *fgnames[];
+extern char **fgnamp;
+FILE *fd = 0;
+int lmaster = 500;
+int *hfreq, hfrflg;
+int colevel = 0;
+int soutlen = 1000;
+int reached = 0;
+int iflong = 0;
+int prfreqs = 0;
+char usedir[100];
+char gfile[50];
+static int full = 1000;
+static int tags = 0;
+char *sinput, *soutput, *tagout;
+long indexdate = 0, gdate();
+extern char *todir();
+
+main(argc,argv)
+       char *argv[];
+{
+/* read query from stdin, expect name of indexes in argv[1] */
+static FILE *fa, *fb, *fc;
+char nma[100], nmb[100], nmc[100], *qitem[100], *rprog = 0;
+char nmd[100], grepquery[256];
+static char oldname[30] ;
+static int was = 0;
+/* these pointers are unions of pointer to int and pointer to long */
+long *hpt;
+unsigned *master = 0;
+int falseflg, nhash, nitem, nfound, frtbl, kk;
+
+       /* special wart for refpart: default is tags only */
+
+while (argv[1][0] == '-')
+       {
+       switch(argv[1][1])
+               {
+               case 'a': /* all output, incl. false drops */
+                       falseflg = 1; break;
+               case 'r':
+                       argc--; argv++;
+                       rprog = argv[1];
+                       break;
+               case 'F': /* put out full text */
+                       full = setfrom(argv[1][2]);
+                       break;
+               case 'T': /* put out tags */
+                       tags = setfrom(argv[1][2]);
+                       break;
+               case 'i': /* input in argument string */
+                       argc--; argv++;
+                       sinput = argv[1];
+                       break;
+               case 's': /*text output to string */
+               case 'o':
+                       argc--; argv++;
+                       soutput = argv[1];
+                       if (argv[2]<16000)
+                               {
+                               soutlen = argv[2];
+                               argc--; argv++;
+                               }
+                       break;
+               case 't': /*tag output to string */
+                       argc--; argv++;
+                       tagout = argv[1];
+                       break;
+               case 'l': /* length of internal lists */
+                       argc--; argv++;
+                       lmaster = atoi(argv[1]);
+                       break;
+               case 'g': /* suppress fgrep search on old files */
+                       keepold = 0;
+                       break;
+               case 'C': /* coordination level */
+                       colevel = atoi(argv[1]+2);
+# if D1
+fprintf(stderr, "colevel set to %d\n",colevel);
+# endif
+                       break;
+               case 'P': /* print term freqs */
+                       prfreqs=1; break;
+               }
+       argc--; argv++;
+       }
+strcpy (nma, todir(argv[1]));
+if (was == 0 || strcmp (oldname, nma) !=0)
+       {
+       strcpy (oldname,nma);
+       strcpy (nmb, nma); strcpy (nmc, nmb); strcpy(nmd,nma);
+       strcat (nma, ".ia");
+       strcat (nmb, ".ib");
+       strcat (nmc, ".ic");
+       strcat (nmd, ".id");
+       if (was)
+               {fclose(fa); fclose(fb); fclose(fc);}
+
+       fa = fopen(nma, "r");
+       if (fa==NULL)
+               {
+               err("No files %s",nma);
+               exit(1);
+               }
+       fb = fopen(nmb, "r");
+       fc = fopen(nmc, "r");
+       was =1;
+       if (fb== NULL || fc ==NULL)
+               {
+               err("Index incomplete %s", nmb);
+               exit(1);
+               }
+       indexdate = gdate(fb);
+       fd = fopen(nmd, "r");
+       }
+fseek (fa, 0L, 0);
+fread (&nhash, sizeof(nhash), 1, fa);
+fread (&iflong, sizeof(iflong), 1, fa);
+if(master==0)
+master = calloc (lmaster, iflong? sizeof(long): sizeof(int));
+hpt = calloc(nhash, sizeof(*hpt));
+kk=fread( hpt, sizeof(*hpt), nhash, fa);
+# if D1
+fprintf(stderr,"read %d hashes, iflong %d, nhash %d\n", kk, iflong, nhash);
+# endif
+_assert (kk==nhash);
+hfreq = calloc(nhash, sizeof(*hfreq));
+_assert (hfreq != NULL);
+frtbl = fread(hfreq, sizeof(*hfreq), nhash, fa);
+hfrflg = (frtbl == nhash);
+# if D1
+fprintf(stderr, "read freqs %d\n", frtbl);
+# endif
+
+while (1)
+       {
+       nitem = getq(qitem);
+       if (nitem==0) continue;
+       if (nitem < 0) break;
+       nfound = doquery(hpt, nhash, fb, nitem, qitem, master);
+# if D1
+       fprintf(stderr,"after doquery nfound %d\n", nfound);
+# endif
+       fgnamp=fgnames;
+       if (falseflg == 0)
+               nfound = baddrop(master, nfound, fc, nitem, qitem, rprog, full);
+# if D1
+       fprintf(stderr,"after baddrop nfound %d\n", nfound);
+# endif
+       if (fgnamp>fgnames)
+               {
+               char **fgp, tgbuff[100];
+               int k;
+# if D1
+               fprintf(stderr, "were %d bad files\n", fgnamp-fgnames);
+# endif
+               grepquery[0]=0;
+               for(k=0; k<nitem; k++)
+                       {
+                       strcat(grepquery, " ");
+                       strcat(grepquery, qitem[k]);
+                       }
+# if D1
+               fprintf(stderr, "grepquery %s\n",grepquery);
+# endif
+               for(fgp=fgnames; fgp<fgnamp; fgp++)
+                       {
+# if D1
+                       fprintf(stderr, "Now on %s query /%s/\n", *fgp, grepquery);
+# endif
+                       makefgrep(*fgp);
+# if D1
+                       fprintf(stderr, "grepmade\n");
+# endif
+                       if (tagout==0)
+                               tagout=tgbuff;
+                       grepcall(grepquery, tagout, *fgp);
+# if D1
+                       fprintf(stderr, "tagout now /%s/\n", tagout);
+# endif
+                       if (full)
+                               {
+                               char bout[1000];
+                               findline(tagout, bout, 1000);
+                               fputs(bout,stdout);
+                               }
+                       }
+               }
+       if (tags)
+               result (master, nfound >tags ? tags: nfound, fc);
+       }
+}
+
+char *
+todir(t)
+       char *t;
+{
+       char *s;
+       s=t;
+       while (*s) s++;
+       while (s>=t && *s != '/') s--;
+       if (s<t) return(t);
+*s++ = 0;
+t = (*t ? t : "/");
+chdir (t);
+strcpy (usedir,t);
+return(s);
+}
+setfrom(c)
+{
+switch(c)
+       {
+       case 'y': case '\0':
+       default:
+               return(1000);
+       case '1':
+       case '2': case '3': case '4': case '5':
+       case '6': case '7': case '8': case '9':
+               return(c-'0');
+       case 'n': case '0':
+               return(0);
+       }
+}
diff --git a/usr/src/cmd/refer/hunt2.c b/usr/src/cmd/refer/hunt2.c
new file mode 100644 (file)
index 0000000..eece98b
--- /dev/null
@@ -0,0 +1,267 @@
+# include "refer..c"
+static int *coord = 0;
+int hh[50]; extern int *hfreq, hfrflg, hcomp(), hexch();
+extern int prfreqs;
+
+doquery(hpt, nhash, fb, nitem, qitem, master)
+       union ptr {unsigned *a; long *b;} master;
+       long *hpt;
+       FILE *fb;
+       char *qitem[];
+{
+long k;
+union ptr prevdrop;
+int nf = 0, best = 0, nterm = 0, i, g, j;
+int *prevcoord;
+long lp;
+extern int lmaster, colevel, reached;
+long getl(); unsigned getw(); extern int iflong;
+
+# if D1
+fprintf(stderr, "entering doquery nitem %d\n",nitem);
+fprintf(stderr, "first few hashes are %ld %ld %ld %ld %ld\n", hpt[0],hpt[1],hpt[2],hpt[3],hpt[4]);
+fprintf(stderr, "and frequencies are  %d %d %d %d %d\n",hfreq[0],hfreq[1],hfreq[2],hfreq[3],hfreq[4]);
+# endif
+_assert (lmaster>0);
+if (coord==0)
+       coord = zalloc(lmaster, sizeof(lmaster));
+if (colevel>0)
+       {
+       prevdrop.a=zalloc(lmaster,iflong?sizeof(long): sizeof(int));
+       prevcoord = zalloc(lmaster, sizeof(lmaster));
+       }
+else
+       {
+       prevdrop.a=master.a;
+       prevcoord=coord;
+       }
+# if D1
+fprintf(stderr, "nitem %d\n",nitem);
+# endif
+for(i=0; i<nitem; i++)
+       {
+       hh[i] = hash(qitem[i])%nhash;
+# if D1
+       fprintf(stderr,"query wd X%sX has hash %d\n", qitem[i], hh[i]);
+# endif
+       }
+# if D1
+fprintf(stderr, "past that loop nhash %d hpt is %lo\n", nhash, hpt);
+# endif
+if (prfreqs)
+       for(i=0; i<nitem; i++)
+               fprintf(stderr,"item %s hash %d hfreq %d\n",qitem[i], hh[i], hfreq[hh[i]]);
+/* if possible, sort query into decreasing frequency of hashes */
+if (hfrflg)
+       shell (nitem, hcomp, hexch);
+# if D1
+for(i=0; i<nitem; i++)
+ fprintf(stderr, "item hash %d frq %d\n", hh[i], hfreq[hh[i]]);
+# endif
+       lp = hpt [hh[0]];
+# if D1
+fprintf(stderr,"first item hash %d lp %ld 0%lo\n", hh[0],lp,lp);
+# endif
+_assert (fb!=NULL);
+_assert (fseek(fb,lp,0)==NULL);
+for(i=0; i<lmaster; i++)
+       {
+       if (iflong)
+               master.b[i] = getl(fb);
+       else
+               master.a[i] = getw(fb);
+       coord[i]=1;
+# if D2
+       if (iflong)
+       fprintf(stderr,"master has %ld\n",(master.b[i]));
+       else
+       fprintf(stderr,"master has %d\n",(master.a[i]));
+# endif
+       _assert (i<lmaster);
+       if (iflong)
+               {
+               if (master.b[i] == -1L) break;
+               }
+       else
+               {
+               if (master.a[i] == -1) break;
+               }
+       }
+nf= i;
+for(nterm=1; nterm<nitem; nterm++)
+       {
+# ifdef D1
+       fprintf(stderr, "item %d, hash %d\n", nterm, hh[nterm]);
+# endif
+       if (colevel>0)
+               {
+               for(j=0; j<nf; j++)
+                       {
+                       if (iflong)
+                       prevdrop.b[j] = master.b[j];
+                       else
+                       prevdrop.a[j] = master.a[j];
+                       prevcoord[j] = coord[j];
+                       }
+               }
+       lp = hpt[hh[nterm]];
+       _assert (fseek(fb, lp, 0)==0);
+# if D1
+       fprintf(stderr,"item %d hash %d seek to %ld\n",nterm,hh[nterm],lp);
+# endif
+       g=j=0;
+       while (1)
+               {
+               if (iflong)
+                       k = getl(fb);
+               else
+                       k = getw(fb);
+               if (k== -1) break;
+# if D2
+               fprintf(stderr,"next term finds %ld\n",k);
+# endif
+# if D3
+               if (iflong)
+               fprintf(stderr, "bfwh j %d nf %d master %ld k %ld\n",j,nf,prevdrop.b[j],(long)(k));
+               else
+               fprintf(stderr, "bfwh j %d nf %d master %ld k %ld\n",j,nf,prevdrop.a[j],(long)(k));
+# endif
+               while (j<nf && (iflong?prevdrop.b[j]:prevdrop.a[j])<k)
+                       {
+# if D3
+                       if (iflong)
+                       fprintf(stderr, "j %d nf %d prevdrop %ld prevcoord %d colevel %d nterm %d k %ld\n",
+                       j,nf,prevdrop.b[j], prevcoord[j], colevel, nterm, (long)(k));
+                       else
+                       fprintf(stderr, "j %d nf %d prevdrop %ld prevcoord %d colevel %d nterm %d k %ld\n",
+                       j,nf,prevdrop.a[j], prevcoord[j], colevel, nterm, (long)(k));
+# endif
+                       if (prevcoord[j] + colevel <= nterm)
+                               j++;
+                       else
+                               {
+                               _assert (g<lmaster);
+                               if (iflong)
+                               master.b[g] = prevdrop.b[j];
+                               else
+                               master.a[g] = prevdrop.a[j];
+                               coord[g++] = prevcoord[j++];
+# if D1
+if (iflong)
+fprintf(stderr, " not skip g %d doc %d coord %d note %d\n",g,master.b[g-1], coord[g-1],master.b[j-1]);
+else
+fprintf(stderr, " not skip g %d doc %ld coord %d nterm %d\n",g,master.a[g-1], coord[g-1],nterm);
+# endif
+                               continue;
+                               }
+                       }
+               if (colevel==0 && j>=nf) break;
+               if (j<nf && (iflong? prevdrop.b[j]: prevdrop.a[j]) == k)
+                       {
+                       if (iflong)
+                       master.b[g]=k;
+                       else
+                       master.a[g]=k;
+                       coord[g++] = prevcoord[j++]+1;
+# if D1
+if (iflong)
+                       fprintf(stderr, " at g %d item %ld coord %d note %ld\n",g,master.b[g-1],coord[g-1],master.b[j-1]);
+else
+                       fprintf(stderr, " at g %d item %d coord %d note %d\n",g,master.a[g-1],coord[g-1],master.a[j-1]);
+# endif
+                       }
+               else
+               if (colevel >= nterm)
+                       {
+                       if (iflong)
+                       master.b[g]=k;
+                       else
+                       master.a[g]=k;
+                       coord[g++] = 1;
+                       }
+               }
+# if D1
+fprintf(stderr,"now have %d items\n",g);
+# endif
+       if (colevel>0)
+       for ( ; j<nf; j++)
+               if ((iflong?prevcoord.b[j]:prevcoord.a[j])+colevel > nterm)
+                       {
+                       _assert(g<lmaster);
+                       if (iflong)
+                       master.b[g] = prevdrop.b[j];
+                       else
+                       master.a[g] = prevdrop.a[j];
+                       coord[g++] = prevcoord[j];
+# if D3
+if(iflong)
+fprintf(stderr, "copied over %ld coord %d\n",master.b[g-1], coord[g-1]);
+else
+fprintf(stderr, "copied over %d coord %d\n",master.a[g-1], coord[g-1]);
+# endif
+                       }
+       nf = g;
+       }
+if (colevel>0)
+       {
+       best=0;
+       for(j=0; j<nf; j++)
+               if (coord[j]>best) best = coord[j];
+# if D1
+       fprintf(stderr, "colevel %d best %d\n", colevel, best);
+# endif
+       reached = best;
+       for(g=j=0; j<nf; j++)
+               if (coord[j]==best)
+                       {
+                       if (iflong)
+                       master.b[g++] = master.b[j];
+                       else
+                       master.a[g++] = master.a[j];
+                       }
+       nf=g;
+# if D1
+       fprintf(stderr, "yet got %d\n",nf);
+# endif
+       }
+# ifdef D1
+       fprintf(stderr, " returning with %d\n",nf);
+# endif
+if (colevel)
+       {
+       free(prevdrop, lmaster, iflong?sizeof(long): sizeof(int));
+       free(prevcoord, lmaster, sizeof (lmaster));
+       }
+# if D3
+for(g=0;g<nf;g++)
+if(iflong)
+fprintf(stderr,":%ld\n",master.b[g]);
+else
+fprintf(stderr,":%d\n",master.a[g]);
+# endif
+return(nf);
+}
+long
+getl(fb)
+       FILE *fb;
+{
+return(getw(fb));
+}
+
+putl(ll, f)
+       long ll;
+       FILE *f;
+{
+putw(ll, f);
+}
+hcomp( n1, n2)
+{
+return (hfreq[hh[n1]]<=hfreq[hh[n2]]);
+}
+hexch( n1, n2 )
+{
+int t;
+t = hh[n1];
+hh[n1] = hh[n2];
+hh[n2] = t;
+}
diff --git a/usr/src/cmd/refer/hunt3.c b/usr/src/cmd/refer/hunt3.c
new file mode 100644 (file)
index 0000000..e89f4fb
--- /dev/null
@@ -0,0 +1,43 @@
+# include "refer..c"
+getq(v)
+       char *v[];
+{
+# define BSIZ 250
+static char buff[BSIZ];
+static int eof = 0;
+extern char *sinput;
+char *p;
+int c, n = 0, las = 0;
+if (eof) return(-1);
+p = buff;
+while ( (c = (sinput ? *sinput++ : getchar()) ) > 0)
+       {
+       if (c== '\n')
+               break;
+       if (isalpha(c) || isdigit(c))
+               {
+               if (las==0)
+                       {
+                       v[n++] = p;
+                       las=1;
+                       }
+               if (las++ <= 6)
+                       *p++ = c;
+               }
+       else
+               {
+               if (las>0)
+                       *p++ = 0;
+               las=0;
+               }
+       }
+*p=0;
+assert(p<buff+BSIZ);
+if (sinput==0 && c<= 0) eof=1;
+# if D1
+fprintf(stderr, "no. keys %d\n",n);
+for(c=0; c<n; c++)
+ fprintf(stderr, "keys X%sX\n", v[c]);
+# endif
+return(n);
+}
diff --git a/usr/src/cmd/refer/hunt5.c b/usr/src/cmd/refer/hunt5.c
new file mode 100644 (file)
index 0000000..19557a5
--- /dev/null
@@ -0,0 +1,50 @@
+# include "stdio.h"
+extern char *soutput, *tagout, usedir[];
+
+result(master, nf, fc)
+       union ptr {unsigned *a; long *b;} *master;
+       FILE *fc;
+{
+int i, c;
+char *s;
+long lp;
+extern int iflong;
+char res[100];
+
+for(i=0; i<nf; i++)
+       {
+       lp = iflong ? master.b[i] : master.a[i];
+       fseek(fc,lp, 0);
+       fgets(res, 100, fc);
+       for(s=res; c = *s; s++)
+               if (c== ';')
+                       {
+                       *s=0;
+                       break;
+                       }
+       if (tagout !=0)
+               {
+               if (res[0]=='/' || usedir[0]==0)
+                       sprintf(tagout, "%s", res);
+               else
+               sprintf(tagout, "%s/%s", usedir, res);
+               while (*tagout) tagout++;
+               }
+       else
+               {
+               if (res[0]!='/' || usedir[0]==0)
+                       printf("%s/", usedir);
+               printf("%s\n", res);
+               }
+       }
+}
+
+# include "sys/types.h"
+# include "sys/stat.h"
+long gdate(f)
+       FILE *f;
+{
+struct stat sb;
+fstat (f->_file, &sb);
+return  (sb . st_mtime);
+}
diff --git a/usr/src/cmd/refer/hunt6.c b/usr/src/cmd/refer/hunt6.c
new file mode 100644 (file)
index 0000000..589f6c3
--- /dev/null
@@ -0,0 +1,110 @@
+# include "stdio.h"
+# include "assert.h"
+# define TXTLEN 1000
+char *outbuf = 0;
+extern char *soutput;
+extern int soutlen, iflong;
+extern long indexdate;
+baddrop(master, nf, fc, nitem, qitem, rprog, full)
+       union ptr {unsigned *a; long *b; } master;
+       FILE *fc;
+       char *qitem[], *rprog;
+{
+/* checks list of drops for real bad drops;
+   uses "deliv" to find items. */
+int i, g, j, need, got, na, len;
+long lp;
+char res[100], *ar[50], output[TXTLEN];
+extern int colevel, reached;
+# if D1
+if (iflong)
+fprintf(stderr,"in baddrop, nf %d master %ld %ld %ld\n", nf, master.b[0], master.b[1], master.b[2]);
+else
+fprintf(stderr,"in baddrop, nf %d master %d %d %d\n", nf, master.a[0], master.a[1], master.a[2]);
+# endif
+for (i=g=0; i<nf; i++)
+       {
+       lp = iflong ? master.b[i] : master.a[i];
+# if D1
+       if (iflong)
+       fprintf(stderr, "i %d master %lo lp %lo\n", i, master.b[i], lp);
+       else
+       fprintf(stderr, "i %d master %o lp %lo\n", i, master.a[i], lp);
+# endif
+       fseek (fc, lp, 0);
+       fgets( res, 100, fc);
+# if D1
+       fprintf(stderr, "tag %s", res);
+# endif
+       if (!auxil(res,output))
+               {
+               char *s; int c;
+# if D1
+               fprintf(stderr, "not auxil try rprog %c\n", rprog? 'y': 'n');
+# endif
+               for(s=res; c= *s; s++)
+                       if (c == ';' || c == '\n')
+                               {*s=0; break;}
+               len = rprog ?
+                       corout (res, output, rprog, 0, TXTLEN) :
+                       findline (res, output, TXTLEN, indexdate);
+               }
+# if D1
+       _assert (len <TXTLEN);
+       fprintf(stderr,"item %d of %d, tag %s len %d output\n%s\n..\n",i,nf,res, len,output);
+# endif
+       if (len==0)
+               continue;
+       need = colevel ? reached : nitem;
+       na=0;
+       ar[na++] = "fgrep";
+       ar[na++] = "-r";
+       ar[na++] = "-n";
+       ar[na++] = need;
+       ar[na++] = "-i";
+       ar[na++] = output;
+       ar[na++] = len;
+       for(j=0; j<nitem; j++)
+               ar[na++] = qitem[j];
+# ifdef D1
+       fprintf(stderr, "calling fgrep len %d ar[4] %s %o %d \n",len,ar[4],ar[5],ar[6]);
+# endif
+       if (fgrep(na, ar)==0)
+               {
+# ifdef D1
+       fprintf(stderr, "fgrep found it\n");
+# endif
+               if (iflong)
+                       master.b[g++] = master.b[i];
+               else
+                       master.a[g++] = master.a[i];
+               if (full >= g)
+                       if (soutput==0)
+                               fputs(output, stdout);
+                       else
+                               strcpy (soutput, output);
+               }
+# ifdef D1
+       fprintf(stderr, "after fgrep\n");
+# endif
+       }
+return(g);
+}
+auxil( res, output)
+       char *res, *output;
+{
+extern FILE *fd;
+long lp, c; int len;
+if (fd==0)return(0);
+while (c = *res++) 
+       {
+       if (c == ';')
+               {
+               sscanf(res, "%ld,%d", &lp, &len);
+               fseek (fd, lp, 0);
+               fgets(output, len, fd);
+               return(1);
+               }
+       }
+return(0);
+}
diff --git a/usr/src/cmd/refer/hunt7.c b/usr/src/cmd/refer/hunt7.c
new file mode 100644 (file)
index 0000000..6a74308
--- /dev/null
@@ -0,0 +1,104 @@
+# include "stdio.h"
+# define SAME 0
+# include "assert.h"
+# define FGCT 10
+# define FGSIZE 150
+int keepold = 1; /* keep old things for fgrep search */
+char fgspace[FGSIZE];
+char *fgp = fgspace;
+char *fgnames[FGCT];
+char **fgnamp = fgnames;
+findline(in, out, outlen, indexdate)
+       long indexdate;
+       char *in, *out;
+{
+static char name[100] = "";
+char *p, **ftp;
+extern long gdate();
+static FILE *fa = NULL;
+long lp, llen;
+int len, k, nofil;
+
+# if D1
+       fprintf(stderr, "findline: %s\n", in);
+# endif
+       if (mindex(in, '!'))
+               return(remote(in, out));
+       nofil = in[0]==0;
+       for(p=in; *p && *p != ':' && *p != ';'; p++)
+               ;
+       if (*p) *p++=0;
+       else p=in;
+       k = sscanf(p, "%ld,%ld", &lp, &llen);
+# ifdef D1
+       fprintf(stderr, "p %s k %d lp %ld llen %ld\n",p,k,lp,llen);
+# endif
+       if (k<2)
+               {
+               lp = 0;
+               llen=outlen;
+               }
+# ifdef D1
+       fprintf(stderr, "lp %ld llen %ld\n",lp, llen);
+# endif
+# ifdef D1
+fprintf(stderr, "fa now %o, p %o in %o %s\n",fa, p,in,in);
+# endif
+       if (nofil)
+{
+# if D1
+fprintf(stderr, "set fa to stdin\n");
+# endif
+               fa = stdin;
+}
+       else
+       if (strcmp (name, in) != 0 || 1)
+               {
+# if D1
+fprintf(stderr, "old: %s new %s not equal\n",name,in);
+# endif
+               if (fa != NULL)
+                       fa = freopen(in, "r", fa);
+               else
+                       fa = fopen(in, "r");
+# if D1
+               if (fa==NULL) fprintf(stderr, "failed to (re)open *%s*\n",in);
+# endif
+               if (fa == NULL)
+                       return(0);
+                       /* err("Can't open %s", in); */
+               strcpy(name, in);
+               if (gdate(fa) > indexdate && indexdate != 0)
+                       {
+                       if (keepold)
+                               {
+                               for(ftp=fgnames; ftp<fgnamp; ftp++)
+                                       if (strcmp(*ftp, name)==SAME)
+                                               return(0);
+                               strcpy (*fgnamp++ = fgp, name);
+                               assert(fgnamp<fgnames+FGCT);
+                               while (*fgp && *fgp!=':')
+                                       fgp++;
+                               *fgp++ = 0;
+                               assert (fgp<fgspace+FGSIZE);
+                               return(0);
+                               }
+                       fprintf(stderr, "Warning: index predates file '%s'\n", name);
+                       }
+               }
+# if D1
+       else
+               fprintf(stderr, "old %s new %s same fa %o\n", name,in,fa);
+# endif
+       if (fa != NULL)
+               {
+               fseek (fa, lp, 0);
+               len = (llen >= outlen) ? outlen-1 : llen;
+               len = fread (out, 1, len, fa);
+               out[len] = 0;
+# ifdef D1
+       fprintf(stderr, "length as read is %d\n",len);
+# endif
+               }
+       return(len);
+}
diff --git a/usr/src/cmd/refer/hunt9.c b/usr/src/cmd/refer/hunt9.c
new file mode 100644 (file)
index 0000000..73b615f
--- /dev/null
@@ -0,0 +1,6 @@
+remote(in, out)
+       char *in, *out;
+{
+/* "in" is a long distance file name: get it */
+;
+}
diff --git a/usr/src/cmd/refer/inv2.c b/usr/src/cmd/refer/inv2.c
new file mode 100644 (file)
index 0000000..a3f9e41
--- /dev/null
@@ -0,0 +1,90 @@
+# include "stdio.h"
+# include "assert.h"
+newkeys (outf, inf, recf, nhash, fd, iflong)
+       FILE *outf, *inf, *recf, *fd;
+       int *iflong;
+{
+/* reads key lines from inf; hashes and writes on outf; writes orig
+   key on recf, records pointer on outf too.
+   format of outf is : hash code space record pointer
+*/
+
+# define LINESIZ 1250
+long lp, ftell();
+long ld = 0; int ll = 0, lt = 0;
+char line[LINESIZ];
+char key[30], bkeys[40];
+char *p, *s;
+char *keyv[500];
+int i, nk, ndoc = 0, more = 0, c;
+
+lp = ftell (recf);
+while (fgets(line, LINESIZ, inf))
+       {
+       p = line;
+       while (*p != '\t') p++;
+       *p++ =0;
+       fputs(line, recf);
+       if (fd)
+               {
+               sprintf(bkeys, ";%ld", ld);
+               ll = strlen(p);
+               lt = strlen(bkeys);
+               fputs(bkeys, recf);
+               sprintf(bkeys, ",%d", ll);
+               lt += strlen(bkeys);
+               fputs(bkeys, recf);
+               ld += ll;
+               fputs(p, fd);
+               }
+       putc('\n',recf);
+       for(s=p; *s; s++);
+       if (*--s == '\n')
+               {
+               more=0;
+               *s=0;
+               }
+       else
+               more=1;
+       _assert (fd==0 || more==0);
+       nk = getargs(p, keyv);
+       if (more)
+               nk--;
+       for(i=0; i<nk; i++)
+               fprintf(outf,"%04d %06ld\n",hash(keyv[i])%nhash, lp);
+# if D1
+       for(i=0; i<nk; i++)
+               printf("key %s hash %d\n",keyv[i],hash(keyv[i])%nhash);
+# endif
+       if (more) /* allow more than LINESIZ keys */
+               {
+               strcpy(key, keyv[nk]);
+               for(s=key; *s; s++);
+               while ( (c=getc(inf)) != '\n')
+                       {
+                       if (c != ' ')
+                               {
+                               *s++ = c;
+                               continue;
+                               }
+                       *s=0;
+                       if (s>key)
+                               fprintf(outf, "%04d %06ld\n",hash(key)%nhash, lp);
+                       s = key;
+                       }
+               }
+       lp += (strlen(line)+lt+1);
+       ndoc++;
+       }
+*iflong = (lp>=65536L);
+if (sizeof(int)>2) *iflong=1; /* force long on VAX */
+fclose(recf);
+return(ndoc);
+}
+trimnl(p)
+       char *p;
+{
+while (*p) p++;
+p--;
+if (*p == '\n') *p=0;
+}
diff --git a/usr/src/cmd/refer/inv3.c b/usr/src/cmd/refer/inv3.c
new file mode 100644 (file)
index 0000000..0448f4e
--- /dev/null
@@ -0,0 +1,16 @@
+getargs(s, arps)
+       char *s, *arps[];
+{
+       int i;
+i = 0;
+while (1)
+       {
+       arps[i++]=s;
+       while (*s != 0 && *s!=' '&& *s != '\t')s++;
+       if (*s==0) break;
+       *s++ =0;
+       while (*s==' ' || *s=='\t')s++;
+       if (*s==0)break;
+       }
+return(i);
+}
diff --git a/usr/src/cmd/refer/inv5.c b/usr/src/cmd/refer/inv5.c
new file mode 100644 (file)
index 0000000..7aa5886
--- /dev/null
@@ -0,0 +1,50 @@
+# include "stdio.h"
+
+recopy (ft, fb, fa, nhash)
+       FILE *ft, *fb, *fa;
+{
+/* copy fb (old hash items/pointers) to ft (new ones) */
+int n, i, iflong;
+long getl();
+int getw();
+int *hpt_s;
+int (*getfun)();
+long *hpt_l;
+long k, lp;
+if (fa==NULL)
+       {
+       err("No old pointers",0);
+       return;
+       }
+fread(&n, sizeof(n), 1, fa);
+fread(&iflong, sizeof(iflong), 1, fa);
+if (iflong)
+       {
+       hpt_l =  calloc(sizeof(*hpt_l), n+1);
+       n =fread(hpt_l, sizeof(*hpt_l), n, fa);
+       }
+else
+       {
+       hpt_s =  calloc(sizeof(*hpt_s), n+1);
+       n =fread(hpt_s, sizeof(*hpt_s), n, fa);
+       }
+if (n!= nhash)
+       fprintf(stderr, "Changing hash value to old %d\n",n);
+fclose(fa);
+if (iflong)
+       getfun = getl;
+else
+       getfun = getw;
+for(i=0; i<n; i++)
+       {
+       if (iflong)
+               lp = hpt_l[i];
+       else
+               lp = hpt_s[i];
+       fseek(fb, lp, 0);
+       while ( (k= (*getfun)(fb) ) != -1)
+               fprintf(ft, "%04d %06ld\n",i,k);
+       }
+fclose(fb);
+return(n);
+}
diff --git a/usr/src/cmd/refer/inv6.c b/usr/src/cmd/refer/inv6.c
new file mode 100644 (file)
index 0000000..99dd21f
--- /dev/null
@@ -0,0 +1,73 @@
+# include "stdio.h"
+# include "assert.h"
+whash(ft, fa, fb, nhash, iflong, ptotct, phused)
+       FILE *fa, *fb, *ft;
+       int nhash, *phused;
+       long *ptotct;
+{
+char line[100];
+int hash = 0, hused = 0;
+long totct = 0L;
+int ct = 0;
+long point;
+long opoint = -1;
+int m;
+int k; long lp;
+long *hpt;
+int *hfreq = NULL;
+
+hpt = calloc (nhash+1, sizeof(*hpt));
+_assert (hpt != NULL);
+hfreq = calloc (nhash, sizeof(*hfreq));
+_assert (hfreq !=NULL);
+hpt[0] = 0;
+lp= 0;
+while (fgets(line, 100, ft))
+       {
+       totct++;
+       sscanf(line, "%d %ld", &k, &point);
+       if (hash < k)
+               {
+               hused++;
+               if (iflong) putl(-1L, fb); else putw(-1, fb);
+               hfreq[hash]=ct;
+               while (hash<k)
+                       {
+                       hpt[++hash] = lp;
+                       hfreq[hash] = 0;
+                       }
+               hpt[hash] = lp += iflong? sizeof(long) : sizeof(int);
+               opoint= -1;
+               ct=0;
+               }
+       if (point!=opoint)
+               {
+               if (iflong)
+                       putl(opoint=point, fb);
+               else
+                       putw( (int)(opoint=point), fb);
+               lp += iflong? sizeof(long) : sizeof(int);
+               ct++;
+               }
+       }
+if (iflong) putl(-1L, fb); else putw(-1,fb);
+while (hash<nhash)
+       hpt[++hash]=lp;
+fwrite(&nhash, sizeof(nhash), 1, fa);
+fwrite(&iflong, sizeof(iflong), 1, fa);
+fwrite(hpt, sizeof(*hpt), nhash, fa);
+fwrite (hfreq, sizeof(*hfreq), nhash, fa);
+*ptotct = totct;
+*phused = hused;
+}
+putl(ll, f)
+       long ll;
+       FILE *f;
+{
+putw(ll, f);
+}
+long getl(f)
+       FILE *f;
+{
+return(getw(f));
+}
diff --git a/usr/src/cmd/refer/kaiser.c b/usr/src/cmd/refer/kaiser.c
new file mode 100644 (file)
index 0000000..cd1ddfb
--- /dev/null
@@ -0,0 +1,274 @@
+# include "stdio.h"
+# include "ctype.h"
+char *months[] {"Jan", "Feb", "Mar", "Apr", "May",
+       "Jun", "Jul", "Aug", "Sep","Oct", "Nov", "Dec",0};
+main()
+{
+int state 1000, i, book, volume, corp, report;
+int na;
+char *v[20], **vv, **rr;
+char ubuff[1000], *up;
+char line[100];
+char *p, *s, *r, *q;
+while (gets(line))
+       {
+       if (line[1]>'9' || line[1]<'0') continue;
+       switch(line[0])
+               {
+               case 'T':
+                       if (state > 'T')
+                               {
+                               book=0;
+                               report=0;
+                               printf("\n%%T ");
+                               }
+                       printf("%s\n", line+18);
+                       state='T';
+                       na = getargs(line+18, v);
+                       for(i=0;i<na;i++)
+                               if (strcmp(v[i], "(Book)")==0)
+                                       book=1;
+                       continue;
+               case 'A':
+                       state = 'A';
+                       na=getargs(line+18, vv=v);
+                       if (na<=0) continue;
+                       while (na>0)
+                               {
+                               printf("%%A ");
+                               corp=0;
+                               for(p=vv[1]; *p; p++)
+                                       if (islower(*p))
+                                               corp=1;
+                               if (corp==0)
+                                       {
+                                       for(p=vv[1]; *p; p++)
+                                               printf("%c. ", *p);
+                                       if (na>2 &&strcmp(vv[2], "+"))
+                                               {
+                                               printf("%s", vv[0]);
+                                               if (strcmp(vv[2], "Jr.")==0)
+                                                       printf(",");
+                                               printf(" %s\n",vv[2]);
+                                               vv++;na--;
+                                               }
+                                       else
+                                               printf("%s\n", vv[0]);
+                                       }
+                               else
+                                       printf("%s %s\n",vv[0],vv[1]);
+                               vv+=2;
+                               na-=2;
+                               if (strcmp(vv[0], "+")==0)
+                                       {
+                                       vv++;na--;
+                                       }
+                               }
+                       continue;
+               case 'U':
+                       if (state!='U')
+                               ubuff[0]=0;
+                       else
+                               strcat(ubuff, " ");
+                       state = 'U';
+                       strcat(ubuff, line+18);
+                       if (line[2]=='.')
+                               { /* end of item */
+                               p=ubuff; /*start*/
+                               volume=0;
+                               for(s=ubuff; *s; s++)
+                                       if (s[-1]==' ' && prefix("Vol", s))
+                                               {
+                                               for(q=s-1; q>ubuff; q--)
+                                                       {
+                                                       if (*q==' ' || *q==',') *q=0;
+                                                       else break;
+                                                       }
+                                               volume=1;
+                                               break;
+                                               }
+                               if (*s==0)
+                               for(s=ubuff; *s && (*s!=',' || sprefix("Inc", s+1)); s++)
+                                       ;
+                               else
+                               s++;
+                               if (*s==',')*s++=0;
+                               if (book)
+                                       printf("%%I %s\n",ubuff);
+                               else if (volume)
+                                       printf("%%J %s\n", ubuff);
+                               else if (substr(ubuff, "Report")!=0)
+                                       {
+                                       report=1;
+                                       printf("%%R %s\n", ubuff);
+                                       }
+                               else
+                                       printf("%%J %s\n", ubuff);
+                               if (volume)
+                                       {
+                                       s += 3; /* Vol */
+                                       if (*s=='.') s++;
+                                       while (*s==' ')s++;
+                                       printf("%%V ");
+                                       while (*s && *s != ' ' && *s!=',' && *s!=';' && *s!= ':')
+                                               putchar(*s++);
+                                       putchar('\n');
+                                       if (*s==':')
+                                               {
+                                               printf("%%N ");
+                                               while (*s==' ')s++;
+                                               while (isdigit(*s))
+                                                       putchar(*s++);
+                                               putchar('\n');
+                                               }
+                                       *s++=0;
+                                       while (*s==' ')*s++=0;
+                                       if (s[0]=='N' && s[1]=='o' && (s[2]==' '||s[2]=='.'))
+                                               {
+                                               s+=2;
+                                               while (*s==' '||*s=='.')s++;
+                                               printf("%%N ");
+                                               while (isdigit(*s)||*s=='-')
+                                                       putchar(*s++);
+                                               putchar('\n');
+                                               }
+                                       if (*s==',') *s++=0;
+                                       }
+                               for(rr=months; *rr; rr++)
+                                       {
+                                       q= substr(s, *rr);
+                                       if (q)
+                                               {
+                                               for(r=q; *r; r++);
+                                               r--;
+                                               if (*r=='.')*r=0;
+                                               printf("%%D %s\n",q);
+                                               *(q-1)=0;
+                                               break;
+                                               }
+                                       }
+                               if (*rr==0)
+                                       {
+                                       for(q=s; *q; q++)
+                                               {
+                                               if (q[0]=='1' && q[1]=='9' && (q[4]==0 || (q[4]=='.' && q[5]==0)))
+                                                       {
+                                                       if (q[4]=='.') q[4]=0;
+                                                       printf("%%D %s\n",q);
+                                                       rr=months;
+                                                       q[-1]=0;
+                                                       if (q==s) q[0]=0;
+                                                       break;
+                                                       }
+                                               }
+                                       }
+                               if (*rr==0) /* no date */
+                                       printf("%%D 19xx\n");
+                               /* if book bite off next field for city, if report for issuer */
+                               if (book)
+                                       {
+                                       for(q=s; *q && *q != ','; q++)
+                                               ;
+                                       if (*q==',')
+                                               {
+                                               r=q;
+                                               r++;
+                                               while (*r==' ')r++;
+                                               if (isupper(r[0]) && isupper(r[1]))
+                                                       {
+                                                       r+=2;
+                                                       *r++=0;
+                                                       while (*r==' ')r++;
+                                                       }
+                                               else
+                                                       *q=0;
+                                               printf("%%C %s\n", s);
+                                               s=r;
+                                               }
+                                       }
+                               for(q=s; *q; q++)
+                                       {
+                                       if (q[0]==' ' && q[1]=='p' && (q[2]=='p'||q[2]==0))
+                                               {
+                                               for(r=q; r>s; r--)
+                                                       {
+                                                       if (*r==' ' || *r==',')
+                                                               *r=0;
+                                                       }
+                                               *q=0;
+                                               q+=2;
+                                               if (q[0]=='p')q++;
+                                               while (*q==' '||*q=='.')q++;
+                                               r=q;
+                                               while (isdigit(*q)||*q=='.'||*q=='-'||isalpha(*q))q++;
+                                               *q++=0;
+                                               while (*q==' ')q++;
+                                               printf("%%P %s\n",r);
+                                               break;
+                                               }
+                                       }
+                               s=ispp(s);
+                               while (*s==' ')s++;
+                               while (*q==' ')q++;
+                               if (*s||*q)
+                                       printf("%%O %s %s\n", *s?s:"", *q?q:"");
+                               }
+                       continue;
+               }
+       }
+}
+getargs(s, arps)
+       char *s, *arps[];
+{
+       int i;
+i = 0;
+while (1)
+       {
+       arps[i++]=s;
+       while (*s != 0 && *s!=' '&& *s != '\t')s++;
+       if (*s==0) break;
+       *s++ =0;
+       while (*s==' ' || *s=='\t')s++;
+       if (*s==0)break;
+       }
+return(i);
+}
+prefix(small, big)
+       char *small, *big;
+{
+int c;
+while ((c= *small++) == *big++)
+       if (c==0) return(1);
+return(c==0);
+}
+substr(big, small)
+       char *small, *big;
+{
+while (*big)
+       if (prefix(small, big))
+               return(big);
+       else
+               big++;
+return(0);
+}
+sprefix(small, big)
+       char *small, *big;
+{
+while (*big==' ') big++;
+return(prefix(small,big));
+}
+ispp(s)
+       char *s;
+{
+static char buff[50];
+char *p, *t;
+p=s;
+while (*p==' ') p++;
+if (!isdigit(*p)) return(s);
+t=p;
+while (isdigit(*p))p++;
+if (p[0]!='p' || p[1]!='p') return(s);
+*p=0;
+sprintf(buff, "%spp.", t);
+return(buff);
+}
diff --git a/usr/src/cmd/refer/mkey2.c b/usr/src/cmd/refer/mkey2.c
new file mode 100644 (file)
index 0000000..94949b1
--- /dev/null
@@ -0,0 +1,137 @@
+# include "stdio.h"
+# include "ctype.h"
+
+       static int eof = 0;
+       static long lp, lim;
+       static int alph, used, prevc;
+       static char *p, key[20];
+
+dofile(f, name)
+       FILE *f;
+       char *name;
+{
+
+/* read file f & spit out keys & ptrs */
+# define MAXLINE 500
+char line[MAXLINE], *s;
+extern int minlen, keycount, labels;
+int c;
+long grec();
+extern int wholefile;
+extern char *iglist;
+alph=used=prevc=eof=0;
+
+lp=0;
+if (wholefile==0)
+while (lim = grec(line,f))
+       {
+# if D1
+fprintf(stderr, "line: /%s",line);
+# endif
+       used=alph=0;
+       p = key;
+       for(s=line; (c= *s) && (used<keycount); s++)
+               chkey(c, name);
+       lp += lim;
+       if (used) putchar('\n');
+       }
+else
+       {
+       p=key;
+       used=alph=0;
+       while ( (c=getc(f)) != EOF && used<keycount)
+               chkey (c, name);
+       if (used) putchar('\n');
+       }
+fclose(f);
+}
+
+outkey( ky, lead, trail)
+       char *ky;
+{
+       int n;
+n = strlen(ky);
+if (n<minlen) return (0);
+if (n<3)
+       {
+       if (trail == '.') return(0);
+       if (mindex(".%,!#$%&'();+:*", lead)!=0) return(0);
+       }
+if (isdigit(ky[0]))
+       if (ky[0] != '1' || ky[1] != '9' || n!= 4) return(0);
+if (common(ky))
+       return(0);
+return(1);
+}
+long grec (s, f)
+       char *s;
+       FILE *f;
+{
+       char tm[200];
+       int curtype = 0;
+       long len = 0L, tlen = 0L;
+       extern int wholefile;
+       if (eof) return(0);
+       *s = 0;
+       while (fgets(tm, 200, f))
+               {
+               tlen += strlen(tm);
+               if (tm[0] == '%' || tm[0] == '.')
+                       curtype = tm[1];
+               if (tlen < MAXLINE && mindex(iglist,curtype)==0)
+                               strcat(s, tm);
+               len = tlen;
+               if (wholefile==0 && tm[0] == '\n')
+                       return(len);
+               if (wholefile>0 && len >= MAXLINE)
+                       {
+                       fseek (f, 0L, 2);
+                       return(ftell(f));
+                       }
+               }
+       eof=1;
+       return(s[0] ? len : 0L);
+}
+char *
+trimnl(ln)
+       char *ln;
+{
+register char *p = ln;
+while (*p) p++;
+p--;
+if (*p == '\n') *p=0;
+return(ln);
+}
+chkey (c, name)
+       {
+       if (isalpha(c) || isdigit(c))
+               {
+               if (alph++ < 6)
+                       *p++ = c;
+               }
+       else
+               {
+               *p = 0;
+               for(p=key; *p; p++)
+                       *p |= 040;
+               if (outkey(p=key,prevc,c))
+                       {
+                       if (used==0)
+                           {
+                           if (labels)
+                               {
+                               if (wholefile==0)
+                                       printf("%s:%ld,%ld\t", name, lp, lim);
+                               else
+                                       printf("%s\t", name);
+                           }
+                               }
+                       else
+                               putchar(' ');
+                       fputs(key, stdout);
+                       used++;
+                       }
+               prevc=c;
+               alph=0;
+               }
+       }
diff --git a/usr/src/cmd/refer/mkey3.c b/usr/src/cmd/refer/mkey3.c
new file mode 100644 (file)
index 0000000..0787400
--- /dev/null
@@ -0,0 +1,50 @@
+# include "stdio.h"
+char *comname = "/usr/lib/eign";
+static int cgate = 0;
+extern char *comname;
+# define COMNUM 500
+# define COMTSIZE 997
+int comcount = 100;
+static char cbuf[COMNUM*9];
+static char *cwds[COMTSIZE];
+static char *cbp;
+
+common (s)
+       char *s;
+{
+if (cgate==0) cominit();
+return (c_look(s, 1));
+}
+cominit()
+{
+int i;
+FILE *f;
+cgate=1;
+f = fopen(comname, "r");
+if (f==NULL) return;
+cbp=cbuf;
+for(i=0; i<comcount; i++)
+       {
+       if (fgets(cbp, 15, f)==NULL)
+               break;
+       trimnl(cbp);
+       c_look (cbp, 0);
+       while (*cbp++);
+       }
+fclose(f);
+}
+c_look (s, fl)
+       char *s;
+{
+int h;
+h = hash(s) % (COMTSIZE);
+while (cwds[h] != 0)
+       {
+       if (strcmp(s, cwds[h])==0)
+               return(1);
+       h = (h+1) % (COMTSIZE);
+       }
+if (fl==0)
+       cwds[h] = s;
+return(0);
+}
diff --git a/usr/src/cmd/refer/refer0.c b/usr/src/cmd/refer/refer0.c
new file mode 100644 (file)
index 0000000..caaa6a8
--- /dev/null
@@ -0,0 +1,27 @@
+# include "stdio.h"
+# include "refer..c"
+FILE *in = stdin;
+int endpush = 0;
+int labels = 0;
+int keywant = 0;
+int sort = 0;
+int bare = 0;
+int authrev = 0;
+char *smallcaps = "";
+char *keystr = "AD";
+int nmlen = 0, dtlen = 0;
+char *rdata[NSERCH];
+char **search = rdata;
+int refnum = 0;
+char reftext[NRFTXT];
+char *reftable[NRFTBL];
+char *rtp = reftext;
+int sep = '\n';
+char tfile[NTFILE];
+FILE *fo = stdout;
+FILE *ftemp = stdout;
+char ofile[NTFILE];
+char gfile[NTFILE];
+char hidenam[NTFILE];
+char *Ifile = "standard input";
+int Iline = 0;
diff --git a/usr/src/cmd/refer/refer1.c b/usr/src/cmd/refer/refer1.c
new file mode 100644 (file)
index 0000000..8aa8603
--- /dev/null
@@ -0,0 +1,151 @@
+# include "signal.h"
+# include "refer..c"
+main(argc,argv)
+       char *argv[];
+{
+char line[LLINE], *s;
+int nodeflt =0;
+
+signals();
+while (argv[1][0] == '-')
+       {
+       switch(argv[1][1])
+               {
+               case 'e':
+                       endpush++; break;
+               case 'l': 
+                       labels++;
+                       s = argv[1]+2;
+                       nmlen = atoi(s);
+                       while (*s)
+                               if (*s++ == ',')
+                                       break;
+                       dtlen = atoi(s);
+                       break;
+               case 'k':
+                       keywant = (argv[1][2] ? argv[1][2] : 'L');
+                       labels++;
+                       break;
+               case 's':
+                       sort++;
+                       if (argv[1][2])
+                               keystr= argv[1]+2;
+                       break;
+               case 'p':
+                       argc--; argv++;
+                       *search++ = argv[1];
+                       if (search-rdata>NSERCH)
+                               err("too many -p options (%d)", NSERCH);
+                       break;
+               case 'n':
+                       nodeflt=1;
+                       break;
+               case 'b':
+                       bare = (argv[1][2] == '1') ? 1 : 2;
+                       break;
+               case 'c':
+                       smallcaps = argv[1]+2;
+                       break;
+               case 'a':
+                       authrev = atoi (argv[1]+2);
+                       if (authrev<=0)
+                               authrev = 1000;
+                       break;
+               }
+       argc--; argv++;
+       }
+if (nodeflt==0)
+       *search++ = "/usr/dict/papers/Ind";
+
+if (sort)
+       endpush=1;
+if (endpush)
+       {
+       sprintf(tfile, "/tmp/rj%da", getpid());
+       fo = fopen(tfile, "w");
+       if (fo==NULL)
+               {
+               fo = ftemp;
+               fprintf(stderr,"Can't open scratch file");
+               }
+       sep = 002; /* separate records without confusing sort..*/
+       }
+
+
+if (sort && !labels)
+       {
+       sprintf(ofile,"/tmp/rj%db", getpid());
+       ftemp = fopen(ofile, "w");
+       if (ftemp==NULL)
+               {
+               fprintf(stderr, "Can't open scratch file\n");
+               exit(1);
+               }
+       }
+
+do
+       {
+       if (argc>1)
+               {
+               fclose(in);
+               Iline=0;
+               in = fopen(Ifile=argv[1], "r");
+               argc--; argv++;
+               if (in==NULL)
+                       {
+                       err("Can't read %s", Ifile);
+                       continue;
+                       }
+               }
+       while (input(line))
+               {
+               Iline++;
+# ifdef D1
+               fprintf(stderr, "line %.20s\n",line);
+# endif
+               if (!prefix(".[", line))
+                       output(line);
+               else
+                       doref(line);
+# if D1
+               fprintf(stderr, "past output/doref\n");
+# endif
+               }
+       }
+       while (argc>1);
+if (endpush && fo!=NULL)
+       dumpold();
+output("", ftemp);
+if (sort && !labels)
+       recopy(ofile);
+clfgrep();
+cleanup();
+exit(0);
+}
+
+extern int intr();
+signals()
+{
+       int oldint;
+oldint = signal(SIGINT, &intr);
+if (oldint==1)
+       signal (SIGINT, 1);
+signal (SIGHUP, &intr);
+signal (SIGPIPE, &intr);
+signal (SIGTERM, &intr);
+}
+
+intr()
+{
+       int oldsig;
+signal(SIGINT, 1);
+cleanup();
+exit(1);
+}
+cleanup()
+{
+if (tfile[0]) unlink(tfile);
+if (gfile[0]) unlink(gfile);
+if (ofile[0]) unlink(ofile);
+if (hidenam[0]) unlink(hidenam);
+}
diff --git a/usr/src/cmd/refer/refer2.c b/usr/src/cmd/refer/refer2.c
new file mode 100644 (file)
index 0000000..ccec3da
--- /dev/null
@@ -0,0 +1,203 @@
+# include "refer..c"
+extern FILE *in;
+# define NFLD 30
+# define TLEN 400
+char one[ANSLEN];
+int onelen = ANSLEN;
+static char dr [100] = "";
+doref(firline)
+       char *firline;
+{
+char buff[QLEN], dbuff[3*QLEN], answer[ANSLEN], temp[TLEN];
+char line[LLINE];
+char *p, **sr, *flds[NFLD], *r;
+int nf, nr, alph, query = 0, chp, digs;
+
+/* get query */
+buff[0] = dbuff[0] = 0;
+while (input(line))
+       {
+       if (prefix(".]", line))
+               break;
+       if (control(line[0])) query=1;
+       strcat (query  ? dbuff: buff, line);
+       if (strlen(buff)>QLEN)
+               err("buff too big (%d)", strlen(buff));
+       assert (strlen(dbuff) <3*QLEN);
+       }
+if (strcmp (buff, "$LIST$\n")==0)
+       {
+# if D1
+fprintf(stderr, "dump sorted list\n");
+# endif
+       assert ( dbuff[0]==0);
+       dumpold();
+       return;
+       }
+answer[0] = 0;
+# ifdef D1
+       fprintf(stderr, "query is %s\n",buff);
+# endif
+for( p=buff; *p; p++)
+       {
+       if (isupper(*p)) *p |= 040;
+       }
+alph = digs =0;
+for(p=buff; *p; p++)
+       {
+       if (isalpha(chp = *p)) alph++;
+       else
+       if (isdigit(*p)) digs++;
+       else
+               {
+               *p=0;
+               if ( (alph+digs<3) || common(p-alph))
+                       {
+                       r = p-alph;
+                       while (r < p)
+                               *r++ = ' ';
+                       }
+               if ( alph==0 && digs >0)
+                       {
+                       r = p-digs;
+# if D1
+fprintf(stderr, "number, %d long, text is %s\n",digs,r);
+# endif
+                       if (digs != 4 || (atoi(r)/100 != 19))
+                               {
+                               while (r<p)
+                                       *r++ = ' ';
+                               }
+                       }
+               *p=' ';
+               alph = digs = 0;
+               }
+       }
+# ifdef D1
+       fprintf(stderr, "query translated to %s\n", buff);
+# endif
+one[0]=0;
+if (buff[0]) /* do not search if no query */
+for( sr= rdata; sr < search; sr++)
+       {
+# ifdef D1
+       fprintf(stderr, "now searching %s\n", *sr);
+# endif
+       temp[0]=0;
+       corout (buff, temp, "hunt", *sr, TLEN);
+       assert (strlen(temp)<TLEN);
+       if (strlen(temp)+strlen(answer)>LLINE)
+               err("Accumulated answers too large",0);
+       strcat (answer, temp);
+       if (strlen(answer)>LLINE)
+               err("answer too long (%d)", strlen(answer));
+       if (newline(answer) > 0) break;
+       }
+# if D1
+fprintf(stderr, "answer:\n%s****\n", answer);
+# endif
+assert (strlen(one)<ANSLEN);
+assert (strlen(answer)<ANSLEN);
+if (buff[0])
+switch (newline(answer))
+       {
+       case 0:
+               fprintf (stderr, "No such paper %s\n", buff);
+               return;
+       default:
+               fprintf(stderr, "too many hits for '%s'\n", trimnl(buff));
+               choices(answer);
+               p = buff;
+               while (*p != '\n') p++;
+               *++p=0;
+       case 1:
+# ifdef D1
+       fprintf(stderr, "found one\n");
+# endif
+               if (endpush)
+                       if (nr = chkdup(answer))
+                               {
+                               if (bare<2)
+                                       putsig (0, flds, nr, firline, line);
+                               return;
+                               }
+# if D1
+               fprintf(stderr, "one[0] was %o\n",one[0]);
+# endif
+               if (one[0]==0)
+                       corout (answer, one, "deliv", dr, QLEN);
+# if D1
+               fprintf(stderr, "one now %o\n",one[0]);
+# endif
+               break;
+       }
+assert (strlen(buff)<QLEN);
+assert (strlen(one)<ANSLEN);
+nf = tabs(flds, one);
+nf += tabs(flds+nf, dbuff);
+# if D1
+fprintf(stderr, "one %.20s dbuff %.20s nf %d\n",one,dbuff, nf);
+# endif
+assert (nf < NFLD);
+refnum++;
+if (sort) putkey (nf, flds, refnum, keystr);
+if (bare<2)
+       putsig (nf, flds, refnum, firline, line);
+else
+       flout();
+# if D1
+fprintf(stderr, "put signal\n");
+# endif
+putref (nf, flds);
+# if D1
+fprintf(stderr, "put ref\n");
+# endif
+}
+newline(s)
+       char *s;
+{
+int k = 0, c;
+while (c = *s++)
+       if (c == '\n')
+               k++;
+return(k);
+}
+choices( buff )
+       char *buff;
+{
+char ob[LLINE], *p, *r, *q, *t;
+int nl;
+for(r=p= buff; *p; p++)
+       {
+       if (*p == '\n')
+               {
+               *p++ = 0;
+                       {
+                       corout (r, ob, "deliv", dr, LLINE);
+                       nl = 1;
+                       for( q=ob; *q; q++)
+                               {
+                               if (nl && (q[0] == '.' || q[0] == '%') && q[1] == 'T')
+                                       {
+                                       q += 3;
+                                       for (t=q; *t && *t != '\n'; t++);
+                                       *t = 0;
+                                       fprintf(stderr, "%.70s\n", q);
+                                       q=0; break;
+                                       }
+                               nl = *q == '\n';
+                               }
+                       if (q)
+                               fprintf(stderr, "??? at %s\n",r);
+                       }
+               r=p;
+               }
+       }
+}
+
+control(c)
+       {
+       if (c=='.') return(1);
+       if (c=='%') return(1);
+       return(0);
+       }
diff --git a/usr/src/cmd/refer/refer3.c b/usr/src/cmd/refer/refer3.c
new file mode 100644 (file)
index 0000000..ca95793
--- /dev/null
@@ -0,0 +1,26 @@
+# include "refer..c"
+corout(in, out, rprog, arg, outlen)
+       char *in, *out, *rprog;
+{
+# define move(x, y) close(y); dup(x); close(x);
+int pipev[2], fr1, fr2, fw1, fw2, n;
+
+pipe (pipev); fr1= pipev[0]; fw1 = pipev[1];
+pipe (pipev); fr2= pipev[0]; fw2 = pipev[1];
+if (fork()==0)
+       {
+       close (fw1); close (fr2);
+       move (fr1, 0);
+       move (fw2, 1);
+       execl(rprog, "deliv", arg, 0);
+       err ("Can't run %s", rprog);
+       }
+close(fw2); close(fr1);
+write (fw1, in , strlen(in));
+close(fw1);
+wait(0);
+n = read (fr2, out, outlen);
+out[n]=0;
+close(fr2);
+return(n);
+}
diff --git a/usr/src/cmd/refer/refer4.c b/usr/src/cmd/refer/refer4.c
new file mode 100644 (file)
index 0000000..476d7c9
--- /dev/null
@@ -0,0 +1,65 @@
+# include "refer..c"
+static gate = 0;
+static char buff[LLINE];
+output (s)
+       char *s;
+{
+if (gate)
+       fputs(buff,ftemp);
+else
+       gate=1;
+strcpy(buff,s);
+if (strlen(buff)>LLINE)
+       err("one buff too big (%d)!", LLINE);
+}
+append(s)
+       char *s;
+{
+char *p, *r; int lch;
+trimnl(buff);
+for (p=buff; *p; p++)
+       ;
+lch = *--p;
+switch (lch)
+       {
+       case '.': case ',':
+               *p=0;
+               r="\\*(<";
+               while (*r) *p++= *r++;
+               *p++ = lch;
+               *p=0;
+       }
+strcat(buff,s);
+switch(lch)
+       {
+       case '.': case ',':
+               for(p=buff; *p; p++)
+                       ;
+               if (*--p=='\n')*p=0;
+               r = "\\*(>";
+               while (*r) *p++ = *r++;
+               *p++ = lch;
+               *p++ = '\n';
+               *p=0;
+       }
+if (strlen(buff)>LLINE)
+       err("output buff too long (%d)", LLINE);
+}
+
+flout()
+{
+if (gate)
+       fputs(buff,ftemp);
+gate=0;
+}
+
+char *
+trimnl(ln)
+       char *ln;
+{
+register char *p = ln;
+while (*p) p++;
+p--;
+if (*p == '\n') *p=0;
+return(ln);
+}
diff --git a/usr/src/cmd/refer/refer5.c b/usr/src/cmd/refer/refer5.c
new file mode 100644 (file)
index 0000000..748fe91
--- /dev/null
@@ -0,0 +1,274 @@
+# include "refer..c"
+# define SAME 0
+# define NFLAB 2000
+# define NLABC 100
+static char sig[NLABC];
+
+static char bflab[NFLAB];
+static char *labtab[NLABC];
+static char *lbp = bflab;
+static char labc[NLABC];
+static char stbuff[50];
+static int  prevsig;
+
+putsig (nf, flds, nref, nstline, endline)
+       char *flds[], *nstline, *endline;
+{
+/* choose signal style */
+char t[100], t1[100], t2[100], format[10], *sd;
+int another = 0;
+int addon;
+char *stline;
+static FILE *fhide = 0;
+if (labels)
+       {
+       if (nf==0) /* old */
+               sprintf(t, "%s%c", labtab[nref], labc[nref]);
+       else
+               {
+               *t=0;
+               if (keywant)
+                       sprintf(t, "%s", fpar(nf, flds, t1, keywant, 1, 0));
+               if (t[0]==0)
+                       {
+                       sprintf(format, nmlen>0 ? "%%.%ds%%s" : "%%s%%s", nmlen);
+                       /* format is %s%s for default labels or %.3s%s eg if wanted */
+                       sd = fpar(nf, flds, t2, 'D', 1, 0);
+                       if (dtlen>0)
+                               {
+                               char *sdb;
+                               for(sdb=sd; *sd; sd++);
+                               sd = sd-dtlen;
+                               if (sd<sdb) sd=sdb;
+                               }
+                       sprintf(t, format, fpar(nf, flds, t1, 'A', 1, 0), sd);
+                       }
+               if (keywant)
+                       {
+                       addon=0;
+                       for(sd=t; *sd; sd++);
+                       if (*--sd == '-')
+                               {
+                               addon=1;
+                               *sd=0;
+                               }
+                       }
+               if (!keywant || addon)
+                       addch( t, keylet(t, nref));
+               }
+       }
+else 
+       {
+       if (sort)
+               sprintf(t, "%c%d%c", FLAG, nref, FLAG);
+       else
+               sprintf(t, "%d", nref);
+       }
+another = prefix (".[", sd=lookat());
+if (another && (strcmp(".[\n", sd) != SAME))
+       fprintf(stderr, "File %s, line %d- punctuation ignored from: %s", Ifile, Iline, sd);
+strcat (sig, t);
+# if D1
+fprintf(stderr, "sig is now %s leng %d\n",sig,strlen(sig));
+# endif
+trimnl(nstline);
+trimnl(endline);
+stline=stbuff;
+if (prevsig==0)
+       {
+       strcpy (stline, nstline);
+       prevsig=1;
+       }
+if (stline[2] || endline[2])
+       {
+       stline += 2;
+       endline += 2;
+       }
+else
+       {
+       stline  = "\\*([.";
+       endline = "\\*(.]";
+       }
+if (bare==0)
+       {
+       if (another==0)
+               {
+               sprintf(t1, "%s%s\%s\n", stline, sig, endline);
+               append(t1);
+               flout();
+               sig[0]=0;
+               prevsig=0;
+               if (fo == fhide)
+                       {
+                       int ch;
+                       fclose(fhide); fhide= fopen(hidenam, "r");
+                       fo= ftemp;
+                       while ((ch = getc(fhide)) != EOF)
+                               putc(ch, fo);
+                       fclose(fhide);
+                       unlink(hidenam);
+                       }
+               }
+       else
+               {
+               strcat (sig, ",\\|");
+               /* hide if need be */
+               if (fo == ftemp)
+                       {
+                       sprintf(hidenam, "/tmp/rj%dc", getpid());
+# if D1
+fprintf(stderr, "hiding in %s\n", hidenam);
+# endif
+                       fhide= fopen(hidenam, "w");
+                       if (fhide==NULL) err("Can't get scratch file %s", hidenam);
+                       fo = fhide;
+                       }
+               }
+       }
+if (bare<2)
+       if (nf>0) fprintf(fo,".ds [F %s%c",t,sep);
+if (bare>0)
+       flout();
+# if D1
+fprintf(stderr, "sig is now %s\n",sig);
+# endif
+}
+char *
+fpar (nf, flds, out, c, seq, prepend)
+       char *flds[], *out;
+{
+char *p, *s;
+int i, fnd = 0;
+for(i=0; i<nf; i++)
+       if (flds[i][1]==c && ++fnd >= seq)
+               {
+               if (c=='T' || c == 'J') /* for titles use first word otherwise last */
+                       {
+                       p=flds[i]+3;
+                       if (prefix("A ", p)) p +=2;
+                       if (prefix("An ", p)) p +=3;
+                       if (prefix("The ", p)) p+= 4;
+                       mycpy2(out, p, 20);
+                       return(out);
+                       }
+               for(s=p= flds[i]+2; *p; p++);
+               while (p>s && *p != ' ') p--;
+               /* special wart for authors */
+               if (c=='A' && (p[-1] == ',' || p[1] =='('))
+                       {
+                       p--;
+                       while (p>s && *p != ' ') p--;
+                       mycpy (out, p+1);
+                       }
+               else
+                       strcpy (out, p+1);
+               if (c=='A' && prepend)
+                       initadd(out, flds[i]+2, p);
+               return(out);
+               }
+return(0);
+}
+putkey(nf, flds, nref, keystr)
+       char *flds[], *keystr;
+{
+char t1[50], *sf;
+int ctype, i, count;
+fprintf(fo, ".\\\"");
+if (nf <= 0)
+       fprintf(fo, "%s%c%c", labtab[nref], labc[nref], sep);
+else
+       {
+       while (ctype= *keystr++)
+               {
+               count = atoi(keystr);
+               if (*keystr=='+') count=999;
+               if (count<=0) count=1;
+               for(i=1; i<=count; i++)
+                       {
+                       sf= fpar(nf, flds, t1, ctype, i, 1);
+                       if (sf==0)
+                               break;
+                       sf = artskp(sf);
+                       fprintf(fo, "%s%c", sf, '-');
+                       }
+               }
+       fprintf(fo, "%c%d%c%c", FLAG, nref, FLAG, sep);
+       }
+}
+keylet(t, nref)
+       char *t;
+{
+int i;
+int x = 'a'-1;
+for(i=1; i<nref;i++)
+       {
+       if (strcmp(labtab[i], t) == 0)
+               x = labc[i];
+       }
+strcpy(labtab[nref]=lbp, t);
+while (*lbp++);
+if (lbp-bflab >NFLAB)
+       err("bflab overflow (%d)", NFLAB);
+if (nref >NLABC)
+       err ("nref in labc overflow (%d)", NLABC);
+# ifdef D1
+fprintf(stderr, "lbp up to %d of 2000\n", lbp-bflab);
+# endif
+return (labc[nref] = x+1);
+}
+mycpy(s,t)
+       char *s, *t;
+{
+while (*t && *t != ',' && *t != ' ')
+       *s++ = *t++;
+*s=0;
+}
+mycpy2 (s, t, n)
+       char *s, *t;
+{
+int c;
+while (n-- && (c= *t++)>0)
+       {
+       if (c==' ')c= '-';
+       *s++ = c;
+       }
+*s=0;
+}
+initadd(to, from, stop)
+       char *to, *from, *stop;
+{
+       int c, nalph = 1;
+while (*to) to++;
+while (from<stop)
+       {
+       c = *from++;
+       if (!isalpha(c))
+               {
+               if (nalph)
+                       *to++ = '.';
+               nalph=0;
+               continue;
+               }
+       if (nalph++ ==0)
+               *to++ = c;
+       }
+*to=0;
+}
+
+static char *articles[] = {"the ", "an ", "a ", 0};
+char *
+artskp(s)
+       char *s;
+{
+/* skips over initial "a ", "an ", or "the " in s */
+       char **p, *r1, *r2;
+for(p=articles; *p; p++)
+       {
+       r2 = s;
+       for (r1= *p; ((*r1 ^ *r2) & ~040 ) == 0; r1++)
+               r2++;
+       if (*r1==0 && *r2 != 0)
+               return(r2);
+       }
+return(s);
+}
diff --git a/usr/src/cmd/refer/refer8.c b/usr/src/cmd/refer/refer8.c
new file mode 100644 (file)
index 0000000..6ea018a
--- /dev/null
@@ -0,0 +1,32 @@
+# include "refer..c"
+static char ahead[1000];
+static int peeked = 0;
+static int noteof = 1;
+char *
+input (s)
+       char *s;
+{
+if (peeked)
+       {
+       peeked=0;
+       if (noteof==0) return(0);
+       strcpy (s, ahead);
+       return(s);
+       }
+return(fgets(s, 1000, in));
+}
+char *
+lookat()
+{
+if (peeked) return(ahead);
+noteof=input(ahead);
+peeked=1;
+return(noteof);
+}
+addch(s, c)
+       char *s;
+{
+while (*s) s++;
+*s++ = c;
+*s = 0;
+}
diff --git a/usr/src/cmd/refer/sample b/usr/src/cmd/refer/sample
new file mode 100644 (file)
index 0000000..9fd5757
--- /dev/null
@@ -0,0 +1,1737 @@
+%A A. V. Aho
+%A C. Beeri
+%A J. D. Ullman
+%T The  Theory of Joins in Relational Databases
+%J Proc. 18th IEEE Symp. on Foundations of Computer Science
+%D 1977
+
+%A A. V. Aho
+%A Y. Sagiv
+%A J. D. Ullman
+%T Equivalence of Relational Expressions
+%O unpublished
+%D 1977
+
+%A W. W. Armstrong
+%T Dependency Structures of Data Base Relationships
+%J Proc. IFIP 74
+%I North Holland
+%D 1974
+%P 580-583
+
+%A P. A. Bernstein
+%A C. Beeri
+%T An Algorithmic Approach to Normalization of Relational Database Schemes
+%R TR CSRG-7B
+%I Computer Science Research Group, University of Toronto
+%D September 1976
+
+%A C. Beeri
+%A R. Fagin
+%A J. H. Howard
+%T A Complete Axiomatization for Functional and Multivalued Dependencies
+%R RJ1977
+%I IBM, San Jose, California
+%D 1977
+
+%A A. K. Chandra
+%A P. M. Merlin
+%T Optimal Implementation of Conjunctive Queries in Relational Data Bases
+%J Proc. 9th ACM Symp. on Theory of Computing
+%D 1976
+%P 77-90
+
+%A E. F. Codd
+%T A Relational Model for Large Shared Data Bases
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 13
+%N 6
+%D June 1970
+%P 377-387
+
+%A E. F. Codd
+%T Further Normalization of the Data Base Relational Model
+%B Data Base Systems
+%E R. Rustin
+%I Prentice Hall
+%C Englewood Cliffs, N. J
+%D 1972
+%P 33-64
+
+%A E. F. Codd
+%T Relational Completeness of Data Base Sublanguages
+%B Data Base Systems
+%E R. Rustin
+%I Prentice-Hall
+%C Englewood Cliffs, N. J
+%D May 1971
+%P 65-98
+
+%A S. A. Cook
+%T The Complexity of Theorem Proving Procedures
+%J Proc. 3rd ACM Symp. on Theory of Computing
+%D May 1971
+%P 151-158
+
+%A C. J. Date
+%T An Introduction to Database Systems
+%I Addison-Wesley
+%C Reading, Mass
+%D 1975
+
+%A C. Delobel
+%T Contributions Theoretiques a la Conception d'un Systeme d'informations
+%O Ph. D. thesis, Univ. of Grenoble, Oct
+%D 1973
+
+%A R. Fagin
+%T Multivalued Dependencies and a New Normal Form for Relational Databases
+%J ACM Trans. Data Base Systems
+%V 2
+%N 3
+%D September 1977
+%P 262-278
+
+%A P. A. V. Hall
+%T Optimization of a Single Relational Expression in a Relational
+Database System
+%J IBM J. Research and Development
+%D May 1976
+%P 244-257
+
+%A R. M. Karp
+%T Reducibility Among Combinatorial Problems
+%B Complexity of Computer Computations
+%E R. E. Miller and J. W. Thatcher
+%I Plenum Press
+%C New York
+%D 1972
+%P 85-104
+
+%A C. L. Lucchesi
+%A S. L. Osborn
+%T Candidate Keys for Relations
+%J J. Comp. Sys. Sci.
+%O (To appear; available from Department of Computer Science, University of Waterloo).
+%D 1976
+
+%A J. Minker
+%T Performing Inferences over Relational Databases
+%R TR363, Department of Computer Science
+%I University of Maryland
+%D March 1975
+
+%A R. M. Pecherer
+%T Efficient Evaluation of Expressions in a Relational Algebra
+%J Proc. ACM Pacific Conf.
+%D April 1975
+%P 44-49
+
+%A F. P. Palermo
+%T A Database Search Problem
+%B Information Systems COINS IV
+%E J. T. Tou
+%I Plenum Press
+%C New York
+%D 1974
+
+%A J. Rissanen
+%T Independent Components of Relations
+%R RJ1899, IBM, San Jose, California
+%D 1977
+
+%A Y. Sagiv
+%A M. Yannakakis
+%T unpublished
+
+%A J. M. Smith
+%A P. Y.\(hyT. Chang
+%T Optimizing the Performance of a Relational Algebra Database Interface
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 18
+%N 10
+%D October 1975
+
+%A M. Stonebraker
+%A L. A. Rowe
+%T Observations on Data Manipulation Languages and their
+Embedding in General Purpose Programming Languages
+%R TR UCB/ERL M77-53
+%D July 1977
+%I University of California, Berkeley
+
+%A E. Wong
+%A K. Youssefi
+%T Decomposition \(em a Strategy for Query Processing
+%J ACM Trans. Data Base Systems
+%V 1
+%N 3
+%D September 1976
+%P 223-241
+
+%A C. Zaniolo
+%T Analysis and Design of Relational Schemata for Database Systems
+%R Tech. Rept. UCLA-ENG-7769
+%I Department of Computer Science, UCLA
+%D July 1976
+
+%A M. M. Zloof
+%T Query-by-Example: the Invocation and Definition of Tables and Forms
+%J Proc. ACM International Conf. on Very Large Data Bases
+%D September 1975
+%P 1-24
+
+%A S. K. Abdali
+%T A lambda calculus model of programming languages \(em I. simple constructs
+%J J. Comp. Languages
+%V 1
+%D 1976
+%P 287-301
+
+%A S. K. Abdali
+%T A lambda calculus model of programming languages \(em II. jumps and procedures
+%J J. Comp. Languages
+%V 1
+%D 1976
+%P 303-320
+
+%A ADJ (J. A. Goguen, J. W. Thatcher, E. G. Wagner and J. B Wright)
+%T A junction between category theory and computer science, I: basic concepts and examples (Part 1)
+%R Report RC 4526
+%I IBM Research
+%C Yorktown Heights, N. Y.
+%K part1
+%D September 1973
+
+%A ADJ (J. A. Goguen, J. W. Thatcher, E. G. Wagner and J. B Wright)
+%T A junction between category theory and computer science, I: basic concepts and examples (Part 2)
+%R Report RC 5908
+%I IBM Research
+%K part2
+%C Yorktown Heights, N. Y.
+%D March 1976
+
+%A L. Ammeraal
+%T How program statements transform predicates
+%R Report IW 39/75
+%I Mathematisch Centrum
+%C Amsterdam
+%D December 1975
+
+%A L. Ammeraal
+%T On forward and backward proof rules for program verification
+%R Report IW 65/76
+%I Mathematisch Centrum
+%C Amsterdam
+%D November 1976
+
+%A E. R. Anderson
+%A F. C. Belz
+%A E. K. Blum
+%T Semanol (73) A metalanguage for programming the semantics of programming languages
+%J Acta Informatica
+%V 6
+%D 1976
+%P 109-131
+
+%A K. R. Apt
+%T Equivalence of operational and denotational semantics for a fragment of Pascal
+%R Report IW 71/76
+%I Mathematisch Centrum
+%C Amsterdam
+%D December 1976
+
+%A K. R. Apt
+%A J. W. de Bakker
+%T Exercises in denotational semantics
+%J Lecture Notes in Computer Science
+%V 45
+%D 1976
+%P 1-11
+
+%A K. R. Apt
+%A J. W. de Bakker
+%T Semantics and proof theory of Pascal procedures
+%J Lecture Notes in Computer Science
+%V 52
+%D 1977
+%P 30-44
+
+%A K. R. Apt
+%A L. G. L. T. Meertens
+%T Completeness with finite systems of intermediate assertions for recursive program schemas
+%R Report IW 84/77
+%I Mathematisch Centrum
+%C Amsterdam
+%D September 1977
+
+%A A. Arnold
+%A M. Nivat
+%T Non deterministic recursive program schemes
+%D 1977
+
+%A A. Arnold
+%A M. Nivat
+%T On nondeterministic program schemes
+%D 1977
+
+%A E. A. Ashcroft
+%A Maurice Clint
+%A C. A. R. Hoare
+%T Remarks on ``Program proving: jumps and functions by M. Clint and C. A. R. Hoare''
+%J Acta Informatica
+%V 6
+%D 1976
+%P 317-318
+
+%A J. W. Backus
+%A R. J. Beeber
+%A S. Best
+%A R. Goldberg
+%A L. M. Haibt
+%A H. L. Herrick
+%A R. A. Nelson
+%A D. Sayre
+%A P. B. Sheridan
+%A H. Stern
+%A I. Ziller
+%A R. A. Hughes
+%A R. Nutt
+%T The Fortran automatic coding system
+%J Western Computer Proceedings
+%D 1957
+%P 188-198
+
+%A J. P. Banatre
+%T Producing optimised code for coercions
+%J Information Processing Letters
+%V 6
+%N 2
+%D April 1977
+%P 56-59
+
+%A Henk Barendregt
+%T A global representation of the recursive functions in the $lambda -$claculus
+%J Theor. Comp. Sci.
+%V 3
+%D 1976
+%P 225-242
+
+%A H. Bekic
+%T Towards a mathematical theory of processes
+%R TR 25.125
+%I IBM Laboratory
+%C Vienna
+%D December 1971
+
+%A G. Berry
+%T Bottom-up computation of recursive programs
+%R Rapport de Recherche No 133
+%I IRIA
+%C Rocquencourt, France
+%D September 1975
+
+%A Gerard Berry
+%A Bruno Courcelle
+%T Program equivalence and canonical forms in stable discrete interpretations
+%E S. Michaelson and R. Milner
+%B Automata Languages and Programming , Third International Colloquium
+%I Edinburgh University Press
+%D July 1976
+%P 168-188
+
+%A Gerard Berry
+%A J. J. Levy
+%T Minimal and optimal computations of recursive programs
+%J J. Assoc. Comp. Mach.
+%K acm jacm
+%D to appear
+
+%A Richard Bird
+%T Programs and Machines
+%I John Wiley
+%C New York, N. Y.
+%D 1976
+
+%A A. Blikle
+%T Programs with subscripted variables
+%J Bulletin de L'Academie Polonaise des Sciences, Serie des sciences math., astr. et phys.
+%V XIX
+%N 9
+%D 1971
+%P 853-857
+
+%A C. Bohm
+%T The CUCH as a formal and description language
+%E T. B. Steel, Jr.
+%B Formal language description languages for computer programming
+%I North-Holland
+%C Amsterdam
+%D 1966
+%P 179-197
+
+%A H. J. Boom
+%T Extended type checking
+%R Report IW 60/76
+%I Mathematisch Centrum
+%C Amsterdam
+%D September 1976
+
+%A S. R. Bourne
+%A A. D. Birrell
+%A I. Walker
+%T Algol 68C Reference Manual
+%I Computer Laboratory, Cambridge University
+%C Cambridge, England
+%D 1975
+
+%A R. S. Boyer
+%A J. S. Moore
+%T A computer proof of the correctness of a simple optimizing compiler for expressions
+%R Tech. Rep. 5
+%I SRI
+%C Menlo Park, Ca.
+%D January 1977
+
+%A J. M. Boyle
+%A A. A. Grau
+%T An algorithmic semantics for Algol 60 identifier denotation
+%J J. Assoc. Comp. Mach.
+%K acm jacm
+%V 17
+%N 2
+%D April 1970
+%P 361-382
+
+%A R. M. Burstall
+%T Semantics of assignment
+%E Ella Dale and Donald Michie
+%B Machine Intelligence 2
+%I American Elsevier
+%C New York
+%D 1968
+%P 3-20
+
+%A R. M. Burstall
+%T Proving properties of programs by structural induction
+%J Comp. J.
+%P 41-48
+
+%A R. M. Burstall
+%T Some techniques for proving properties of programs which alter data structures
+%B Machine Intelligence
+
+%A E. M. Clarke, Jr.
+%T Program invariants as fixed points
+%J Proc. 18th IEEE Symp. on Foundations of Computer Science
+%D October 1977
+%P 18-29
+
+%A Maurice Clint
+%T Program proving: coroutines
+%J Acta Informatica
+%V 2
+%N 1
+%D 1973
+%P 50-63
+
+%A Maurice Clint
+%A C. A. R. Hoare
+%T Program proving:jumps and functions
+%J Acta Informatica
+%V 1
+%D 1972
+%P 214-224
+%O see also Ashcroft, Clint and Hoare (1976)
+
+%A S. A. Cook
+%T Soundness and completeness of an axiom system for program verification
+%J SIAM J. Computing
+%D to appear
+
+%A S. A. Cook
+%A D. C. Oppen
+%T An assertion language for data structures
+%J Proc. 2nd ACM Symp. on Principles of Programming Languages
+%D January 1975
+%P 160-166
+
+%A D. C. Cooper
+%T Program scheme equivalences and second-order logic
+%B Machine Intelligence
+%P 3-15
+
+%A Bruno Courcelle
+%T On the definition of classes of interpretations
+%R Rapport de Recherche No 231
+%I IRIA
+%C Rocquencourt, France
+%D May 1977
+
+%A B. Courcelle
+%A I. Guessarian
+%T On some classes of interpretations
+%R Rapport de Recherche No 253
+%I IRIA
+%C Rocquencourt, France
+%D September 1977
+
+%A Bruno Courcelle
+%A Jean Vuillemin
+%T Completeness results for the equivalence of recursive schema
+%J J. Comp. Sys. Sci.
+%V 12
+%D 1976
+%P 179-197
+
+%A Karel Culik II
+%T A model for the formal definition of programming languages
+%J Int. J. Comp. Math.
+%V 3
+%D 1973
+%P 315-345
+
+%A R. J. Cunningham
+%A M. E. J. Guilford
+%T A note on the semantic definition of side effects
+%J Information Processing Letters
+%V 4
+%N 5
+%D February 1976
+%P 118-120
+
+%A Ole-Johan Dahl
+%A Bjorn Myhrhaug
+%A Kristen Nygaard
+%T Simula 67: common base language
+%R Publication S-22
+%I Norwegian Computing Centre
+%C Oslo, Norway
+%D October 1970
+
+%A J. W. de Bakker
+%T Semantics of programming languages
+%E J. T. Tou
+%B Advances in Information Systems Science, Vol. 2
+%I Plenum Press
+%C New York, N. Y.
+%D 1969
+%P 173-227
+
+%A J. W. de Bakker
+%T Recursive Procedures
+%I Mathem\ 1atical Centre Tracts 24, Mathematisch Centrum
+%C Amsterdam
+%D 1971
+
+%A J. W. de Bakker
+%T Recursion, induction and symbol manipulation
+%B Informatica Symposium 1971
+%I Mathematisch Centre Tracts 25, Mathematisch Centrum
+%D 1971
+
+%A J. W. de Bakker
+%T Axiom systems for simple assignment statements
+%J Lecture Notes in Mathematics
+%V 188
+%D 1971
+%P 1-22
+
+%A J. W. de Bakker
+%T A property of linear conditionals
+%J Lecture Notes in Mathematics
+%V 188
+%D 1971
+%P 23-27
+
+%A J. W. de Bakker
+%T The fixpoint approach in semantics: theory and applications
+%E J. W. de Bakker
+%B Foundations of Computer Science
+%I Mathematical Centre Tracts 63
+%C Amsterdam
+%D 1975
+%P 3-53
+
+%A J. W. de Bakker
+%T Least fixed points revisited
+%J Theor. Comp. Sci.
+%V 2
+%D 1976
+%P 155-181
+
+%A J. W. de Bakker
+%A J. W. de Bakker
+%T Fixed point semantics and Dijkstra's fundamental invariance theorem
+%R Report IW 29/76
+%I Mathematisch centrum
+%C Amsterdam
+%D January 1976
+
+%A J. W. de Bakker
+%T Correctness proofs for assignment statements
+%R Report IW 55/76
+%I Mathematisch Centrum
+%C Amsterdam
+%D 1976
+
+%A J. W. de Bakker
+%T Semantics and the foundations of program proving
+%E B. Gilchrist
+%B Information Processing 77
+%I North-Holland
+%C Amsterdam
+%D 1977
+%P 279-284
+
+%A J. W. de Bakker
+%T Recursive programs as predicate transformers
+%E E. Neuhold
+%B IFIP Working Conference on the Formal Description of Programming Concepts
+%I North-Holland
+%C Amsterdam
+%D to appear
+
+%A J. W. de Bakker
+%A L. G. L. T. Meertens
+%T On the completeness of the inductive assertion method
+%J J. Comp. Sys. Sci.
+%V 11
+%D 1975
+%P 323-357
+
+%A J. W. de Bakker
+%A Dana Scott
+%T A theory of programs
+%R unpublished
+%D August 1969
+
+%A Mariangiola Dezani-Ciancaglini
+%A Maddalena Zacchi
+%T Application of Church-Rosser properties to increase the parallelism and efficiency of algorithms
+%J Lecture Notes in Computer Science
+%V 14
+%D 1974
+
+%A E. W. Dijkstra
+%T A Discipline of Programming
+%I Prentice Hall
+%C Englewood Cliffs, N. J.
+%D 1976
+
+%A J. E. Donahue
+%T The mathematical semantics of axiomatically defined programming language constructs
+%E G. Huet and G. Kahn
+%B Proving and Improving Programs
+%I IRIA
+%C Rocquencourt, France
+%D July 1975
+%P 353-367
+
+%A J. E. Donahue
+%T Complementary Definitions of Programming Language Semantics
+%J Lecture Notes in Computer Science
+%V 42
+%D 1976
+
+%A J. E. Donahue
+%T Locations considered unnecessary
+%J Acta Informatica
+%V 8
+%D 1977
+%P 221-242
+
+%A H. Egli
+%T A mathematical model for non-deterministic computations
+%D September 1975
+
+%A Herbert Egli
+%A Robert L. Constable
+%T Computability concepts for programming language semantics
+%J Theor. Comp. Sci.
+%V 2
+%D 1976
+%P 133-145
+
+%A G. W. Ernst
+%T Rules of inference for procedure calls
+%J Acta Informatica
+%V 8
+%D 1977
+%P 145-152
+
+%A R. W. Floyd
+%T Assigning meanings to programs
+%E J. T. Schwartz
+%B Mathematical Aspects of Computer Science, Proceedings of a Symposium in Applied Mathematics, Vol. 19
+%I American Math. Soc.
+%C Providence, R. I.
+%D 1967
+%P 19-32
+
+%A Nissim Francez
+%A Boris Klebansky
+%A Amir Pnueli
+%T Backtracking in recursive computations
+%J Acta Informatica
+%V 8
+%D 1977
+%P 125-144
+
+%A Jan V. Garwick
+%T The definition of programming languages by their compilers
+%E T. B. Steel, Jr.
+%B Formal Language Description Languages for Computer Programming
+%I North-Holland
+%C Amsterdam
+%D 1966
+%P 139-147
+
+%A Michael Gordon
+%T Operational reasoning and denotational semantics
+%E G. Huet and G. Kahn
+%B Proving and Improving Programs
+%I IRIA
+%C Rocquencourt, France
+%D July 1975
+%P 83-98
+
+%A G. A. Gorelick
+%T A complete axiomatic system for proving assertions about recursive and nonrecursive programs
+%R Tech. Rep. 75
+%I Department of Computer Science, University of Toronto
+%D January 1975
+
+%A David Gries
+%T Assignment to subscripted variables
+%R TR 77-305
+%I Department of Computer Science, Cornell University
+%D September 1976
+
+%A David Gries
+%T An illustration of current ideas on the derivation of correctness proofs and correct programs
+%J IEEE Trans. on Software Engineering
+%V SE-2
+%N 4
+%D December 1976
+%P 238-244
+
+%A David Gries
+%A Narain Gehani
+%T Some ideas on data types in high level languages
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 20
+%N 6
+%D July 1976
+%P 414-420
+
+%A D. Grune
+%T A view of coroutines
+%R Report IW 63/76
+%I Mathematisch Centrum
+%C Amsterdam
+%D November 1976
+
+%A Irene Guessarian
+%T Semantic equivalence of program schemes and its syntactic characterization
+%E S. Michaelson and R. Milner
+%B Automata, Languages and Programming, Third International Colloquium
+%I Edinburgh University Press
+%D July 1976
+%P 189-200
+
+%A I. Guessarian
+%T Sur quelques applications de la semantique algebrique des schemas recursifs polyadiques
+%D 1977
+
+%A John Guttag
+%T Abstract data types and the development of data structures
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 20
+%N 6
+%D July 1976
+%P 396-404
+
+%A J. V. Guttag
+%A Ellis Horowitz
+%A D. R. Musser
+%T Abstract data types and software validation
+%R Report ISI/RR-76-48
+%I Information Sciences Institute, University of Southern California
+%C Los Angeles, Ca.
+%D August 1976
+
+%A J. V. Guttag
+%A Ellis Horowitz
+%A D. R. Musser
+%T The design of data type specifications
+%R Report ISI/RR-76-49
+%I Information Sciences Institute, Univeristy of Southern California
+%C Los Angeles, Ca.
+%D November 1976
+
+%A D. Harel
+%T Arithmetical completeness in logics of programs
+%D September 1977
+
+%A David Harel
+%T On the correctness of regular deterministic programs; a unifying survey
+%D November 1977
+
+%A D. Harel
+%T Complete axiomatization of properties of recursive programs (extended abstract)
+%D November 1977
+
+%A David Harel
+%A Amir Pnueli
+%A Jonathan Stavi
+%T A complete axiomatic system for proving deductions about recursive programs
+%J Ninth ACM Symp. Theory of Computing
+%D May 1977
+%P 249-260
+
+%A D. Harel
+%A V. R. Pratt
+%T Nondeterminism in logics of programs
+%J Proc. 5th ACM Symp. on Principles of Programming Languages
+%D January 1978
+
+%A William Harrison
+%T Formal semantics of a schematic intermediate language
+%R Report RC 6271
+%I IBM Research
+%C Yorktown Heights, N. Y.
+%D November 1976
+
+%A R. Haskell
+%T Efficient implementation of a class of recursively defined functions
+%J Comp. J.
+%V 18
+%N 1
+%D 1975
+%P 23-29
+
+%A Peter Henderson
+%A J. H. Morris, Jr.
+%T A lazy evaluator
+%J Proc. 3rd ACM Symp. on Principles of Programming Languages
+%D January 1976
+%P 95-103
+
+%A M. C. B. Hennessy
+%T Parameter passing mechanisms and non-determinism
+
+%A M. C. B. Hennessy
+%A E. A. Ashcroft
+%T The semantics of nondeterminism
+%R Report CS-76-17
+%I Department of Computer Science, University of Waterloo
+%D April 1976
+
+%A C. A. R. Hoare
+%T An axiomatic basis for computer programming
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 12
+%N 10
+%D October 1969
+%P 576-580,583
+
+%A C. A. R. Hoare
+%T Procedures and parameters: an axiomatic approach
+%J Lecture Notes in Mathematics
+%V 188
+%D 1971
+%P 102-116
+
+%A C. A. R. Hoare
+%T Proof of correctness of data representations
+%J Acta Informatica
+%V 1
+%D 1972
+%P 271-281
+
+%A C. A. R. Hoare
+%T Hints on programming language design
+%O Invited address at ACM Symposium on Principles of Programming Languages.
+%D October 1973
+
+%A C. A. R. Hoare
+%T Some properties of non-deterministic computations
+
+%A C. A. R. Hoare
+%A P. E. Lauer
+%T Consistent and complementary formal theories of the semantics of programming languages
+%J Acta Informatica
+%V 3
+%D 1974
+%P 135-153
+
+%A C. M. Hoffman
+%T Design and correctness of a compiler for Lucid
+%R Research Report CS-76-20
+%I Computer Science Department, University of Waterloo
+%D May 1976
+
+%A C. M. Hoffman
+%A L. H. landweber
+%T A completeness theorem for straight-line programs with structured variables
+%J J. Assoc. Comp. Mach.
+%K acm jacm
+%V 23
+%N 1
+%D January 1976
+%P 203-220
+
+%A Chiharu Hosono
+%A Masahiko Sato
+%T The retracts in $P omega$ do not form a continuous lattice \(em a solution to Scott's problem
+%J Theor. Comp. Sci.
+%V 4
+%D 1977
+%P 137-142
+
+%A Gerard Huet
+%T Confluent Reductions: Abstract Properties and Applications to Term Rewriting Systems
+%J Proc. 18th IEEE Symp. on Foundations of Computer Science
+%D October 1977
+%P 30-45
+
+%A Gerard Huet
+%A Bernard Lang
+%T Program transformations in classes of interpretations
+%O Lecture Notes
+%D May 1976
+
+%A Shigeru Igarashi
+%T Semantics of Algol-like statements
+%J Lecture Notes in Mathematics
+%V 188
+%D 1971
+%P 117-177
+
+%A Shigeru Igarashi
+%A R. L. London
+%A D. C. Luckham
+%T Automatic program verification I: a logical basis and its implementation
+%J Acta Informatica
+%V 4
+%D 1975
+%P 145-182
+
+%A Kurt Jensen
+%T An investigation into different semantic approaches
+%R Report DAIMI PB-61
+%I Department of Computer Science, University of Aarhus
+%D June 1976
+
+%A Gilles Kahn
+%T An approach to systems correctness
+
+%A Gilles Kahn
+%T The semantics of a simple language for parallel programming
+%E J. L. Rosenfeld
+%B Information Processing 74
+%I North-Holland
+%C Amsterdam
+%D 1974
+%P 471-475
+
+%A Gilles Kahn
+%A D. B. MacQueen
+%T Coroutines and networks of parallel processes
+%E B. Gilchrist
+%B Information Processing 77
+%I North-Holland
+%C Amsterdam
+%D 1977
+%P 993-998
+
+%A D. M. Kaplan
+%T Some completeness results in the mathematical theory of computation
+%J J. Assoc. Comp. Mach.
+%K acm jacm
+%V 15
+%N 1
+%D January 1968
+%P 124-134
+
+%A R. M. Keller
+%T Denotational models for parallel programs with indeterminate operators
+%E E. Neuhold
+%B IFIP Working Conference on the Formal Description of Programming Concepts
+%I North-Holland
+%C Amsterdam
+%D to appear
+
+%A D. E. Knuth
+%A P. B. Bendix
+%T Simple word problems in universal algebras
+%E J. Leech
+%B Computational Problems in Abstract Algebra
+%I Pergamon Press
+%C Oxford
+%D 1970
+%P 263-297
+
+%A D. E. Knuth
+%A L. Trabb Pardo
+%T Early development of programming languages
+%B Encyclopedia of Computer Science and Technology, Vol. 7
+%I Marcel Dekker
+%C New York, N. Y.
+%D 1977
+%P 419-493
+%R STAN-CS-76-562
+
+%A J. Kral
+%T On the equivalence of modes and the equivalence of finite automata
+%J ALGOL Bulletin
+%N 35
+%D March 1973
+%P 34-35
+
+%A P. J. Landin
+%T The mechanical evaluation of expressions
+%J Comp. J.
+%V 6
+%N 4
+%D January 1964
+%P 308-320
+
+%A P. J. Landin
+%T A correspondence between Algol 60 and Church's lambda-notation
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 8
+%N 2,3
+%D February and March 1965
+%P 89-101 and 158-165
+
+%A P. J. Landin
+%T A formal description of Algol 60
+%E T. B. Steel, Jr.
+%B Formal Language Description Languages for Computer Programming
+%I North-Holland
+%C Amsterdam
+%D 1966
+%P 266-294
+
+%A P. J. Landin
+%T The next 700 programming languages
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 9
+%N 3
+%D March 1966
+%P 157-166
+
+%A P. J. Landin
+%T A $lambda -$calculus approach
+%E L. Fox
+%B Advances in Programming and Non-numerical Computation
+%I Pergammon Press
+%C Oxford
+%D 1966
+%P 97-141
+
+%A Hans Langmaack
+%T On correct procedure parameter transmission in higher programming languages
+%J Acta Informatica
+%V 2
+%D 1973
+%P 110-142
+
+%A D. Lankford
+%T On deciding word problems by rewrite rule simplifiers
+%D September 1977
+
+%A H. F. Ledgard
+%T A model for type checking \(em with an application to Algol 60
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 15
+%N 11
+%D November 1972
+%P 956-
+
+%A J. A. N. Lee
+%T The formal definition of the Basic language
+%J Comp. J.
+%V 15
+%N 1
+%D February 1972
+%P 37-41
+
+%A D. J. Lehmann
+%A M. B. Smyth
+%T Data types
+%J Proc. 18th IEEE Symp. on Foundations of Computer Science
+%D October 1977
+%P 7-12
+
+%A G. T. Ligler
+%T Proof rules, mathematical semantics and programming language design
+%D 1975
+
+%A G. T. Ligler
+%T Surface properties of programming language constructs
+%J Theor. Comp. Sci.
+%D to appear
+
+%A R. J. Lipton
+%T A necessary and sufficient condition for the existence of Hoare logics
+%J Proc. 18th IEEE Symp. on Foundations of Computer Science
+%D October 1977
+%P 1-6
+
+%A R. L. London
+%T A bibliography on proving the correctness of programs
+%E B. Meltzer
+%E D. Michie
+%B Machine Intelligence 5
+%I Edinburgh University Press, Edinburgh, and American Elsevier, New York, N. Y.
+%D 1970
+%P 569-580
+
+%A R. L. London
+%A M. Shaw
+%A W. A. Wulf
+%T Abstraction and verification in Alphard: a symbol table example
+%D December 1976
+
+%A Peter Lucas
+%T On the semantics of programming languages and software devices
+%E R. Rustin
+%B Formal Semantics of Programming Languages
+%I Prentice-Hall
+%C Englewood Cliffs, N. J.
+%D 1972
+%P 41-57
+
+%A P. Lucas
+%T Formal definition of programming languages and systems
+%B Information Processing 71
+%I North-Holland
+%C Amsterdam
+%D 1971
+%P 291-297
+
+%A Peter Lucas
+%A Kurt Walk
+%T On the formal definition of PL/I
+%J Annual Review of Automatic Programming
+%V 6
+%N 3
+%D 1970
+%P 105-182
+
+%A D. C. Luckham
+%A D. M. R. Park
+%A M. S. Paterson
+%T On formalized computer programs
+%J J. Comp. Sys. Sci.
+%V 4
+%D 1970
+%P 220-249
+
+%A D. C. Luckham
+%A Norihisa Suzuki
+%T Automatic program verification V: verification oriented proof rules for arrays, records and pointers
+%R Report STAN-CS-76-549
+%D March 1976
+
+%A D. C. Luckham
+%A Norihisa Suzuki
+%T Proof of termination within a weak logic of programs
+%J Acta Informatica
+%V 8
+%D 1977
+%P 21-36
+
+%A M. E. Majster
+%T Extended data graphs, a formalism for structured data and data structures
+%J Acta Informatica
+%V 8
+%D 1977
+%P 37-59
+
+%A Zohar Manna
+%A Stephen Ness
+%A Jean Vuillemin
+%T Inductive methods for proving properties of programs
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 16
+%N 8
+%D August 1973
+%P 491-502
+
+%A Zohar Manna
+%A Jean Vuillemin
+%T Fixpoint approach to the theory of computation
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 15
+%N 7
+%D July 1972
+%P 528-536
+
+%A George Markowsky
+%T categories of chain-complete posets
+%J Theor. Comp. Sci.
+%V 4
+%D 1977
+%P 125-135
+
+%A G Markowsky
+%A B. K. Rosen
+%T Bases for chain-complete posets
+%J IBM J. Research and Development
+%V 20
+%N 2
+%D March 1976
+%P 138-147
+
+%A W. D. Maurer
+%T Induction principles for context-free languages
+%J Lecture Notes in Computer Science
+%V 1
+%D 1973
+%P 134-143
+
+%A John McCarthy
+%T Recursive functions of symbolic expressions and their computation by machine, part I
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 3
+%N 4
+%D April 1960
+%P 184-195
+
+%A John McCarthy
+%T Towards a mathematical science of computation
+%E C. M. Popplewell
+%B Information Processing 1962
+%I North-Holland
+%C Amsterdam
+%D 1963
+%P 21-28
+
+%A John McCarthy
+%T A basis for a mathematical theory of computation
+%E P. Braffort and D. Hirschberg
+%B Computer Programming and Formal Systems
+%I North-Holland
+%C Amsterdam
+%D 1963
+%P 33-70
+
+%A John McCarthy
+%T A formal description of a subset of Algol
+%E T. B. Steel, Jr.
+%B Formal Language Description Languages for Computer Programming
+%I North-Holland
+%C Amsterdam
+%D 1966
+%P 1-12
+
+%A John McCarthy
+%A James Painter
+%T Correctness of a compiler for arithmetic expressions
+%E J. T. Schwartz
+%B Proceedings of Symposia in Applied Mathematics, Volume XIX
+%I American Math. Society
+%C Providence, R. I.
+%D 1967
+%P 33-41
+
+%A M. D. McIlroy
+%T Coroutines
+%D 1968
+
+%A Robert Milne
+%T Verifying the correctness of implementations
+%D 1977
+
+%A R. E. Milne
+%T Transforming predicate transformers
+%E E. Neuhold
+%B IFIP Working Conference on the Formal Description of Programming Concepts
+%I North-Holland
+%C Amsterdam
+%D to appear
+
+%A Robin Milner
+%T Models in LCF
+%R Report STAN-CS-73-332
+%I Computer Science Department, Stanford University
+%D January 1973
+
+%A R. Milner
+%T Processes; a model of computing agents
+
+%A R. Milner
+%T Program semantics and mechanized proof
+%I Mathematical Centre Tracts 82
+%D 1976
+%P 3-44
+
+%A R. Milner
+%T LCF; a methodology for performing rigorous proofs about programs
+%B First IBM Symposium on Mathematical Foundations of Computer Science
+%I Academic and Scientific Programs, IBM Japan
+%C Tokyo
+%D October 1976
+
+%A J. H. Morris, Jr.
+%T Another recursion induction principle
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 14
+%N 5
+%D May 1971
+%P 351-354
+
+%A P. D. Mosses
+%T The mathematical semantics of Algol 60
+%R Technical Monograph PRG-12
+%I Programming Research Group, Oxford University
+%D 1974
+
+%A P. D. Mosses
+%T The semantics of semantic equations
+%J Lecture Notes in Computer Science
+%V 28
+%D 1975
+%P 409-422
+
+%A P. D. Mosses
+%T Compiler generation using denotational semantics
+%J Lecture Notes in Computer Science
+%V 45
+%D 1976
+%P 436-441
+
+%A P. D. Mosses
+%T Making denotational semantics less concrete
+%D 1977
+
+%A Maurice Nivat
+%T On some families of languages related to the Dyck language
+%J Proc. 2nd ACM Symp. on Theory of Computing
+%D May 1970
+%P 221-225
+
+%A M. Nivat
+%T On the interpretation of recursive program schemes
+%R Rapport de Recherche No 84
+%I IRIA
+%C Rocquencourt, France
+%D October 1974
+
+%A Mike O'Donnell
+%T Subtree replacement systems: a unifying theory for recursive equations, Lisp, Lucid and combinatory logic
+%J Ninth ACM Symp. Theory of Computing
+%D May 1977
+%P 295-305
+
+%A D. C. Oppen
+%A S. A. Cook
+%T Proving assertions about programs that manipulate data structures
+%J Proc. 7th ACM Symp. on Theory of Computing
+%D May 1975
+%P 107-116
+
+%A B. A. Othmer
+%T Programming language data structures: a comparative study
+%R Tech. Rep. No. 30
+%I Department of Computer Science, Rutgers University
+%D March 1974
+
+%A G. Pacini
+%T An optimal fix-point computation rule for a simple recursive language
+%R Nota Interna B73-10
+%I Consiglio Nazionale delle Ricerche, Istituto di Elaborazione della Informazione
+%C Pisa
+%D October 1973
+
+%A G. Pacini
+%A C. Montangero
+%A F. Turini
+%T Graph representation and computation rules for typeless recursive languages
+%J Lecture Notes in Computer Science
+%V 14
+%D 1974
+%P 158-169
+
+%A F. G. Pagan
+%T On interpreter oriented definitions of programming languages
+%J Comp. J.
+%V 19
+%N 2
+%D 1976
+%P 151-155
+
+%A David Park
+%T Some semantics for data structures
+%E D. Michie
+%B Machine Intelligence 3
+%I American Elsevier
+%C New York, N. Y.
+%D 1968
+%P 351-371
+
+%A David Park
+%T Fixpoint induction and proofs of program properties
+%B Machine Intelligence 5
+%D 1970
+%P 59-78
+
+%A David Park
+%T Finiteness is mu-ineffable
+%J Theor. Comp. Sci.
+%V 3
+%D 1976
+%P 173-181
+
+%A Helmut Partsch
+%A Peter Pepper
+%T A family of rules for recursion removal
+%J Information Processing Letters
+%V 5
+%N 6
+%D December 1976
+%P 174-177
+
+%A G. D. Plotkin
+%T A set-theoretical definition of application
+%R Memorandum MIP-R-95
+%I School of Artificial Intelligence, University of Edinburgh
+%D March 1972
+
+%A G. D. Plotkin
+%T Lambda-definability and logical relations
+%R Memorandum SAI-RM-4
+%I School of Artificial Intelligence, University of Edinburgh
+%D October 1973
+
+%A G. D. Plotkin
+%T Call-by-name, call-by-value and the $lambda -$calculus
+%J Theor. Comp. Sci.
+%V 1
+%D 1975
+%P 125-159
+
+%A A. Pnueli
+%T The temporal logic of programs
+%J Proc. 18th IEEE Symp. on Foundations of Computer Science
+%D October 1977
+%P 46-57
+
+%A V. R. Pratt
+%T Semantical considerations in Floyd-Hoare logic
+%J Proc. 17th IEEE Symp. on Foundations of Computer Science
+%D October 1976
+%P 109-121
+
+%A J. C. Raoult
+%A J. Vuillemin
+%T Operational and semantic equivalence between recursive programs
+%D 1977
+
+%A J. C. Reynolds
+%T Relational and continuation semantics for a simple imperative language
+%B Seminaires IRIA: theorie des algorithmes, des langages et de la programmation
+%D 1974
+%P 51-58
+
+%A J. C. Reynolds
+%T On the relation between direct and continuation semantics
+%J Lecture Notes in Computer Science
+%V 14
+%D 1974
+%P 141-156
+
+%A J. C. Reynolds
+%T Formal semantics
+%O preliminary draft for Cosers
+%D June 1976
+
+%A J. C. Reynolds
+%T Semantics of the domain of flow diagrams
+%J J. Assoc. Comp. Mach.
+%K acm jacm
+%V 24
+%N 3
+%D July 1977
+%P 484-503
+
+%A H. G. Rice
+%T Recursion and iteration
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 8
+%N 2
+%D February 1965
+%P 114-115
+
+%A J. S. Rohl
+%T Converting a class of recursive procedures into non-recursive ones
+%J Software \(em Practice and Experience
+%V 7
+%D 1977
+%P 231-238
+
+%A B. D. Russell
+%T Implementation correctness involving a language with goto statements
+%J SIAM J. Computing
+%V 6
+%N 3
+%D September 1977
+%P 403-415
+
+%A Bruce Russell
+%T On an equivalence between continuation and stack semantics
+%J Acta Informatica
+%V 8
+%D 1977
+%P 113-123
+
+%A Andrzej Salwicki
+%T Procedures, formal computations and models
+%J Lecture Notes in Computer Science
+%V 28
+%D 1975
+%P 464-484
+
+%A J. G. Sanderson
+%T The lambda calculus, lattice theory and reflexive domains
+%D 1973
+
+%A E. Sciore
+%A A. Tang
+%T Computability theory in admissible domains
+%D 1977
+
+%A Dana Scott
+%T Outline of a mathematical theory of computation
+%J Proc. 4th Princeton Conf. on Information Sciences and Systems
+%D March 1970
+%P 169-176
+
+%A Dana Scott
+%T The lattice of flow diagrams
+%J Lecture Notes in Mathematics
+%V 188
+%D 1971
+%P 311-366
+
+%A Dana Scott
+%T Continuous lattices
+%E F. W. Lawvere
+%B Toposes, Algebraic Geometry and Logic
+%I Lecture Notes in Mathematics 274, Springer Verlag
+%C Berlin
+%D 1972
+%P 97-136
+
+%A Dana Scott
+%T Mathematical concepts in programming language semantics
+%J Proc. AFIPS SJCC
+%D 1972
+%P 225-234
+
+%A Dana Scott
+%T A simplified construction for $lambda -$calculus models
+%C Uppsala
+%D April 1973
+
+%A Dana Scott
+%T Data types as lattices
+%J SIAM J. Computing
+%V 5
+%N 3
+%D September 1976
+%P 522-587
+
+%A Dana Scott
+%T Logic and programming languages
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 20
+%N 9
+%D September 1977
+%P 634-640
+
+%A Dana Scott
+%A Christopher Strachey
+%T Towards a mathematical semantics for computer languages
+%B Proceedings of the Symposium on Computers and Automata
+%I Polytechnic Press
+%C Brooklyn, N. Y.
+%D April 1971
+%P 19-46
+
+%A Adi Shamir
+%A W. W. Wadge
+%T Data types as objects
+%J Lecture Notes in Computer Science
+%V 52
+%D 1977
+%P 465-479
+
+%A M. Shaw
+%A W. A. Wulf
+%A R. L. London
+%T Abstraction and verification in Alphard: iteration and generators
+%R Report ISI/RR-76-47
+%I Information Sciences Institute, University of Southern California
+%C Los Angeles
+%D August 1976
+
+%A M. B. Smyth
+%T Powerdomains
+%D 1977
+
+%A M. B. Smyth
+%A G. D. Plotkin
+%T The category-theoretic solution of recursive domain equations
+%J Proc. 18th IEEE Symp. on Foundations of Computer Science
+%D October 1977
+%P 13-17
+
+%A J. E. Stoy
+%T The congruence of two programming language definitions
+%J Theor. Comp. Sci.
+%D to appear
+
+%A Christopher Strachey
+%T Towards a formal semantics
+%E T. B. Steel, Jr.
+%B Formal Language Description Languages for Computer Programming
+%I North-Holland
+%C Amsterdam
+%D 1966
+%P 198-220
+
+%A Christopher Strachey
+%T Varieties of programming language
+%B International Computing Symposium Proceedings
+%I Cini Foundation
+%C Venice
+%D April 1972
+%P 222-233
+
+%A Christopher Strachey
+%A Christopher Wadsworth
+%T Continuations: a mathematical semantics which can deal with full jumps
+%R Technical Monograph PRG-11
+%I Programming Research Group, Oxford University
+%D 1974
+
+%A A. Tang
+%T Chain properties in P$omega$
+%D 1977
+
+%A Alfred Tarski
+%T A lattice-theoretical fixpoint theorem and its applications
+%J Pacific J. Math.
+%V 5
+%N 2
+%D June 1955
+%P 285-309
+
+%A R. D. Tennent
+%T Mathematical semantics of Snobol 4
+%J Proc. ACM Symp. on Principles of Programming Languages
+%D October 1973
+%P 95-107
+
+%A R. D. Tennent
+%T The denotational semantics of programming languages
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 19
+%N 8
+%D August 1976
+%P 437-453
+
+%A R. D. Tennent
+%T Language design methods based on semantic principles
+%J Acta Informatica
+%V 8
+%D 1977
+%P 97-112
+
+%A R. D. Tennent
+%T A denotational definition of the programming language Pascal
+%R Tech. Rep. 77-47
+%I Department of Computing and Information Science, Queen's University
+%C Kingston, Ontario
+%D July 1977
+
+%A A. van Wijngaarden
+%T Recursive definition of syntax and semantics
+%E T. B. Steel, Jr.
+%B Formal Language Description Languages for Computer Programming
+%I North-Holland
+%C Amsterdam
+%D 1966
+%P 13-24
+
+%A S. A. Walker
+%A H. R. Strong, Jr.
+%T Characterizations of flowchartable recursions
+%J J. Comp. Sys. Sci.
+%V 7
+%N 4
+%D August 1973
+%P 404-447
+
+%A Mitchell Wand
+%T A characterization of weakest preconditions
+%J J. Comp. Sys. Sci.
+%V 15
+%D 1977
+%P 209-212
+
+%A Ben Wegbreit
+%T Procedure closure in EL1
+%J Comp. J.
+%V 17
+%N 1
+%D February 1974
+%P 38-43
+
+%A Ben Wegbreit
+%T The treatment of data types in EL1
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 17
+%N 5
+%D May 1974
+%P 251-264
+
+%A Ben Wegbreit
+%T Constructive methods in program verification
+%J IEEE Trans. on Software Engineering
+%V SE-3
+%N 3
+%D May 1977
+%P 193-209
+
+%A W. A. Wulf
+%A R. L. London
+%A Mary Shaw
+%T An introduction to the construction and verification of Alphard programs
+%J IEEE Trans. on Software Engineering
+%V SE-2
+%N 4
+%D December 1976
+%P 253-265
+
diff --git a/usr/src/cmd/refer/shell.c b/usr/src/cmd/refer/shell.c
new file mode 100644 (file)
index 0000000..ed18064
--- /dev/null
@@ -0,0 +1,24 @@
+shell (n, comp, exch)
+       int (*comp)(), (*exch)();
+/* SORTS UP.  IF THERE ARE NO EXCHANGES (IEX=0) ON A SWEEP
+  THE COMPARISON GAP (IGAP) IS HALVED FOR THE NEXT SWEEP */
+{
+       int igap, iplusg, iex, i, imax;
+       igap=n;
+while (igap > 1)
+       {
+       igap /= 2;
+       imax = n-igap;
+       do
+               {
+               iex=0;
+               for(i=0; i<imax; i++)
+                       {
+                       iplusg = i + igap;
+                       if ((*comp) (i, iplusg) ) continue;
+                       (*exch) (i, iplusg);
+                       iex=1;
+                       }
+               } while (iex>0);
+       }
+}
diff --git a/usr/src/cmd/refer/test b/usr/src/cmd/refer/test
new file mode 100644 (file)
index 0000000..74a0e11
--- /dev/null
@@ -0,0 +1,60 @@
+.LP
+hoboken harrison newark roseville avenue grove street
+.[
+Aho Ullman subsequence 1976
+.]
+east orange brick church orange highland avenue
+mountain station south orange maplewood millburn short hills
+.[
+Kernighan software tools 1975
+.]
+summit chatham madison convent station morristown
+new providence murray hill berkeley heights
+gillette stirling millington lyons basking ridge
+.[
+Kernighan typesetting guide second
+.]
+bernardsville far hills peapack gladstone
+.LP
+Each person to whom this notice is addressed is entitled to submit,
+.[
+Kernighan tools 1975
+.]
+or request the Department of Labor to submit, to the District Director
+described above, a comment on the question of whether the Plan meets the
+requirements for qualification under Part I of Subchapter D of Chapter
+I of the Internal Revenue Code of 1954.  Two or more such persons
+.[
+Blue Cubic spline CSTR
+.]
+may join in a single comment or request.  If such a person or persons
+request the Department of Labor to submit a comment and that department
+declines to do so in respect of one or more matters raised in the request,
+the person or persons so requesting may submit a comment to the
+.[
+Graham small hexagon
+.]
+.[
+Blue cubic spline CSTR
+.]
+District Director in respect of the matters on which the Department
+of Labor declines to comment.  A comment
+submitted to the District Director must be received
+by him on or before June 30, 1977.  However, if it is
+being submitted on a matter on which the Department of
+Labor was first requested, but declined to comment, the comment
+.[
+Chambers methods linear models
+.]
+must be received by the District Director on or before the later
+of June 30, 1977 or the 15th day after the day on which the
+Department of Labor notifies such person
+that it declines to comment, but in no event later than July 15, 1977.
+A request of the Department of Labor to submit a comment must be received
+by that department on or before June 10, 1977, or, if the person or persons
+making the request wish to preserve their right to submit a comment to
+the District Director in the event the Department of Labor declines to comment,
+on or before May 30, 1977.
+.[
+$LIST$
+.]
diff --git a/usr/src/cmd/refer/thash.c b/usr/src/cmd/refer/thash.c
new file mode 100644 (file)
index 0000000..037800c
--- /dev/null
@@ -0,0 +1,140 @@
+# include "stdio.h"
+int nh 500;
+int saw[6000];
+char *comname "/usr/lib/eign";
+
+main (argc,argv)
+       char *argv[];
+{
+
+int i, z;
+char *name;
+
+FILE *f;
+
+while (argc>1 && argv[1][0] == '-')
+       {
+       switch(argv[1][1])
+               {
+               case 'h':
+                       nh = atoi(argv[1]+2); break;
+               }
+       argc--; argv++;
+       }
+if (argc<=1)
+       dofile(stdin, "");
+else
+for(i=1; i<argc; i++)
+       {
+       f = fopen(name=argv[i], "r");
+       if (f==NULL)
+               err("No file %s",name);
+       else
+               dofile(f, name);
+       }
+for(z=i=0; i<nh; i++)
+       {
+       if (saw[i]) z++;
+       }
+printf("hashes %d used %d\n",nh,z);
+}
+# include "stdio.h"
+
+dofile(f, name)
+       FILE *f;
+       char *name;
+{
+
+/* read file f & spit out keys & ptrs */
+# define MAXLINE 750
+char line[MAXLINE], *s;
+char key[20], *p;
+int k 0;
+int c, lim;
+int alph 0;
+int used 0;
+long lp 0;
+
+while (fgets(line, MAXLINE, f))
+       {
+       k++;
+       used=alph=0;
+       lim = strlen(line);
+       p = key;
+       for(s=line; c= *s; s++)
+               {
+               if (isalpha(c) || isdigit(c))
+                       {
+                       if (alph++ < 6)
+                               *p++ = c;
+                       }
+               else
+                       {
+                       *p = 0;
+                       if (outkey(p=key))
+                               {
+                               tkey(key,k);
+                               used=1;
+                               }
+                       alph=0;
+                       }
+               }
+       lp += lim;
+       }
+}
+
+outkey( ky)
+       char *ky;
+{
+       int n;
+n = strlen(ky);
+if (n<3) return(0);
+if (isdigit(ky[0]))
+       if (ky[0] != '1' || ky[1] != '9' || n!= 4) return(0);
+return(1);
+}
+# include "stdio.h"
+hash (s)
+       char *s;
+{
+int c, n, q;
+for(q=n=0; c= *s; s++)
+       n += (c*n + c << (n%4));
+return(n);
+}
+err (s, a)
+       char *s;
+{
+fprintf(stderr, "Error: ");
+fprintf(stderr, s, a);
+putc('\n', stderr);
+}
+prefix(t, s)
+       char *t, *s;
+{
+int c, d;
+while ( (c= *t++) == *s++)
+       if (c==0) return(1);
+return(c==0 ? 1: 0);
+}
+mindex(s, c)
+       char *s;
+{
+register char *p;
+for( p=s; *p; p++)
+       if (*p ==c)
+               return(p);
+return(0);
+}
+tkey(s,nw)
+       char *s;
+{
+int x;
+x = abs(hash(s)) % nh;
+/* if (saw[x]) printf("%d %d\n", x, nw); */
+saw[x]= nw;
+}
+abs(n)
+{
+return(n>0 ? n : -n);
+}
diff --git a/usr/src/cmd/refer/types.c b/usr/src/cmd/refer/types.c
new file mode 100644 (file)
index 0000000..d9348e6
--- /dev/null
@@ -0,0 +1,14 @@
+# if LONG
+# define ptr long
+# define uptr long
+# define getp getl
+# define putp putl
+# define MONE -1L
+extern long getl();
+# else
+# define ptr int
+# define uptr unsigned
+# define getp getw
+# define putp putw
+# define MONE -1
+# endif
diff --git a/usr/src/cmd/refer/what..c b/usr/src/cmd/refer/what..c
new file mode 100644 (file)
index 0000000..0aa00a5
--- /dev/null
@@ -0,0 +1,17 @@
+# include "stdio.h"
+# include "ctype.h"
+# include "sys/types.h"
+# include "sys/stat.h"
+# include "assert.h"
+# define NFILES 100
+# define NAMES 2000
+extern exch(), comp();
+struct filans {
+       char *nm;
+       long fdate;
+       long size;
+       int uid;
+       };
+extern struct filans files[NFILES];
+extern char fnames[NAMES];
+# define NFEED 5
diff --git a/usr/src/cmd/refer/what1.c b/usr/src/cmd/refer/what1.c
new file mode 100644 (file)
index 0000000..6fbb4c1
--- /dev/null
@@ -0,0 +1,133 @@
+# include "what..c"
+struct filans files[NFILES];
+char fnames[NAMES];
+int relfeed 0;
+char *rb[NFEED];
+char rbb[200], *rbp rbb;;
+
+main(argc,argv)
+       char *argv[];
+{
+       char *s, *t, *xargv[50], *wd[50];
+       struct filans *af;
+       int xargc 0, nw, nf, i;
+while (argc>1 && argv[1][0]=='-')
+       {
+       switch(argv[1][1])
+               {
+               case 'r': relfeed=1; break;
+               }
+       argc--; argv++;
+       }
+if (argc<=1)
+       {
+       printf("No query.\n");
+       return(0);
+       }
+nf = doclook(argc,argv,0);
+printf("   %d files\n",nf);
+if (relfeed && nf>NFEED)
+       {
+       wrdoc(NFEED, argc, argv, 1);
+       nw = freqwd (rb, wd, argc);
+       for(i=0; rb[i]; i++)
+               unlink(rb[i]);
+       }
+for(i=0; i<argc; i++)
+       xargv[xargc++]=argv[i];
+if (relfeed)
+       {
+       printf("Adding: ");
+       for(i=0; i<nw; i++)
+               if (!lfind(wd[i], xargc, xargv))
+                       printf("%s ", xargv[xargc++]=wd[i]);
+       printf("\n");
+       nf = doclook(xargc, xargv, relfeed? xargc/4 : 0);
+       printf("  %d files\n",nf);
+       }
+shell (nf, comp, exch);
+wrdoc(nf, xargc, xargv, 0);
+return(0);
+}
+exch( i1, i2 )
+{
+       struct filans *p1, *p2;
+       struct filans xt;
+       p1=files+i1;
+       p2=files+i2;
+       xt = *p1;
+       *p1 = *p2;
+       *p2 = xt;
+}
+comp(i1, i2)
+{
+       struct filans *p1, *p2;
+       p1 = files+i1;
+       p2= files+i2;
+       if (p1->fdate != p2->fdate)
+               return(p2->fdate > p1->fdate);
+       return(p2->uid >= p1->uid);
+}
+wrdoc ( np, argc, argv, relfeed )
+{
+       struct filans *af;
+       char *s, *t, buf[200];
+       int eval, k, pid;
+       FILE *rf NULL;
+       FILE *ans NULL;
+       pid=getpid();
+       for(af=files; af<files+np; af++)
+               {
+               t = ctime(&af->fdate);
+               getpw(af->uid, s=buf);
+               while (*s && *s!=':') s++;
+               *s=0;
+               printf("%s (%.20s)  %s, %ld bytes\n",af->nm,t+4,buf,af->size);
+               if (relfeed)
+                       {
+                       k=af-files;
+                       _assert (k<NFEED);
+                       sprintf(rb[k]=rbp, "rf%d.%d",pid, k);
+                       rf = fopen(rb[k], "w");
+                       while (*rbp++);
+                       }
+               describe(af->nm, argc,argv, rf);
+               if (relfeed)
+                       {
+                       printf("You like that one?");
+                       fflush(stdout);
+                       fgets(buf, 100, stdin);
+                       switch(buf[0])
+                               {
+                               case 'y': case 'Y': eval=1; break;
+                               case 'n': case 'N': eval = -1; break;
+                               default: eval=0; break;
+                               }
+                       fclose(rf);
+                       if (eval<=0)
+                               {
+                               unlink(rb[k]);
+                               rb[k][0]=0;
+                               }
+                       }
+               }
+       if (relfeed) rb[np]=0;
+}
+lfind( wl, n, wds)
+       char *wl, *wds[];
+{
+       int i;
+for(i=0; i<n; i++)
+       if (str6cmp(wl, wds[i])==0)
+               return(1);
+return(0);
+}
+str6cmp(s, t)
+       char *s, *t;
+{
+int i 0, c;
+while ( (c= *s++ ) == ( *t++))
+       if (c==0 || ++i ==6)
+               return(0);
+return(1);
+}
diff --git a/usr/src/cmd/refer/what3.c b/usr/src/cmd/refer/what3.c
new file mode 100644 (file)
index 0000000..c727da9
--- /dev/null
@@ -0,0 +1,71 @@
+# include "what..c"
+
+doclook(argc, argv, colevel)
+       char *argv[];
+{
+       int fpa[2], fpb[2], fpc[2], pid1, pid2, st;
+       int iarg;
+       char *s;
+       FILE *ansf;
+       struct filans *af;
+       struct stat statbuf;
+# define RD 0
+# define WR 1
+# define fmv(x,y) close(y); dup(x); close(x);
+/* we want to run chkbib and then lhunt and pipe in & out */
+pipe (fpa); /* from this program to chkbib */
+pipe (fpb); /* from chkbib to lhunt */
+pipe (fpc); /* from lhunt to us */
+if (  (pid1 = fork())  ==0)
+       {
+       fmv(fpa[RD], 0);
+       fmv(fpb[WR], 1);
+       close(fpa[WR]); close(fpb[RD]); close(fpc[RD]); close(fpc[WR]); 
+       execl("/usr/lib/refer/mkey", "mkey", "-s", 0);
+       _assert(0);
+       }
+if (  (pid2 = fork()) == 0)
+       {
+       char coarg[20];
+       sprintf(coarg, "-C%d", colevel);
+       fmv(fpb[RD], 0);
+       fmv(fpc[WR], 1);
+       close(fpa[RD]); close(fpa[WR]); close(fpb[WR]); close(fpc[RD]);
+       execl("/usr/lib/refer/hunt", "hunt",
+               /* "-P", */
+               coarg, "-Ty", "-Fn", "/usr/dict/lookall/All", 0);
+       _assert(0);
+       }
+_assert (pid1 != -1); _assert(pid2 != -1);
+close(fpb[RD]); close(fpb[WR]); close(fpa[RD]); close(fpc[WR]);
+ansf = fopen("/dev/null", "r");
+fmv (fpc[RD], ansf->_file);
+for(iarg=1; iarg<argc; iarg++)
+       prod(fpa[WR], argv[iarg]);
+close(fpa[WR]);
+s=fnames;
+af=files;
+while (af < files+NFILES)
+       {
+       if (fgets(af->nm=s, NAMES, ansf)==0)
+               break;
+       trimnl(s);
+       if (*s==0) continue;
+       while (*s++);
+       _assert(s<fnames+NAMES);
+       st = stat(af->nm, &statbuf);
+       if (st<0) continue;
+       af->uid = statbuf.st_uid;
+       af->fdate = statbuf.st_mtime;
+       af->size = statbuf.st_size;
+       af++;
+       }
+fclose(ansf);
+return(af-files);
+}
+prod(f,s)
+       char *s;
+{
+write (f, s, strlen(s));
+write (f, "\n", 1);
+}
diff --git a/usr/src/cmd/refer/what4.c b/usr/src/cmd/refer/what4.c
new file mode 100644 (file)
index 0000000..e9a2bd3
--- /dev/null
@@ -0,0 +1,163 @@
+# include "what..c"
+struct wst { char *tx; int ct; } ;
+# define NW 5
+# define ZIPF 10
+# define HASHF 3
+# define WLEN 10
+# define SAME 0
+# define TSIZE HASHF*ZIPF*NW
+int HSIZE;
+static struct wst word[TSIZE];
+static char tbuf[NW*ZIPF*WLEN], *tp tbuf;
+# define NF 10
+
+freqwd ( fn, wd, nin )
+       char *fn[], *wd[];
+{
+       FILE *fi[NF];
+       int nw 0, i, any, nf, j, wexch(), wcomp();
+       char tw[20];
+for(HSIZE=TSIZE; !prime(HSIZE); HSIZE--);
+for(nf=0; fn[nf] && nf<NF; nf++)
+       fi[nf] = fn[nf][0] ? fopen(fn[nf], "r") : NULL;
+do {
+       any=0;
+       for(i=0; i<nf; i++)
+               {
+               if (fi[i]==NULL) continue;
+               if (gw(fi[i], tw)==0)
+                       {
+                       fclose(fi[i]);
+                       fi[i]==NULL;
+                       continue;
+                       }
+               any=1;
+               if (common(tw)) continue;
+               if (strlen(tw)<3) continue;
+               j = lookup (tw);
+               if (j<0 && nw < ZIPF*NW)
+                       {
+                       j = -j;
+                       strcpy (tp, tw);
+                       word[j].tx = tp;
+                       while (*tp++);
+                       _assert (tp < tbuf+NW*ZIPF*WLEN);
+                       word[j].ct = 1;
+                       nw++;
+                       }
+               else if (j>0)
+                       word[j].ct++;
+               }
+       } while (any>0);
+shell ( TSIZE, wcomp, wexch );
+for(nw=0; word[nw].ct >0 && nw<TSIZE; nw++)
+       if (nw>=nin*2 && word[nw].ct != word[0].ct)
+               break;
+for(i=0; i<nw; i++)
+       wd[i] = word[i].tx;
+return(nw);
+}
+
+lookup (wt)
+       char *wt;
+{
+int h;
+h = hash(wt);
+for( h = h%HSIZE; word[h].tx; h = (h+1)%HSIZE)
+       {
+       if (h==0) continue;
+       if (strcmp(wt, word[h].tx) == SAME)
+               return (h);
+       }
+return ( -h );
+}
+
+hash (s)
+       char *s;
+{
+int k 0, c 0, i 0;
+while ( c = *s++ )
+       k ^= (c << (i++%5) );
+return (k>0 ? k : -k);
+}
+
+gw (f, t)
+       char *t;
+       FILE *f;
+{
+int start 1, oldc ' ', c;
+if (f==NULL) return (0);
+while ( (c=getc(f)) != EOF)
+       {
+       if (isupper(c)) c= tolower(c);
+       if (start==1)
+               if (!alphanum(c, oldc))
+                       continue;
+               else
+                       start=0;
+       if (start==0)
+               if (alphanum(c, oldc))
+                       *t++ = c;
+               else
+                       {
+                       *t=0;
+                       return(1);
+                       }
+       oldc=c;
+       }
+return(0);
+}
+
+alphanum( c, oldc )
+{
+if (isalpha(c) || isdigit(c)) return(1);
+if (isalpha(oldc))
+       if (c== '\'' || c == '-') return(1);
+return(0);
+}
+
+wcomp (n1, n2)
+{
+return (word[n1].ct >= word[n2].ct);
+}
+
+wexch (n1, n2)
+{
+struct wst tt;
+tt.tx = word[n1].tx; tt.ct = word[n1].ct;
+word[n1].tx = word[n2].tx; word[n1].ct = word[n2].ct;
+word[n2].tx = tt.tx; word[n2].ct = tt.ct;
+}
+
+prime(n)
+{
+/* only executed once- slow is ok */
+int i;
+if (n%2==0) return(0);
+for(i=3; i*i<=n; i+= 2)
+       if (n%i ==0 ) return(0);
+return(1);
+}
+trimnl(s)
+       char *s;
+{
+       while (*s)s++;
+       if (*--s=='\n') *s=0;
+}
+
+
+/* this is the test for what4.c as a standalone prog ...
+main (argc, argv)
+       char *argv[];
+{
+char *ff[10], *wd[20], **ffp ff;
+int n, i;
+while (--argc)
+       *ffp++ = *++argv;
+*ffp=0;
+n=freqwd(ff,wd);
+for(i=0; i<n; i++)
+ printf("%s\n",wd[i]);
+printf("total of %d items\n",n);
+}
+ /* .... */
diff --git a/usr/src/cmd/sed/sed0.c b/usr/src/cmd/sed/sed0.c
new file mode 100644 (file)
index 0000000..2b92948
--- /dev/null
@@ -0,0 +1,966 @@
+#include <stdio.h>
+#include "sed.h"
+
+struct label   *labtab = ltab;
+char   CGMES[] = "command garbled: %s\n";
+char   TMMES[] = "Too much text: %s\n";
+char   LTL[]   = "Label too long: %s\n";
+char   AD0MES[]        = "No addresses allowed: %s\n";
+char   AD1MES[]        = "Only one address allowed: %s\n";
+char   bittab[]  = {
+               1,
+               2,
+               4,
+               8,
+               16,
+               32,
+               64,
+               128
+       };
+
+main(argc, argv)
+char   *argv[];
+{
+
+       eargc = argc;
+       eargv = argv;
+
+       badp = &bad;
+       aptr = abuf;
+       lab = labtab + 1;       /* 0 reserved for end-pointer */
+       rep = ptrspace;
+       rep->ad1 = respace;
+       lbend = &linebuf[LBSIZE];
+       hend = &holdsp[LBSIZE];
+       ptrend = &ptrspace[PTRSIZE];
+       reend = &respace[RESIZE];
+       labend = &labtab[LABSIZE];
+       lnum = 0;
+       pending = 0;
+       depth = 0;
+       spend = linebuf;
+       fcode[0] = stdout;
+       nfiles = 1;
+
+       if(eargc == 1)
+               exit(0);
+
+
+       while (--eargc > 0 && (++eargv)[0][0] == '-')
+               switch (eargv[0][1]) {
+
+               case 'n':
+                       nflag++;
+                       continue;
+
+               case 'f':
+                       if(eargc-- <= 0)        exit(2);
+
+                       if((fin = fopen(*++eargv, "r")) == NULL) {
+                               fprintf(stderr, "Cannot open pattern-file: %s\n", *eargv);
+                               exit(2);
+                       }
+
+                       fcomp();
+                       fclose(fin);
+                       continue;
+
+               case 'e':
+                       eflag++;
+                       fcomp();
+                       eflag = 0;
+                       continue;
+
+               case 'g':
+                       gflag++;
+                       continue;
+
+               default:
+                       fprintf(stdout, "Unknown flag: %c\n", eargv[0][1]);
+                       continue;
+               }
+
+
+       if(rep == ptrspace) {
+               eargv--;
+               eargc++;
+               eflag++;
+               fcomp();
+               eargv++;
+               eargc--;
+               eflag = 0;
+       }
+
+       if(depth) {
+               fprintf(stderr, "Too many {'s");
+               exit(2);
+       }
+
+       labtab->address = rep;
+
+       dechain();
+
+/*     abort();        /*DEBUG*/
+
+       if(eargc <= 0)
+               execute((char *)NULL);
+       else while(--eargc >= 0) {
+               execute(*eargv++);
+       }
+       fclose(stdout);
+       exit(0);
+}
+fcomp()
+{
+
+       register char   *p, *op, *tp;
+       char    *address();
+       union reptr     *pt, *pt1;
+       int     i;
+       struct label    *lpt;
+
+       op = lastre;
+
+       if(rline(linebuf) < 0)  return;
+       if(*linebuf == '#') {
+               if(linebuf[1] == 'n')
+                       nflag = 1;
+       }
+       else {
+               cp = linebuf;
+               goto comploop;
+       }
+
+       for(;;) {
+               if(rline(linebuf) < 0)  break;
+
+               cp = linebuf;
+
+comploop:
+/*     fprintf(stdout, "cp: %s\n", cp);        /*DEBUG*/
+               while(*cp == ' ' || *cp == '\t')        cp++;
+               if(*cp == '\0' || *cp == '#')           continue;
+               if(*cp == ';') {
+                       cp++;
+                       goto comploop;
+               }
+
+               p = address(rep->ad1);
+               if(p == badp) {
+                       fprintf(stderr, CGMES, linebuf);
+                       exit(2);
+               }
+
+               if(p == rep->ad1) {
+                       if(op)
+                               rep->ad1 = op;
+                       else {
+                               fprintf(stderr, "First RE may not be null\n");
+                               exit(2);
+                       }
+               } else if(p == 0) {
+                       p = rep->ad1;
+                       rep->ad1 = 0;
+               } else {
+                       op = rep->ad1;
+                       if(*cp == ',' || *cp == ';') {
+                               cp++;
+                               if((rep->ad2 = p) > reend) {
+                                       fprintf(stderr, TMMES, linebuf);
+                                       exit(2);
+                               }
+                               p = address(rep->ad2);
+                               if(p == badp || p == 0) {
+                                       fprintf(stderr, CGMES, linebuf);
+                                       exit(2);
+                               }
+                               if(p == rep->ad2)
+                                       rep->ad2 = op;
+                               else
+                                       op = rep->ad2;
+
+                       } else
+                               rep->ad2 = 0;
+               }
+
+               if(p > reend) {
+                       fprintf(stderr, "Too much text: %s\n", linebuf);
+                       exit(2);
+               }
+
+               while(*cp == ' ' || *cp == '\t')        cp++;
+
+swit:
+               switch(*cp++) {
+
+                       default:
+                               fprintf(stderr, "Unrecognized command: %s\n", linebuf);
+                               exit(2);
+
+                       case '!':
+                               rep->negfl = 1;
+                               goto swit;
+
+                       case '{':
+                               rep->command = BCOM;
+                               rep->negfl = !(rep->negfl);
+                               cmpend[depth++] = &rep->lb1;
+                               if(++rep >= ptrend) {
+                                       fprintf(stderr, "Too many commands: %s\n", linebuf);
+                                       exit(2);
+                               }
+                               rep->ad1 = p;
+                               if(*cp == '\0') continue;
+
+                               goto comploop;
+
+                       case '}':
+                               if(rep->ad1) {
+                                       fprintf(stderr, AD0MES, linebuf);
+                                       exit(2);
+                               }
+
+                               if(--depth < 0) {
+                                       fprintf(stderr, "Too many }'s\n");
+                                       exit(2);
+                               }
+                               *cmpend[depth] = rep;
+
+                               rep->ad1 = p;
+                               continue;
+
+                       case '=':
+                               rep->command = EQCOM;
+                               if(rep->ad2) {
+                                       fprintf(stderr, AD1MES, linebuf);
+                                       exit(2);
+                               }
+                               break;
+
+                       case ':':
+                               if(rep->ad1) {
+                                       fprintf(stderr, AD0MES, linebuf);
+                                       exit(2);
+                               }
+
+                               while(*cp++ == ' ');
+                               cp--;
+
+
+                               tp = lab->asc;
+                               while((*tp++ = *cp++))
+                                       if(tp >= &(lab->asc[8])) {
+                                               fprintf(stderr, LTL, linebuf);
+                                               exit(2);
+                                       }
+                               *--tp = '\0';
+
+                               if(lpt = search(lab)) {
+                                       if(lpt->address) {
+                                               fprintf(stderr, "Duplicate labels: %s\n", linebuf);
+                                               exit(2);
+                                       }
+                               } else {
+                                       lab->chain = 0;
+                                       lpt = lab;
+                                       if(++lab >= labend) {
+                                               fprintf(stderr, "Too many labels: %s\n", linebuf);
+                                               exit(2);
+                                       }
+                               }
+                               lpt->address = rep;
+                               rep->ad1 = p;
+
+                               continue;
+
+                       case 'a':
+                               rep->command = ACOM;
+                               if(rep->ad2) {
+                                       fprintf(stderr, AD1MES, linebuf);
+                                       exit(2);
+                               }
+                               if(*cp == '\\') cp++;
+                               if(*cp++ != '\n') {
+                                       fprintf(stderr, CGMES, linebuf);
+                                       exit(2);
+                               }
+                               rep->re1 = p;
+                               p = text(rep->re1);
+                               break;
+                       case 'c':
+                               rep->command = CCOM;
+                               if(*cp == '\\') cp++;
+                               if(*cp++ != ('\n')) {
+                                       fprintf(stderr, CGMES, linebuf);
+                                       exit(2);
+                               }
+                               rep->re1 = p;
+                               p = text(rep->re1);
+                               break;
+                       case 'i':
+                               rep->command = ICOM;
+                               if(rep->ad2) {
+                                       fprintf(stderr, AD1MES, linebuf);
+                                       exit(2);
+                               }
+                               if(*cp == '\\') cp++;
+                               if(*cp++ != ('\n')) {
+                                       fprintf(stderr, CGMES, linebuf);
+                                       exit(2);
+                               }
+                               rep->re1 = p;
+                               p = text(rep->re1);
+                               break;
+
+                       case 'g':
+                               rep->command = GCOM;
+                               break;
+
+                       case 'G':
+                               rep->command = CGCOM;
+                               break;
+
+                       case 'h':
+                               rep->command = HCOM;
+                               break;
+
+                       case 'H':
+                               rep->command = CHCOM;
+                               break;
+
+                       case 't':
+                               rep->command = TCOM;
+                               goto jtcommon;
+
+                       case 'b':
+                               rep->command = BCOM;
+jtcommon:
+                               while(*cp++ == ' ');
+                               cp--;
+
+                               if(*cp == '\0') {
+                                       if(pt = labtab->chain) {
+                                               while(pt1 = pt->lb1)
+                                                       pt = pt1;
+                                               pt->lb1 = rep;
+                                       } else
+                                               labtab->chain = rep;
+                                       break;
+                               }
+                               tp = lab->asc;
+                               while((*tp++ = *cp++))
+                                       if(tp >= &(lab->asc[8])) {
+                                               fprintf(stderr, LTL, linebuf);
+                                               exit(2);
+                                       }
+                               cp--;
+                               *--tp = '\0';
+
+                               if(lpt = search(lab)) {
+                                       if(lpt->address) {
+                                               rep->lb1 = lpt->address;
+                                       } else {
+                                               pt = lpt->chain;
+                                               while(pt1 = pt->lb1)
+                                                       pt = pt1;
+                                               pt->lb1 = rep;
+                                       }
+                               } else {
+                                       lab->chain = rep;
+                                       lab->address = 0;
+                                       if(++lab >= labend) {
+                                               fprintf(stderr, "Too many labels: %s\n", linebuf);
+                                               exit(2);
+                                       }
+                               }
+                               break;
+
+                       case 'n':
+                               rep->command = NCOM;
+                               break;
+
+                       case 'N':
+                               rep->command = CNCOM;
+                               break;
+
+                       case 'p':
+                               rep->command = PCOM;
+                               break;
+
+                       case 'P':
+                               rep->command = CPCOM;
+                               break;
+
+                       case 'r':
+                               rep->command = RCOM;
+                               if(rep->ad2) {
+                                       fprintf(stderr, AD1MES, linebuf);
+                                       exit(2);
+                               }
+                               if(*cp++ != ' ') {
+                                       fprintf(stderr, CGMES, linebuf);
+                                       exit(2);
+                               }
+                               rep->re1 = p;
+                               p = text(rep->re1);
+                               break;
+
+                       case 'd':
+                               rep->command = DCOM;
+                               break;
+
+                       case 'D':
+                               rep->command = CDCOM;
+                               rep->lb1 = ptrspace;
+                               break;
+
+                       case 'q':
+                               rep->command = QCOM;
+                               if(rep->ad2) {
+                                       fprintf(stderr, AD1MES, linebuf);
+                                       exit(2);
+                               }
+                               break;
+
+                       case 'l':
+                               rep->command = LCOM;
+                               break;
+
+                       case 's':
+                               rep->command = SCOM;
+                               seof = *cp++;
+                               rep->re1 = p;
+                               p = compile(rep->re1);
+                               if(p == badp) {
+                                       fprintf(stderr, CGMES, linebuf);
+                                       exit(2);
+                               }
+                               if(p == rep->re1) {
+                                       rep->re1 = op;
+                               } else {
+                                       op = rep->re1;
+                               }
+
+                               if((rep->rhs = p) > reend) {
+                                       fprintf(stderr, TMMES, linebuf);
+                                       exit(2);
+                               }
+
+                               if((p = compsub(rep->rhs)) == badp) {
+                                       fprintf(stderr, CGMES, linebuf);
+                                       exit(2);
+                               }
+                               if(*cp == 'g') {
+                                       cp++;
+                                       rep->gfl++;
+                               } else if(gflag)
+                                       rep->gfl++;
+
+                               if(*cp == 'p') {
+                                       cp++;
+                                       rep->pfl = 1;
+                               }
+
+                               if(*cp == 'P') {
+                                       cp++;
+                                       rep->pfl = 2;
+                               }
+
+                               if(*cp == 'w') {
+                                       cp++;
+                                       if(*cp++ !=  ' ') {
+                                               fprintf(stderr, CGMES, linebuf);
+                                               exit(2);
+                                       }
+                                       if(nfiles >= 10) {
+                                               fprintf(stderr, "Too many files in w commands\n");
+                                               exit(2);
+                                       }
+
+                                       text(fname[nfiles]);
+                                       for(i = nfiles - 1; i >= 0; i--)
+                                               if(cmp(fname[nfiles],fname[i]) == 0) {
+                                                       rep->fcode = fcode[i];
+                                                       goto done;
+                                               }
+                                       if((rep->fcode = fopen(fname[nfiles], "w")) == NULL) {
+                                               fprintf(stderr, "cannot open %s\n", fname[nfiles]);
+                                               exit(2);
+                                       }
+                                       fcode[nfiles++] = rep->fcode;
+                               }
+                               break;
+
+                       case 'w':
+                               rep->command = WCOM;
+                               if(*cp++ != ' ') {
+                                       fprintf(stderr, CGMES, linebuf);
+                                       exit(2);
+                               }
+                               if(nfiles >= 10){
+                                       fprintf(stderr, "Too many files in w commands\n");
+                                       exit(2);
+                               }
+
+                               text(fname[nfiles]);
+                               for(i = nfiles - 1; i >= 0; i--)
+                                       if(cmp(fname[nfiles], fname[i]) == 0) {
+                                               rep->fcode = fcode[i];
+                                               goto done;
+                                       }
+
+                               if((rep->fcode = fopen(fname[nfiles], "w")) == NULL) {
+                                       fprintf(stderr, "Cannot create %s\n", fname[nfiles]);
+                                       exit(2);
+                               }
+                               fcode[nfiles++] = rep->fcode;
+                               break;
+
+                       case 'x':
+                               rep->command = XCOM;
+                               break;
+
+                       case 'y':
+                               rep->command = YCOM;
+                               seof = *cp++;
+                               rep->re1 = p;
+                               p = ycomp(rep->re1);
+                               if(p == badp) {
+                                       fprintf(stderr, CGMES, linebuf);
+                                       exit(2);
+                               }
+                               if(p > reend) {
+                                       fprintf(stderr, TMMES, linebuf);
+                                       exit(2);
+                               }
+                               break;
+
+               }
+done:
+               if(++rep >= ptrend) {
+                       fprintf(stderr, "Too many commands, last: %s\n", linebuf);
+                       exit(2);
+               }
+
+               rep->ad1 = p;
+
+               if(*cp++ != '\0') {
+                       if(cp[-1] == ';')
+                               goto comploop;
+                       fprintf(stderr, CGMES, linebuf);
+                       exit(2);
+               }
+
+       }
+       rep->command = 0;
+       lastre = op;
+}
+char   *compsub(rhsbuf)
+char   *rhsbuf;
+{
+       register char   *p, *q;
+
+       p = rhsbuf;
+       q = cp;
+       for(;;) {
+               if((*p = *q++) == '\\') {
+                       *p = *q++;
+                       if(*p > numbra + '0' && *p <= '9')
+                               return(badp);
+                       *p++ |= 0200;
+                       continue;
+               }
+               if(*p == seof) {
+                       *p++ = '\0';
+                       cp = q;
+                       return(p);
+               }
+               if(*p++ == '\0') {
+                       return(badp);
+               }
+
+       }
+}
+
+char *compile(expbuf)
+char   *expbuf;
+{
+       register c;
+       register char *ep, *sp;
+       char    neg;
+       char *lastep, *cstart;
+       int cclcnt;
+       int     closed;
+       char    bracket[NBRA], *bracketp;
+
+       if(*cp == seof) {
+               cp++;
+               return(expbuf);
+       }
+
+       ep = expbuf;
+       lastep = 0;
+       bracketp = bracket;
+       closed = numbra = 0;
+       sp = cp;
+       if (*sp == '^') {
+               *ep++ = 1;
+               sp++;
+       } else {
+               *ep++ = 0;
+       }
+       for (;;) {
+               if (ep >= &expbuf[ESIZE]) {
+                       cp = sp;
+                       return(badp);
+               }
+               if((c = *sp++) == seof) {
+                       if(bracketp != bracket) {
+                               cp = sp;
+                               return(badp);
+                       }
+                       cp = sp;
+                       *ep++ = CEOF;
+                       return(ep);
+               }
+               if(c != '*')
+                       lastep = ep;
+               switch (c) {
+
+               case '\\':
+                       if((c = *sp++) == '(') {
+                               if(numbra >= NBRA) {
+                                       cp = sp;
+                                       return(badp);
+                               }
+                               *bracketp++ = numbra;
+                               *ep++ = CBRA;
+                               *ep++ = numbra++;
+                               continue;
+                       }
+                       if(c == ')') {
+                               if(bracketp <= bracket) {
+                                       cp = sp;
+                                       return(badp);
+                               }
+                               *ep++ = CKET;
+                               *ep++ = *--bracketp;
+                               closed++;
+                               continue;
+                       }
+
+                       if(c >= '1' && c <= '9') {
+                               if((c -= '1') >= closed)
+                                       return(badp);
+       
+                               *ep++ = CBACK;
+                               *ep++ = c;
+                               continue;
+                       }
+                       if(c == '\n') {
+                               cp = sp;
+                               return(badp);
+                       }
+                       if(c == 'n') {
+                               c = '\n';
+                       }
+                       goto defchar;
+
+               case '\0':
+                       continue;
+               case '\n':
+                       cp = sp;
+                       return(badp);
+
+               case '.':
+                       *ep++ = CDOT;
+                       continue;
+
+               case '*':
+                       if (lastep == 0)
+                               goto defchar;
+                       if(*lastep == CKET) {
+                               cp = sp;
+                               return(badp);
+                       }
+                       *lastep |= STAR;
+                       continue;
+
+               case '$':
+                       if (*sp != seof)
+                               goto defchar;
+                       *ep++ = CDOL;
+                       continue;
+
+               case '[':
+                       if(&ep[17] >= &expbuf[ESIZE]) {
+                               fprintf(stderr, "RE too long: %s\n", linebuf);
+                               exit(2);
+                       }
+
+                       *ep++ = CCL;
+
+                       neg = 0;
+                       if((c = *sp++) == '^') {
+                               neg = 1;
+                               c = *sp++;
+                       }
+
+                       cstart = sp;
+                       do {
+                               if(c == '\0') {
+                                       fprintf(stderr, CGMES, linebuf);
+                                       exit(2);
+                               }
+                               if (c=='-' && sp>cstart && *sp!=']') {
+                                       for (c = sp[-2]; c<*sp; c++)
+                                               ep[c>>3] |= bittab[c&07];
+                               }
+                               if(c == '\\') {
+                                       switch(c = *sp++) {
+                                               case 'n':
+                                                       c = '\n';
+                                                       break;
+                                       }
+                               }
+
+                               ep[c >> 3] |= bittab[c & 07];
+                       } while((c = *sp++) != ']');
+
+                       if(neg)
+                               for(cclcnt = 0; cclcnt < 16; cclcnt++)
+                                       ep[cclcnt] ^= -1;
+                       ep[0] &= 0376;
+
+                       ep += 16;
+
+                       continue;
+
+               defchar:
+               default:
+                       *ep++ = CCHR;
+                       *ep++ = c;
+               }
+       }
+}
+rline(lbuf)
+char   *lbuf;
+{
+       register char   *p, *q;
+       register        t;
+       static char     *saveq;
+
+       p = lbuf - 1;
+
+       if(eflag) {
+               if(eflag > 0) {
+                       eflag = -1;
+                       if(eargc-- <= 0)
+                               exit(2);
+                       q = *++eargv;
+                       while(*++p = *q++) {
+                               if(*p == '\\') {
+                                       if((*++p = *q++) == '\0') {
+                                               saveq = 0;
+                                               return(-1);
+                                       } else
+                                               continue;
+                               }
+                               if(*p == '\n') {
+                                       *p = '\0';
+                                       saveq = q;
+                                       return(1);
+                               }
+                       }
+                       saveq = 0;
+                       return(1);
+               }
+               if((q = saveq) == 0)    return(-1);
+
+               while(*++p = *q++) {
+                       if(*p == '\\') {
+                               if((*++p = *q++) == '0') {
+                                       saveq = 0;
+                                       return(-1);
+                               } else
+                                       continue;
+                       }
+                       if(*p == '\n') {
+                               *p = '\0';
+                               saveq = q;
+                               return(1);
+                       }
+               }
+               saveq = 0;
+               return(1);
+       }
+
+       while((t = getc(fin)) != EOF) {
+               *++p = t;
+               if(*p == '\\') {
+                       t = getc(fin);
+                       *++p = t;
+               }
+               else if(*p == '\n') {
+                       *p = '\0';
+                       return(1);
+               }
+       }
+       *++p = '\0';
+       return(-1);
+}
+
+char   *address(expbuf)
+char   *expbuf;
+{
+       register char   *rcp;
+       long    lno;
+
+       if(*cp == '$') {
+               cp++;
+               *expbuf++ = CEND;
+               *expbuf++ = CEOF;
+               return(expbuf);
+       }
+
+       if(*cp == '/') {
+               seof = '/';
+               cp++;
+               return(compile(expbuf));
+       }
+
+       rcp = cp;
+       lno = 0;
+
+       while(*rcp >= '0' && *rcp <= '9')
+               lno = lno*10 + *rcp++ - '0';
+
+       if(rcp > cp) {
+               *expbuf++ = CLNUM;
+               *expbuf++ = nlno;
+               tlno[nlno++] = lno;
+               if(nlno >= NLINES) {
+                       fprintf(stderr, "Too many line numbers\n");
+                       exit(2);
+               }
+               *expbuf++ = CEOF;
+               cp = rcp;
+               return(expbuf);
+       }
+       return(0);
+}
+cmp(a, b)
+char   *a,*b;
+{
+       register char   *ra, *rb;
+
+       ra = a - 1;
+       rb = b - 1;
+
+       while(*++ra == *++rb)
+               if(*ra == '\0') return(0);
+       return(1);
+}
+
+char   *text(textbuf)
+char   *textbuf;
+{
+       register char   *p, *q;
+
+       p = textbuf;
+       q = cp;
+       while(*q == '\t' || *q == ' ')  q++;
+       for(;;) {
+
+               if((*p = *q++) == '\\')
+                       *p = *q++;
+               if(*p == '\0') {
+                       cp = --q;
+                       return(++p);
+               }
+               if(*p == '\n') {
+                       while(*q == '\t' || *q == ' ')  q++;
+               }
+               p++;
+       }
+}
+
+
+struct label   *search(ptr)
+struct label   *ptr;
+{
+       struct label    *rp;
+
+       rp = labtab;
+       while(rp < ptr) {
+               if(cmp(rp->asc, ptr->asc) == 0)
+                       return(rp);
+               rp++;
+       }
+
+       return(0);
+}
+
+
+dechain()
+{
+       struct label    *lptr;
+       union reptr     *rptr, *trptr;
+
+       for(lptr = labtab; lptr < lab; lptr++) {
+
+               if(lptr->address == 0) {
+                       fprintf(stderr, "Undefined label: %s\n", lptr->asc);
+                       exit(2);
+               }
+
+               if(lptr->chain) {
+                       rptr = lptr->chain;
+                       while(trptr = rptr->lb1) {
+                               rptr->lb1 = lptr->address;
+                               rptr = trptr;
+                       }
+                       rptr->lb1 = lptr->address;
+               }
+       }
+}
+
+char *ycomp(expbuf)
+char   *expbuf;
+{
+       register char   c, *ep, *tsp;
+       char    *sp;
+
+       ep = expbuf;
+       sp = cp;
+       for(tsp = cp; *tsp != seof; tsp++) {
+               if(*tsp == '\\')
+                       tsp++;
+               if(*tsp == '\n')
+                       return(badp);
+       }
+       tsp++;
+
+       while((c = *sp++ & 0177) != seof) {
+               if(c == '\\' && *sp == 'n') {
+                       sp++;
+                       c = '\n';
+               }
+               if((ep[c] = *tsp++) == '\\' && *tsp == 'n') {
+                       ep[c] = '\n';
+                       tsp++;
+               }
+               if(ep[c] == seof || ep[c] == '\0')
+                       return(badp);
+       }
+       if(*tsp != seof)
+               return(badp);
+       cp = ++tsp;
+
+       for(c = 0; !(c & 0200); c++)
+               if(ep[c] == 0)
+                       ep[c] = c;
+
+       return(ep + 0200);
+}
+
diff --git a/usr/src/cmd/sh/args.c b/usr/src/cmd/sh/args.c
new file mode 100644 (file)
index 0000000..5fe26de
--- /dev/null
@@ -0,0 +1,135 @@
+#
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Bell Telephone Laboratories
+ *
+ */
+
+#include       "defs.h"
+
+PROC STRING *copyargs();
+LOCAL DOLPTR   dolh;
+
+CHAR   flagadr[10];
+
+CHAR   flagchar[] = {
+       'x',    'n',    'v',    't',    's',    'i',    'e',    'r',    'k',    'u',    0
+};
+INT    flagval[]  = {
+       execpr, noexec, readpr, oneflg, stdflg, intflg, errflg, rshflg, keyflg, setflg, 0
+};
+
+/* ========    option handling ======== */
+
+
+INT    options(argc,argv)
+       STRING          *argv;
+       INT             argc;
+{
+       REG STRING      cp;
+       REG STRING      *argp=argv;
+       REG STRING      flagc;
+       STRING          flagp;
+
+       IF argc>1 ANDF *argp[1]=='-'
+       THEN    cp=argp[1];
+               flags &= ~(execpr|readpr);
+               WHILE *++cp
+               DO      flagc=flagchar;
+
+                       WHILE *flagc ANDF *flagc != *cp DO flagc++ OD
+                       IF *cp == *flagc
+                       THEN    flags |= flagval[flagc-flagchar];
+                       ELIF *cp=='c' ANDF argc>2 ANDF comdiv==0
+                       THEN    comdiv=argp[2];
+                               argp[1]=argp[0]; argp++; argc--;
+                       ELSE    failed(argv[1],badopt);
+                       FI
+               OD
+               argp[1]=argp[0]; argc--;
+       FI
+
+       /* set up $- */
+       flagc=flagchar;
+       flagp=flagadr;
+       WHILE *flagc
+       DO IF flags&flagval[flagc-flagchar]
+          THEN *flagp++ = *flagc;
+          FI
+          flagc++;
+       OD
+       *flagp++=0;
+
+       return(argc);
+}
+
+VOID   setargs(argi)
+       STRING          argi[];
+{
+       /* count args */
+       REG STRING      *argp=argi;
+       REG INT         argn=0;
+
+       WHILE Rcheat(*argp++)!=ENDARGS DO argn++ OD
+
+       /* free old ones unless on for loop chain */
+       freeargs(dolh);
+       dolh=copyargs(argi,argn);       /* sets dolv */
+       assnum(&dolladr,dolc=argn-1);
+}
+
+freeargs(blk)
+       DOLPTR          blk;
+{
+       REG STRING      *argp;
+       REG DOLPTR      argr=0;
+       REG DOLPTR      argblk;
+
+       IF argblk=blk
+       THEN    argr = argblk->dolnxt;
+               IF (--argblk->doluse)==0
+               THEN    FOR argp=argblk->dolarg; Rcheat(*argp)!=ENDARGS; argp++
+                       DO free(*argp) OD
+                       free(argblk);
+               FI
+       FI
+       return(argr);
+}
+
+LOCAL STRING * copyargs(from, n)
+       STRING          from[];
+{
+       REG STRING *    np=alloc(sizeof(STRING*)*n+3*BYTESPERWORD);
+       REG STRING *    fp=from;
+       REG STRING *    pp=np;
+
+       np->doluse=1;   /* use count */
+       np=np->dolarg;
+       dolv=np;
+
+       WHILE n--
+       DO *np++ = make(*fp++) OD
+       *np++ = ENDARGS;
+       return(pp);
+}
+
+clearup()
+{
+       /* force `for' $* lists to go away */
+       WHILE argfor=freeargs(argfor) DONE
+
+       /* clean up io files */
+       WHILE pop() DONE
+}
+
+DOLPTR useargs()
+{
+       IF dolh
+       THEN    dolh->doluse++;
+               dolh->dolnxt=argfor;
+               return(argfor=dolh);
+       ELSE    return(0);
+       FI
+}
diff --git a/usr/src/cmd/sh/blok.c b/usr/src/cmd/sh/blok.c
new file mode 100644 (file)
index 0000000..df09ace
--- /dev/null
@@ -0,0 +1,111 @@
+#
+/*
+ *     UNIX shell
+ *
+ *     S. R. Bourne
+ *     Bell Telephone Laboratories
+ *
+ */
+
+#include       "defs.h"
+
+
+/*
+ *     storage allocator
+ *     (circular first fit strategy)
+ */
+
+#define BUSY 01
+#define busy(x)        (Rcheat((x)->word)&BUSY)
+
+POS            brkincr=BRKINCR;
+BLKPTR         blokp;                  /*current search pointer*/
+BLKPTR         bloktop=BLK(end);       /*top of arena (last blok)*/
+
+
+
+ADDRESS        alloc(nbytes)
+       POS             nbytes;
+{
+       REG POS         rbytes = round(nbytes+BYTESPERWORD,BYTESPERWORD);
+
+       LOOP    INT             c=0;
+               REG BLKPTR      p = blokp;
+               REG BLKPTR      q;
+               REP     IF !busy(p)
+                       THEN    WHILE !busy(q = p->word) DO p->word = q->word OD
+                               IF ADR(q)-ADR(p) >= rbytes
+                               THEN    blokp = BLK(ADR(p)+rbytes);
+                                       IF q > blokp
+                                       THEN    blokp->word = p->word;
+                                       FI
+                                       p->word=BLK(Rcheat(blokp)|BUSY);
+                                       return(ADR(p+1));
+                               FI
+                       FI
+                       q = p; p = BLK(Rcheat(p->word)&~BUSY);
+               PER     p>q ORF (c++)==0 DONE
+               addblok(rbytes);
+       POOL
+}
+
+VOID   addblok(reqd)
+       POS             reqd;
+{
+       IF stakbas!=staktop
+       THEN    REG STKPTR      rndstak;
+               REG BLKPTR      blokstak;
+
+               pushstak(0);
+               rndstak=round(staktop,BYTESPERWORD);
+               blokstak=BLK(stakbas)-1;
+               blokstak->word=stakbsy; stakbsy=blokstak;
+               bloktop->word=BLK(Rcheat(rndstak)|BUSY);
+               bloktop=BLK(rndstak);
+       FI
+       reqd += brkincr; reqd &= ~(brkincr-1);
+       blokp=bloktop;
+       bloktop=bloktop->word=BLK(Rcheat(bloktop)+reqd);
+       bloktop->word=BLK(ADR(end)+1);
+       BEGIN
+          REG STKPTR stakadr=STK(bloktop+2);
+          staktop=movstr(stakbot,stakadr);
+          stakbas=stakbot=stakadr;
+       END
+}
+
+VOID   free(ap)
+       BLKPTR          ap;
+{
+       REG BLKPTR      p;
+
+       IF (p=ap) ANDF p<bloktop
+       THEN    Lcheat((--p)->word) &= ~BUSY;
+       FI
+}
+
+#ifdef DEBUG
+chkbptr(ptr)
+       BLKPTR  ptr;
+{
+       INT             exf=0;
+       REG BLKPTR      p = end;
+       REG BLKPTR      q;
+       INT             us=0, un=0;
+
+       LOOP
+          q = Rcheat(p->word)&~BUSY;
+          IF p==ptr THEN exf++ FI
+          IF q<end ORF q>bloktop THEN abort(3) FI
+          IF p==bloktop THEN break FI
+          IF busy(p)
+          THEN us += q-p;
+          ELSE un += q-p;
+          FI
+          IF p>=q THEN abort(4) FI
+          p=q;
+       POOL
+       IF exf==0 THEN abort(1) FI
+       prn(un); prc(SP); prn(us); prc(NL);
+}
+#endif
diff --git a/usr/src/cmd/sh/brkincr.h b/usr/src/cmd/sh/brkincr.h
new file mode 100644 (file)
index 0000000..2c4c254
--- /dev/null
@@ -0,0 +1,2 @@
+#define BRKINCR 01000
+#define BRKMAX 04000
diff --git a/usr/src/cmd/sh/builtin.c b/usr/src/cmd/sh/builtin.c
new file mode 100644 (file)
index 0000000..9125740
--- /dev/null
@@ -0,0 +1,2 @@
+builtin()
+{return(0);}
diff --git a/usr/src/cmd/sh/cmd.c b/usr/src/cmd/sh/cmd.c
new file mode 100644 (file)
index 0000000..94c3337
--- /dev/null
@@ -0,0 +1,406 @@
+#
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Bell Telephone Laboratories
+ *
+ */
+
+#include       "defs.h"
+#include       "sym.h"
+
+PROC IOPTR     inout();
+PROC VOID      chkword();
+PROC VOID      chksym();
+PROC TREPTR    term();
+PROC TREPTR    makelist();
+PROC TREPTR    list();
+PROC REGPTR    syncase();
+PROC TREPTR    item();
+PROC VOID      skipnl();
+PROC VOID      prsym();
+PROC VOID      synbad();
+
+
+/* ========    command line decoding   ========*/
+
+
+
+
+TREPTR makefork(flgs, i)
+       INT             flgs;
+       TREPTR          i;
+{
+       REG TREPTR      t;
+
+       t=getstak(FORKTYPE);
+       t->forktyp=flgs|TFORK; t->forktre=i; t->forkio=0;
+       return(t);
+}
+
+LOCAL TREPTR   makelist(type,i,r)
+       INT             type;
+       TREPTR          i, r;
+{
+       REG TREPTR      t;
+
+       IF i==0 ORF r==0
+       THEN    synbad();
+       ELSE    t = getstak(LSTTYPE);
+               t->lsttyp = type;
+               t->lstlef = i; t->lstrit = r;
+       FI
+       return(t);
+}
+
+/*
+ * cmd
+ *     empty
+ *     list
+ *     list & [ cmd ]
+ *     list [ ; cmd ]
+ */
+
+TREPTR cmd(sym,flg)
+       REG INT         sym;
+       INT             flg;
+{
+       REG TREPTR      i, e;
+
+       i = list(flg);
+
+       IF wdval==NL
+       THEN    IF flg&NLFLG
+               THEN    wdval=';'; chkpr(NL);
+               FI
+       ELIF i==0 ANDF (flg&MTFLG)==0
+       THEN    synbad();
+       FI
+
+       SWITCH wdval IN
+
+           case '&':
+               IF i
+               THEN    i = makefork(FINT|FPRS|FAMP, i);
+               ELSE    synbad();
+               FI
+
+           case ';':
+               IF e=cmd(sym,flg|MTFLG)
+               THEN    i=makelist(TLST, i, e);
+               FI
+               break;
+
+           case EOFSYM:
+               IF sym==NL
+               THEN    break;
+               FI
+
+           default:
+               IF sym
+               THEN    chksym(sym);
+               FI
+
+       ENDSW
+       return(i);
+}
+
+/*
+ * list
+ *     term
+ *     list && term
+ *     list || term
+ */
+
+LOCAL TREPTR   list(flg)
+{
+       REG TREPTR      r;
+       REG INT         b;
+
+       r = term(flg);
+       WHILE r ANDF ((b=(wdval==ANDFSYM)) ORF wdval==ORFSYM)
+       DO      r = makelist((b ? TAND : TORF), r, term(NLFLG));
+       OD
+       return(r);
+}
+
+/*
+ * term
+ *     item
+ *     item |^ term
+ */
+
+LOCAL TREPTR   term(flg)
+{
+       REG TREPTR      t;
+
+       reserv++;
+       IF flg&NLFLG
+       THEN    skipnl();
+       ELSE    word();
+       FI
+
+       IF (t=item(TRUE)) ANDF (wdval=='^' ORF wdval=='|')
+       THEN    return(makelist(TFIL, makefork(FPOU,t), makefork(FPIN|FPCL,term(NLFLG))));
+       ELSE    return(t);
+       FI
+}
+
+LOCAL REGPTR   syncase(esym)
+       REG INT esym;
+{
+       skipnl();
+       IF wdval==esym
+       THEN    return(0);
+       ELSE    REG REGPTR      r=getstak(REGTYPE);
+               r->regptr=0;
+               LOOP wdarg->argnxt=r->regptr;
+                    r->regptr=wdarg;
+                    IF wdval ORF ( word()!=')' ANDF wdval!='|' )
+                    THEN synbad();
+                    FI
+                    IF wdval=='|'
+                    THEN word();
+                    ELSE break;
+                    FI
+               POOL
+               r->regcom=cmd(0,NLFLG|MTFLG);
+               IF wdval==ECSYM
+               THEN    r->regnxt=syncase(esym);
+               ELSE    chksym(esym);
+                       r->regnxt=0;
+               FI
+               return(r);
+       FI
+}
+
+/*
+ * item
+ *
+ *     ( cmd ) [ < in  ] [ > out ]
+ *     word word* [ < in ] [ > out ]
+ *     if ... then ... else ... fi
+ *     for ... while ... do ... done
+ *     case ... in ... esac
+ *     begin ... end
+ */
+
+LOCAL TREPTR   item(flag)
+       BOOL            flag;
+{
+       REG TREPTR      t;
+       REG IOPTR       io;
+
+       IF flag
+       THEN    io=inout((IOPTR)0);
+       ELSE    io=0;
+       FI
+
+       SWITCH wdval IN
+
+           case CASYM:
+               BEGIN
+                  t=getstak(SWTYPE);
+                  chkword();
+                  t->swarg=wdarg->argval;
+                  skipnl(); chksym(INSYM|BRSYM);
+                  t->swlst=syncase(wdval==INSYM?ESSYM:KTSYM);
+                  t->swtyp=TSW;
+                  break;
+               END
+
+           case IFSYM:
+               BEGIN
+                  REG INT      w;
+                  t=getstak(IFTYPE);
+                  t->iftyp=TIF;
+                  t->iftre=cmd(THSYM,NLFLG);
+                  t->thtre=cmd(ELSYM|FISYM|EFSYM,NLFLG);
+                  t->eltre=((w=wdval)==ELSYM ? cmd(FISYM,NLFLG) : (w==EFSYM ? (wdval=IFSYM, item(0)) : 0));
+                  IF w==EFSYM THEN return(t) FI
+                  break;
+               END
+
+           case FORSYM:
+               BEGIN
+                  t=getstak(FORTYPE);
+                  t->fortyp=TFOR;
+                  t->forlst=0;
+                  chkword();
+                  t->fornam=wdarg->argval;
+                  IF skipnl()==INSYM
+                  THEN chkword();
+                       t->forlst=item(0);
+                       IF wdval!=NL ANDF wdval!=';'
+                       THEN    synbad();
+                       FI
+                       chkpr(wdval); skipnl();
+                  FI
+                  chksym(DOSYM|BRSYM);
+                  t->fortre=cmd(wdval==DOSYM?ODSYM:KTSYM,NLFLG);
+                  break;
+               END
+
+           case WHSYM:
+           case UNSYM:
+               BEGIN
+                  t=getstak(WHTYPE);
+                  t->whtyp=(wdval==WHSYM ? TWH : TUN);
+                  t->whtre = cmd(DOSYM,NLFLG);
+                  t->dotre = cmd(ODSYM,NLFLG);
+                  break;
+               END
+
+           case BRSYM:
+               t=cmd(KTSYM,NLFLG);
+               break;
+
+           case '(':
+               BEGIN
+                  REG PARPTR    p;
+                  p=getstak(PARTYPE);
+                  p->partre=cmd(')',NLFLG);
+                  p->partyp=TPAR;
+                  t=makefork(0,p);
+                  break;
+               END
+
+           default:
+               IF io==0
+               THEN    return(0);
+               FI
+
+           case 0:
+               BEGIN
+                  REG ARGPTR   argp;
+                  REG ARGPTR   *argtail;
+                  REG ARGPTR   *argset=0;
+                  INT          keywd=1;
+                  t=getstak(COMTYPE);
+                  t->comio=io; /*initial io chain*/
+                  argtail = &(t->comarg);
+                  WHILE wdval==0
+                  DO   argp = wdarg;
+                       IF wdset ANDF keywd
+                       THEN    argp->argnxt=argset; argset=argp;
+                       ELSE    *argtail=argp; argtail = &(argp->argnxt); keywd=flags&keyflg;
+                       FI
+                       word();
+                       IF flag
+                       THEN t->comio=inout(t->comio);
+                       FI
+                  OD
+
+                  t->comtyp=TCOM; t->comset=argset; *argtail=0;
+                  return(t);
+               END
+
+       ENDSW
+       reserv++; word();
+       IF io=inout(io)
+       THEN    t=makefork(0,t); t->treio=io;
+       FI
+       return(t);
+}
+
+
+LOCAL VOID     skipnl()
+{
+       WHILE (reserv++, word()==NL) DO chkpr(NL) OD
+       return(wdval);
+}
+
+LOCAL IOPTR    inout(lastio)
+       IOPTR           lastio;
+{
+       REG INT         iof;
+       REG IOPTR       iop;
+       REG CHAR        c;
+
+       iof=wdnum;
+
+       SWITCH wdval IN
+
+           case DOCSYM:
+               iof |= IODOC; break;
+
+           case APPSYM:
+           case '>':
+               IF wdnum==0 THEN iof |= 1 FI
+               iof |= IOPUT;
+               IF wdval==APPSYM
+               THEN    iof |= IOAPP; break;
+               FI
+
+           case '<':
+               IF (c=nextc(0))=='&'
+               THEN    iof |= IOMOV;
+               ELIF c=='>'
+               THEN    iof |= IORDW;
+               ELSE    peekc=c|MARK;
+               FI
+               break;
+
+           default:
+               return(lastio);
+       ENDSW
+
+       chkword();
+       iop=getstak(IOTYPE); iop->ioname=wdarg->argval; iop->iofile=iof;
+       IF iof&IODOC
+       THEN iop->iolst=iopend; iopend=iop;
+       FI
+       word(); iop->ionxt=inout(lastio);
+       return(iop);
+}
+
+LOCAL VOID     chkword()
+{
+       IF word()
+       THEN    synbad();
+       FI
+}
+
+LOCAL VOID     chksym(sym)
+{
+       REG INT         x = sym&wdval;
+       IF ((x&SYMFLG) ? x : sym) != wdval
+       THEN    synbad();
+       FI
+}
+
+LOCAL VOID     prsym(sym)
+{
+       IF sym&SYMFLG
+       THEN    REG SYSPTR      sp=reserved;
+               WHILE sp->sysval
+                       ANDF sp->sysval!=sym
+               DO sp++ OD
+               prs(sp->sysnam);
+       ELIF sym==EOFSYM
+       THEN    prs(endoffile);
+       ELSE    IF sym&SYMREP THEN prc(sym) FI
+               IF sym==NL
+               THEN    prs("newline");
+               ELSE    prc(sym);
+               FI
+       FI
+}
+
+LOCAL VOID     synbad()
+{
+       prp(); prs(synmsg);
+       IF (flags&ttyflg)==0
+       THEN    prs(atline); prn(standin->flin);
+       FI
+       prs(colon);
+       prc(LQ);
+       IF wdval
+       THEN    prsym(wdval);
+       ELSE    prs(wdarg->argval);
+       FI
+       prc(RQ); prs(unexpected);
+       newline();
+       exitsh(SYNBAD);
+}
diff --git a/usr/src/cmd/sh/ctype.c b/usr/src/cmd/sh/ctype.c
new file mode 100644 (file)
index 0000000..63cebe5
--- /dev/null
@@ -0,0 +1,108 @@
+#
+/*
+ *     UNIX shell
+ *
+ *     S. R. Bourne
+ *     Bell Telephone Laboratories
+ *
+ */
+
+#include       "defs.h"
+
+char   _ctype1[] {
+/*     000     001     002     003     004     005     006     007     */
+       _EOF,   0,      0,      0,      0,      0,      0,      0,
+
+/*     bs      ht      nl      vt      np      cr      so      si      */
+       0,      _TAB,   _EOR,   0,      0,      0,      0,      0,
+
+       0,      0,      0,      0,      0,      0,      0,      0,
+
+       0,      0,      0,      0,      0,      0,      0,      0,
+
+/*     sp      !       "       #       $       %       &       '       */
+       _SPC,   0,      _DQU,   0,      _DOL1,  0,      _AMP,   0,
+
+/*     (       )       *       +       ,       -       .       /       */
+       _BRA,   _KET,   0,      0,      0,      0,      0,      0,
+
+/*     0       1       2       3       4       5       6       7       */
+       0,      0,      0,      0,      0,      0,      0,      0,
+
+/*     8       9       :       ;       <       =       >       ?       */
+       0,      0,      0,      _SEM,   _LT,    0,      _GT,    0,
+
+/*     @       A       B       C       D       E       F       G       */
+       0,      0,      0,      0,      0,      0,      0,      0,
+
+/*     H       I       J       K       L       M       N       O       */
+       0,      0,      0,      0,      0,      0,      0,      0,
+
+/*     P       Q       R       S       T       U       V       W       */
+       0,      0,      0,      0,      0,      0,      0,      0,
+
+/*     X       Y       Z       [       \       ]       ^       _       */
+       0,      0,      0,      0,      _BSL,   0,      _HAT,   0,
+
+/*     `       a       b       c       d       e       f       g       */
+       _LQU,   0,      0,      0,      0,      0,      0,      0,
+
+/*     h       i       j       k       l       m       n       o       */
+       0,      0,      0,      0,      0,      0,      0,      0,
+
+/*     p       q       r       s       t       u       v       w       */
+       0,      0,      0,      0,      0,      0,      0,      0,
+
+/*     x       y       z       {       |       }       ~       del     */
+       0,      0,      0,      0,      _BAR,   0,      0,      0
+};
+
+
+char   _ctype2[] {
+/*     000     001     002     003     004     005     006     007     */
+       0,      0,      0,      0,      0,      0,      0,      0,
+
+/*     bs      ht      nl      vt      np      cr      so      si      */
+       0,      0,      0,      0,      0,      0,      0,      0,
+
+       0,      0,      0,      0,      0,      0,      0,      0,
+
+       0,      0,      0,      0,      0,      0,      0,      0,
+
+/*     sp      !       "       #       $       %       &       '       */
+       0,      _PCS,   0,      _NUM,   _DOL2,  0,      0,      0,
+
+/*     (       )       *       +       ,       -       .       /       */
+       0,      0,      _AST,   _PLS,   0,      _MIN,   0,      0,
+
+/*     0       1       2       3       4       5       6       7       */
+       _DIG,   _DIG,   _DIG,   _DIG,   _DIG,   _DIG,   _DIG,   _DIG,
+
+/*     8       9       :       ;       <       =       >       ?       */
+       _DIG,   _DIG,   0,      0,      0,      _EQ,    0,      _QU,
+
+/*     @       A       B       C       D       E       F       G       */
+       _AT,    _UPC,   _UPC,   _UPC,   _UPC,   _UPC,   _UPC,   _UPC,
+
+/*     H       I       J       K       L       M       N       O       */
+       _UPC,   _UPC,   _UPC,   _UPC,   _UPC,   _UPC,   _UPC,   _UPC,
+
+/*     P       Q       R       S       T       U       V       W       */
+       _UPC,   _UPC,   _UPC,   _UPC,   _UPC,   _UPC,   _UPC,   _UPC,
+
+/*     X       Y       Z       [       \       ]       ^       _       */
+       _UPC,   _UPC,   _UPC,   _SQB,   0,      0,      0,      _UPC,
+
+/*     `       a       b       c       d       e       f       g       */
+       0,      _LPC,   _LPC,   _LPC,   _LPC,   _LPC,   _LPC,   _LPC,
+
+/*     h       i       j       k       l       m       n       o       */
+       _LPC,   _LPC,   _LPC,   _LPC,   _LPC,   _LPC,   _LPC,   _LPC,
+
+/*     p       q       r       s       t       u       v       w       */
+       _LPC,   _LPC,   _LPC,   _LPC,   _LPC,   _LPC,   _LPC,   _LPC,
+
+/*     x       y       z       {       |       }       ~       del     */
+       _LPC,   _LPC,   _LPC,   _CBR,   0,      _CKT,   0,      0
+};
+
diff --git a/usr/src/cmd/sh/ctype.h b/usr/src/cmd/sh/ctype.h
new file mode 100644 (file)
index 0000000..0566f7c
--- /dev/null
@@ -0,0 +1,90 @@
+#
+/*
+ *     UNIX shell
+ *
+ *     S. R. Bourne
+ *     Bell Telephone Laboratories
+ *
+ */
+
+
+/* table 1 */
+#define T_SUB  01
+#define T_MET  02
+#define        T_SPC   04
+#define T_DIP  010
+#define T_EOF  020
+#define T_EOR  040
+#define T_QOT  0100
+#define T_ESC  0200
+
+/* table 2 */
+#define T_BRC  01
+#define T_DEF  02
+#define T_AST  04
+#define        T_DIG   010
+#define T_FNG  020
+#define T_SHN  040
+#define        T_IDC   0100
+#define T_SET  0200
+
+/* for single chars */
+#define _TAB   (T_SPC)
+#define _SPC   (T_SPC)
+#define _UPC   (T_IDC)
+#define _LPC   (T_IDC)
+#define _DIG   (T_DIG)
+#define _EOF   (T_EOF)
+#define _EOR   (T_EOR)
+#define _BAR   (T_DIP)
+#define _HAT   (T_MET)
+#define _BRA   (T_MET)
+#define _KET   (T_MET)
+#define _SQB   (T_FNG)
+#define _AMP   (T_DIP)
+#define _SEM   (T_DIP)
+#define _LT    (T_DIP)
+#define _GT    (T_DIP)
+#define _LQU   (T_QOT|T_ESC)
+#define _BSL   (T_ESC)
+#define _DQU   (T_QOT)
+#define _DOL1  (T_SUB|T_ESC)
+
+#define _CBR   T_BRC
+#define _CKT   T_DEF
+#define _AST   (T_AST|T_FNG)
+#define _EQ    (T_DEF)
+#define _MIN   (T_DEF|T_SHN)
+#define _PCS   (T_SHN)
+#define _NUM   (T_SHN)
+#define _DOL2  (T_SHN)
+#define _PLS   (T_DEF|T_SET)
+#define _AT    (T_AST)
+#define _QU    (T_DEF|T_FNG|T_SHN)
+
+/* abbreviations for tests */
+#define _IDCH  (T_IDC|T_DIG)
+#define _META  (T_SPC|T_DIP|T_MET|T_EOR)
+
+char   _ctype1[];
+
+/* nb these args are not call by value !!!! */
+#define        space(c)        (((c)&QUOTE)==0 ANDF _ctype1[c]&(T_SPC))
+#define eofmeta(c)     (((c)&QUOTE)==0 ANDF _ctype1[c]&(_META|T_EOF))
+#define qotchar(c)     (((c)&QUOTE)==0 ANDF _ctype1[c]&(T_QOT))
+#define eolchar(c)     (((c)&QUOTE)==0 ANDF _ctype1[c]&(T_EOR|T_EOF))
+#define dipchar(c)     (((c)&QUOTE)==0 ANDF _ctype1[c]&(T_DIP))
+#define subchar(c)     (((c)&QUOTE)==0 ANDF _ctype1[c]&(T_SUB|T_QOT))
+#define escchar(c)     (((c)&QUOTE)==0 ANDF _ctype1[c]&(T_ESC))
+
+char   _ctype2[];
+
+#define        digit(c)        (((c)&QUOTE)==0 ANDF _ctype2[c]&(T_DIG))
+#define fngchar(c)     (((c)&QUOTE)==0 ANDF _ctype2[c]&(T_FNG))
+#define dolchar(c)     (((c)&QUOTE)==0 ANDF _ctype2[c]&(T_AST|T_BRC|T_DIG|T_IDC|T_SHN))
+#define defchar(c)     (((c)&QUOTE)==0 ANDF _ctype2[c]&(T_DEF))
+#define setchar(c)     (((c)&QUOTE)==0 ANDF _ctype2[c]&(T_SET))
+#define digchar(c)     (((c)&QUOTE)==0 ANDF _ctype2[c]&(T_AST|T_DIG))
+#define        letter(c)       (((c)&QUOTE)==0 ANDF _ctype2[c]&(T_IDC))
+#define alphanum(c)    (((c)&QUOTE)==0 ANDF _ctype2[c]&(_IDCH))
+#define astchar(c)     (((c)&QUOTE)==0 ANDF _ctype2[c]&(T_AST))
diff --git a/usr/src/cmd/sh/dup.h b/usr/src/cmd/sh/dup.h
new file mode 100644 (file)
index 0000000..4d65981
--- /dev/null
@@ -0,0 +1,10 @@
+#
+/*
+ *     UNIX shell
+ *
+ *     S. R. Bourne
+ *     Bell Telephone Laboratories
+ *
+ */
+
+#define DUPFLG 0100
diff --git a/usr/src/cmd/sh/error.c b/usr/src/cmd/sh/error.c
new file mode 100644 (file)
index 0000000..144aa66
--- /dev/null
@@ -0,0 +1,83 @@
+#
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Bell Telephone Laboratories
+ *
+ */
+
+#include       "defs.h"
+
+
+/* ========    error handling  ======== */
+
+exitset()
+{
+       assnum(&exitadr,exitval);
+}
+
+sigchk()
+{
+       /* Find out if it is time to go away.
+        * `trapnote' is set to SIGSET when fault is seen and
+        * no trap has been set.
+        */
+       IF trapnote&SIGSET
+       THEN    exitsh(SIGFAIL);
+       FI
+}
+
+failed(s1,s2)
+       STRING  s1, s2;
+{
+       prp(); prs(s1); 
+       IF s2
+       THEN    prs(colon); prs(s2);
+       FI
+       newline(); exitsh(ERROR);
+}
+
+error(s)
+       STRING  s;
+{
+       failed(s,NIL);
+}
+
+exitsh(xno)
+       INT     xno;
+{
+       /* Arrive here from `FATAL' errors
+        *  a) exit command,
+        *  b) default trap,
+        *  c) fault with no trap set.
+        *
+        * Action is to return to command level or exit.
+        */
+       exitval=xno;
+       IF (flags & (forked|errflg|ttyflg)) != ttyflg
+       THEN    done();
+       ELSE    clearup();
+               longjmp(errshell,1);
+       FI
+}
+
+done()
+{
+       REG STRING      t;
+       IF t=trapcom[0]
+       THEN    trapcom[0]=0; /*should free but not long */
+               execexp(t,0);
+       FI
+       rmtemp(0);
+       exit(exitval);
+}
+
+rmtemp(base)
+       IOPTR           base;
+{
+       WHILE iotemp>base
+       DO  unlink(iotemp->ioname);
+           iotemp=iotemp->iolst;
+       OD
+}
diff --git a/usr/src/cmd/sh/expand.c b/usr/src/cmd/sh/expand.c
new file mode 100644 (file)
index 0000000..dd96540
--- /dev/null
@@ -0,0 +1,190 @@
+#
+/*
+ *     UNIX shell
+ *
+ *     S. R. Bourne
+ *     Bell Telephone Laboratories
+ *
+ */
+
+#include       "defs.h"
+#include       <sys/types.h>
+#define DIRSIZ 15
+#include       <sys/stat.h>
+#include       <sys/dir.h>
+
+
+
+/* globals (file name generation)
+ *
+ * "*" in params matches r.e ".*"
+ * "?" in params matches r.e. "."
+ * "[...]" in params matches character class
+ * "[...a-z...]" in params matches a through z.
+ *
+ */
+
+PROC VOID      addg();
+
+
+INT    expand(as,rflg)
+       STRING          as;
+{
+       INT             count, dirf;
+       BOOL            dir=0;
+       STRING          rescan = 0;
+       REG STRING      s, cs;
+       ARGPTR          schain = gchain;
+       struct direct   entry;
+       STATBUF         statb;
+
+       IF trapnote&SIGSET THEN return(0); FI
+
+       s=cs=as; entry.d_name[DIRSIZ-1]=0; /* to end the string */
+
+       /* check for meta chars */
+       BEGIN
+          REG BOOL slash; slash=0;
+          WHILE !fngchar(*cs)
+          DO   IF *cs++==0
+               THEN    IF rflg ANDF slash THEN break; ELSE return(0) FI
+               ELIF *cs=='/'
+               THEN    slash++;
+               FI
+          OD
+       END
+
+       LOOP    IF cs==s
+               THEN    s=nullstr;
+                       break;
+               ELIF *--cs == '/'
+               THEN    *cs=0;
+                       IF s==cs THEN s="/" FI
+                       break;
+               FI
+       POOL
+       IF stat(s,&statb)>=0
+           ANDF (statb.st_mode&S_IFMT)==S_IFDIR
+           ANDF (dirf=open(s,0))>0
+       THEN    dir++;
+       FI
+       count=0;
+       IF *cs==0 THEN *cs++=0200 FI
+       IF dir
+       THEN    /* check for rescan */
+               REG STRING rs; rs=cs;
+
+               REP     IF *rs=='/' THEN rescan=rs; *rs=0; gchain=0 FI
+               PER     *rs++ DONE
+
+               WHILE read(dirf, &entry, 16) == 16 ANDF (trapnote&SIGSET) == 0
+               DO      IF entry.d_ino==0 ORF
+                           (*entry.d_name=='.' ANDF *cs!='.')
+                       THEN    continue;
+                       FI
+                       IF gmatch(entry.d_name, cs)
+                       THEN    addg(s,entry.d_name,rescan); count++;
+                       FI
+               OD
+               close(dirf);
+
+               IF rescan
+               THEN    REG ARGPTR      rchain;
+                       rchain=gchain; gchain=schain;
+                       IF count
+                       THEN    count=0;
+                               WHILE rchain
+                               DO      count += expand(rchain->argval,1);
+                                       rchain=rchain->argnxt;
+                               OD
+                       FI
+                       *rescan='/';
+               FI
+       FI
+
+       BEGIN
+          REG CHAR     c;
+          s=as;
+          WHILE c = *s
+          DO   *s++=(c&STRIP?c:'/') OD
+       END
+       return(count);
+}
+
+gmatch(s, p)
+       REG STRING      s, p;
+{
+       REG INT         scc;
+       CHAR            c;
+
+       IF scc = *s++
+       THEN    IF (scc &= STRIP)==0
+               THEN    scc=0200;
+               FI
+       FI
+       SWITCH c = *p++ IN
+
+           case '[':
+               {BOOL ok; INT lc;
+               ok=0; lc=077777;
+               WHILE c = *p++
+               DO      IF c==']'
+                       THEN    return(ok?gmatch(s,p):0);
+                       ELIF c==MINUS
+                       THEN    IF lc<=scc ANDF scc<=(*p++) THEN ok++ FI
+                       ELSE    IF scc==(lc=(c&STRIP)) THEN ok++ FI
+                       FI
+               OD
+               return(0);
+               }
+
+           default:
+               IF (c&STRIP)!=scc THEN return(0) FI
+
+           case '?':
+               return(scc?gmatch(s,p):0);
+
+           case '*':
+               IF *p==0 THEN return(1) FI
+               --s;
+               WHILE *s
+               DO  IF gmatch(s++,p) THEN return(1) FI OD
+               return(0);
+
+           case 0:
+               return(scc==0);
+       ENDSW
+}
+
+LOCAL VOID     addg(as1,as2,as3)
+       STRING          as1, as2, as3;
+{
+       REG STRING      s1, s2;
+       REG INT         c;
+
+       s2 = locstak()+BYTESPERWORD;
+
+       s1=as1;
+       WHILE c = *s1++
+       DO      IF (c &= STRIP)==0
+               THEN    *s2++='/';
+                       break;
+               FI
+               *s2++=c;
+       OD
+       s1=as2;
+       WHILE *s2 = *s1++ DO s2++ OD
+       IF s1=as3
+       THEN    *s2++='/';
+               WHILE *s2++ = *++s1 DONE
+       FI
+       makearg(endstak(s2));
+}
+
+makearg(args)
+       REG STRING      args;
+{
+       args->argnxt=gchain;
+       gchain=args;
+}
+
diff --git a/usr/src/cmd/sh/fault.c b/usr/src/cmd/sh/fault.c
new file mode 100644 (file)
index 0000000..9a60de3
--- /dev/null
@@ -0,0 +1,109 @@
+#
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Bell Telephone Laboratories
+ *
+ */
+
+#include       "defs.h"
+
+
+STRING         trapcom[MAXTRAP];
+BOOL           trapflg[MAXTRAP];
+
+/* ========    fault handling routines    ======== */
+
+
+VOID   fault(sig)
+       REG INT         sig;
+{
+       REG INT         flag;
+
+       signal(sig,fault);
+       IF sig==MEMF
+       THEN    IF setbrk(brkincr) == -1
+               THEN    error(nospace);
+               FI
+       ELIF sig==ALARM
+       THEN    IF flags&waiting
+               THEN    done();
+               FI
+       ELSE    flag = (trapcom[sig] ? TRAPSET : SIGSET);
+               trapnote |= flag;
+               trapflg[sig] |= flag;
+       FI
+}
+
+stdsigs()
+{
+       ignsig(QUIT);
+       getsig(INTR);
+       getsig(MEMF);
+       getsig(ALARM);
+}
+
+ignsig(n)
+{
+       REG INT         s, i;
+
+       IF (s=signal(i=n,1)&01)==0
+       THEN    trapflg[i] |= SIGMOD;
+       FI
+       return(s);
+}
+
+getsig(n)
+{
+       REG INT         i;
+
+       IF trapflg[i=n]&SIGMOD ORF ignsig(i)==0
+       THEN    signal(i,fault);
+       FI
+}
+
+oldsigs()
+{
+       REG INT         i;
+       REG STRING      t;
+
+       i=MAXTRAP;
+       WHILE i--
+       DO  t=trapcom[i];
+           IF t==0 ORF *t
+           THEN clrsig(i);
+           FI
+           trapflg[i]=0;
+       OD
+       trapnote=0;
+}
+
+clrsig(i)
+       INT             i;
+{
+       free(trapcom[i]); trapcom[i]=0;
+       IF trapflg[i]&SIGMOD
+       THEN    signal(i,fault);
+               trapflg[i] &= ~SIGMOD;
+       FI
+}
+
+chktrap()
+{
+       /* check for traps */
+       REG INT         i=MAXTRAP;
+       REG STRING      t;
+
+       trapnote &= ~TRAPSET;
+       WHILE --i
+       DO IF trapflg[i]&TRAPSET
+          THEN trapflg[i] &= ~TRAPSET;
+               IF t=trapcom[i]
+               THEN    INT     savxit=exitval;
+                       execexp(t,0);
+                       exitval=savxit; exitset();
+               FI
+          FI
+       OD
+}
diff --git a/usr/src/cmd/sh/mac.h b/usr/src/cmd/sh/mac.h
new file mode 100644 (file)
index 0000000..46f0ab1
--- /dev/null
@@ -0,0 +1,60 @@
+#
+/*
+ *     UNIX shell
+ *
+ *     S. R. Bourne
+ *     Bell Telephone Laboratories
+ *
+ */
+
+#define LOCAL  static
+#define PROC   extern
+#define TYPE   typedef
+#define STRUCT TYPE struct
+#define UNION  TYPE union
+#define REG    register
+
+#define IF     if(
+#define THEN   ){
+#define ELSE   } else {
+#define ELIF   } else if (
+#define FI     ;}
+
+#define BEGIN  {
+#define END    }
+#define SWITCH switch(
+#define IN     ){
+#define ENDSW  }
+#define FOR    for(
+#define WHILE  while(
+#define DO     ){
+#define OD     ;}
+#define REP    do{
+#define PER    }while(
+#define DONE   );
+#define LOOP   for(;;){
+#define POOL   }
+
+
+#define SKIP   ;
+#define DIV    /
+#define REM    %
+#define NEQ    ^
+#define ANDF   &&
+#define ORF    ||
+
+#define TRUE   (-1)
+#define FALSE  0
+#define LOBYTE 0377
+#define STRIP  0177
+#define QUOTE  0200
+
+#define EOF    0
+#define NL     '\n'
+#define SP     ' '
+#define LQ     '`'
+#define RQ     '\''
+#define MINUS  '-'
+#define COLON  ':'
+
+#define MAX(a,b)       ((a)>(b)?(a):(b))
diff --git a/usr/src/cmd/sh/macro.c b/usr/src/cmd/sh/macro.c
new file mode 100644 (file)
index 0000000..fd9b4eb
--- /dev/null
@@ -0,0 +1,233 @@
+#
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Bell Telephone Laboratories
+ *
+ */
+
+#include       "defs.h"
+#include       "sym.h"
+
+LOCAL CHAR     quote;  /* used locally */
+LOCAL CHAR     quoted; /* used locally */
+
+
+
+LOCAL STRING   copyto(endch)
+       REG CHAR        endch;
+{
+       REG CHAR        c;
+
+       WHILE (c=getch(endch))!=endch ANDF c
+       DO pushstak(c|quote) OD
+       zerostak();
+       IF c!=endch THEN error(badsub) FI
+}
+
+LOCAL  skipto(endch)
+       REG CHAR        endch;
+{
+       /* skip chars up to } */
+       REG CHAR        c;
+       WHILE (c=readc()) ANDF c!=endch
+       DO      SWITCH c IN
+
+               case SQUOTE:    skipto(SQUOTE); break;
+
+               case DQUOTE:    skipto(DQUOTE); break;
+
+               case DOLLAR:    IF readc()==BRACE
+                               THEN    skipto('}');
+                               FI
+               ENDSW
+       OD
+       IF c!=endch THEN error(badsub) FI
+}
+
+LOCAL  getch(endch)
+       CHAR            endch;
+{
+       REG CHAR        d;
+
+retry:
+       d=readc();
+       IF !subchar(d)
+       THEN    return(d);
+       FI
+       IF d==DOLLAR
+       THEN    REG INT c;
+               IF (c=readc(), dolchar(c))
+               THEN    NAMPTR          n=NIL;
+                       INT             dolg=0;
+                       BOOL            bra;
+                       REG STRING      argp, v;
+                       CHAR            idb[2];
+                       STRING          id=idb;
+
+                       IF bra=(c==BRACE) THEN c=readc() FI
+                       IF letter(c)
+                       THEN    argp=relstak();
+                               WHILE alphanum(c) DO pushstak(c); c=readc() OD
+                               zerostak();
+                               n=lookup(absstak(argp)); setstak(argp);
+                               v = n->namval; id = n->namid;
+                               peekc = c|MARK;;
+                       ELIF digchar(c)
+                       THEN    *id=c; idb[1]=0;
+                               IF astchar(c)
+                               THEN    dolg=1; c='1';
+                               FI
+                               c -= '0';
+                               v=((c==0) ? cmdadr : (c<=dolc) ? dolv[c] : (dolg=0));
+                       ELIF c=='$'
+                       THEN    v=pidadr;
+                       ELIF c=='!'
+                       THEN    v=pcsadr;
+                       ELIF c=='#'
+                       THEN    v=dolladr;
+                       ELIF c=='?'
+                       THEN    v=exitadr;
+                       ELIF c=='-'
+                       THEN    v=flagadr;
+                       ELIF bra THEN error(badsub);
+                       ELSE    goto retry;
+                       FI
+                       c = readc();
+                       IF !defchar(c) ANDF bra
+                       THEN    error(badsub);
+                       FI
+                       argp=0;
+                       IF bra
+                       THEN    IF c!='}'
+                               THEN    argp=relstak();
+                                       IF (v==0)NEQ(setchar(c))
+                                       THEN    copyto('}');
+                                       ELSE    skipto('}');
+                                       FI
+                                       argp=absstak(argp);
+                               FI
+                       ELSE    peekc = c|MARK; c = 0;
+                       FI
+                       IF v
+                       THEN    IF c!='+'
+                               THEN    LOOP WHILE c = *v++
+                                            DO pushstak(c|quote); OD
+                                            IF dolg==0 ORF (++dolg>dolc)
+                                            THEN break;
+                                            ELSE v=dolv[dolg]; pushstak(SP|(*id=='*' ? quote : 0));
+                                            FI
+                                       POOL
+                               FI
+                       ELIF argp
+                       THEN    IF c=='?'
+                               THEN    failed(id,*argp?argp:badparam);
+                               ELIF c=='='
+                               THEN    IF n
+                                       THEN    assign(n,argp);
+                                       ELSE    error(badsub);
+                                       FI
+                               FI
+                       ELIF flags&setflg
+                       THEN    failed(id,badparam);
+                       FI
+                       goto retry;
+               ELSE    peekc=c|MARK;
+               FI
+       ELIF d==endch
+       THEN    return(d);
+       ELIF d==SQUOTE
+       THEN    comsubst(); goto retry;
+       ELIF d==DQUOTE
+       THEN    quoted++; quote^=QUOTE; goto retry;
+       FI
+       return(d);
+}
+
+STRING macro(as)
+       STRING          as;
+{
+       /* Strip "" and do $ substitution
+        * Leaves result on top of stack
+        */
+       REG BOOL        savqu =quoted;
+       REG CHAR        savq = quote;
+       FILEHDR         fb;
+
+       push(&fb); estabf(as);
+       usestak();
+       quote=0; quoted=0;
+       copyto(0);
+       pop();
+       IF quoted ANDF (stakbot==staktop) THEN pushstak(QUOTE) FI
+       quote=savq; quoted=savqu;
+       return(fixstak());
+}
+
+LOCAL  comsubst()
+{
+       /* command substn */
+       FILEBLK         cb;
+       REG CHAR        d;
+       REG STKPTR      savptr = fixstak();
+
+       usestak();
+       WHILE (d=readc())!=SQUOTE ANDF d
+       DO pushstak(d) OD
+
+       BEGIN
+          REG STRING   argc;
+          trim(argc=fixstak());
+          push(&cb); estabf(argc);
+       END
+       BEGIN
+          REG TREPTR   t = makefork(FPOU,cmd(EOFSYM,MTFLG|NLFLG));
+          INT          pv[2];
+
+          /* this is done like this so that the pipe
+           * is open only when needed
+           */
+          chkpipe(pv);
+          initf(pv[INPIPE]);
+          execute(t, 0, 0, pv);
+          close(pv[OTPIPE]);
+       END
+       tdystak(savptr); staktop=movstr(savptr,stakbot);
+       WHILE d=readc() DO pushstak(d|quote) OD
+       await(0);
+       WHILE stakbot!=staktop
+       DO      IF (*--staktop&STRIP)!=NL
+               THEN    ++staktop; break;
+               FI
+       OD
+       pop();
+}
+
+#define CPYSIZ 512
+
+subst(in,ot)
+       INT             in, ot;
+{
+       REG CHAR        c;
+       FILEBLK         fb;
+       REG INT         count=CPYSIZ;
+
+       push(&fb); initf(in);
+       /* DQUOTE used to stop it from quoting */
+       WHILE c=(getch(DQUOTE)&STRIP)
+       DO pushstak(c);
+          IF --count == 0
+          THEN flush(ot); count=CPYSIZ;
+          FI
+       OD
+       flush(ot);
+       pop();
+}
+
+LOCAL  flush(ot)
+{
+       write(ot,stakbot,staktop-stakbot);
+       IF flags&execpr THEN write(output,stakbot,staktop-stakbot) FI
+       staktop=stakbot;
+}
diff --git a/usr/src/cmd/sh/mode.h b/usr/src/cmd/sh/mode.h
new file mode 100644 (file)
index 0000000..4fb3a52
--- /dev/null
@@ -0,0 +1,205 @@
+#
+/*
+ *     UNIX shell
+ */
+
+
+#define BYTESPERWORD   (sizeof(char *))
+
+TYPE char      CHAR;
+TYPE char      BOOL;
+TYPE int       UFD;
+TYPE int       INT;
+TYPE float     REAL;
+TYPE char      *ADDRESS;
+TYPE long int  L_INT;
+TYPE int       VOID;
+TYPE unsigned  POS;
+TYPE char      *STRING;
+TYPE char      MSG[];
+TYPE int       PIPE[];
+TYPE char      *STKPTR;
+TYPE char      *BYTPTR;
+
+STRUCT stat    STATBUF;        /* defined in /usr/sys/stat.h */
+STRUCT blk     *BLKPTR;
+STRUCT fileblk FILEBLK;
+STRUCT filehdr FILEHDR;
+STRUCT fileblk *FILE;
+STRUCT trenod  *TREPTR;
+STRUCT forknod *FORKPTR;
+STRUCT comnod  *COMPTR;
+STRUCT swnod   *SWPTR;
+STRUCT regnod  *REGPTR;
+STRUCT parnod  *PARPTR;
+STRUCT ifnod   *IFPTR;
+STRUCT whnod   *WHPTR;
+STRUCT fornod  *FORPTR;
+STRUCT lstnod  *LSTPTR;
+STRUCT argnod  *ARGPTR;
+STRUCT dolnod  *DOLPTR;
+STRUCT ionod   *IOPTR;
+STRUCT namnod  NAMNOD;
+STRUCT namnod  *NAMPTR;
+STRUCT sysnod  SYSNOD;
+STRUCT sysnod  *SYSPTR;
+STRUCT sysnod  SYSTAB[];
+#define NIL    ((char*)0)
+
+
+/* the following nonsense is required
+ * because casts turn an Lvalue
+ * into an Rvalue so two cheats
+ * are necessary, one for each context.
+ */
+union { int _cheat;};
+#define Lcheat(a)      ((a)._cheat)
+#define Rcheat(a)      ((int)(a))
+
+
+/* address puns for storage allocation */
+UNION {
+       FORKPTR _forkptr;
+       COMPTR  _comptr;
+       PARPTR  _parptr;
+       IFPTR   _ifptr;
+       WHPTR   _whptr;
+       FORPTR  _forptr;
+       LSTPTR  _lstptr;
+       BLKPTR  _blkptr;
+       NAMPTR  _namptr;
+       BYTPTR  _bytptr;
+       }       address;
+
+
+/* for functions that do not return values */
+struct void {INT vvvvvvvv;};
+
+
+/* heap storage */
+struct blk {
+       BLKPTR  word;
+};
+
+#define        BUFSIZ  64
+struct fileblk {
+       UFD     fdes;
+       POS     flin;
+       BOOL    feof;
+       CHAR    fsiz;
+       STRING  fnxt;
+       STRING  fend;
+       STRING  *feval;
+       FILE    fstak;
+       CHAR    fbuf[BUFSIZ];
+};
+
+/* for files not used with file descriptors */
+struct filehdr {
+       UFD     fdes;
+       POS     flin;
+       BOOL    feof;
+       CHAR    fsiz;
+       STRING  fnxt;
+       STRING  fend;
+       STRING  *feval;
+       FILE    fstak;
+       CHAR    _fbuf[1];
+};
+
+struct sysnod {
+       STRING  sysnam;
+       INT     sysval;
+};
+
+/* this node is a proforma for those that follow */
+struct trenod {
+       INT     tretyp;
+       IOPTR   treio;
+};
+
+/* dummy for access only */
+struct argnod {
+       ARGPTR  argnxt;
+       CHAR    argval[1];
+};
+
+struct dolnod {
+       DOLPTR  dolnxt;
+       INT     doluse;
+       CHAR    dolarg[1];
+};
+
+struct forknod {
+       INT     forktyp;
+       IOPTR   forkio;
+       TREPTR  forktre;
+};
+
+struct comnod {
+       INT     comtyp;
+       IOPTR   comio;
+       ARGPTR  comarg;
+       ARGPTR  comset;
+};
+
+struct ifnod {
+       INT     iftyp;
+       TREPTR  iftre;
+       TREPTR  thtre;
+       TREPTR  eltre;
+};
+
+struct whnod {
+       INT     whtyp;
+       TREPTR  whtre;
+       TREPTR  dotre;
+};
+
+struct fornod {
+       INT     fortyp;
+       TREPTR  fortre;
+       STRING  fornam;
+       COMPTR  forlst;
+};
+
+struct swnod {
+       INT     swtyp;
+       STRING  swarg;
+       REGPTR  swlst;
+};
+
+struct regnod {
+       ARGPTR  regptr;
+       TREPTR  regcom;
+       REGPTR  regnxt;
+};
+
+struct parnod {
+       INT     partyp;
+       TREPTR  partre;
+};
+
+struct lstnod {
+       INT     lsttyp;
+       TREPTR  lstlef;
+       TREPTR  lstrit;
+};
+
+struct ionod {
+       INT     iofile;
+       STRING  ioname;
+       IOPTR   ionxt;
+       IOPTR   iolst;
+};
+
+#define        FORKTYPE        (sizeof(struct forknod))
+#define        COMTYPE         (sizeof(struct comnod))
+#define        IFTYPE          (sizeof(struct ifnod))
+#define        WHTYPE          (sizeof(struct whnod))
+#define        FORTYPE         (sizeof(struct fornod))
+#define        SWTYPE          (sizeof(struct swnod))
+#define        REGTYPE         (sizeof(struct regnod))
+#define        PARTYPE         (sizeof(struct parnod))
+#define        LSTTYPE         (sizeof(struct lstnod))
+#define        IOTYPE          (sizeof(struct ionod))
diff --git a/usr/src/cmd/sh/name.c b/usr/src/cmd/sh/name.c
new file mode 100644 (file)
index 0000000..6567b55
--- /dev/null
@@ -0,0 +1,320 @@
+#
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Bell Telephone Laboratories
+ *
+ */
+
+#include       "defs.h"
+
+PROC BOOL      chkid();
+
+
+NAMNOD ps2nod  = {     NIL,            NIL,            ps2name},
+       fngnod  = {     NIL,            NIL,            fngname},
+       pathnod = {     NIL,            NIL,            pathname},
+       ifsnod  = {     NIL,            NIL,            ifsname},
+       ps1nod  = {     &pathnod,       &ps2nod,        ps1name},
+       homenod = {     &fngnod,        &ifsnod,        homename},
+       mailnod = {     &homenod,       &ps1nod,        mailname};
+
+NAMPTR         namep = &mailnod;
+
+
+/* ========    variable and string handling    ======== */
+
+syslook(w,syswds)
+       STRING          w;
+       SYSTAB          syswds;
+{
+       REG CHAR        first;
+       REG STRING      s;
+       REG SYSPTR      syscan;
+
+       syscan=syswds; first = *w;
+
+       WHILE s=syscan->sysnam
+       DO  IF first == *s
+               ANDF eq(w,s)
+           THEN return(syscan->sysval);
+           FI
+           syscan++;
+       OD
+       return(0);
+}
+
+setlist(arg,xp)
+       REG ARGPTR      arg;
+       INT             xp;
+{
+       WHILE arg
+       DO REG STRING   s=mactrim(arg->argval);
+          setname(s, xp);
+          arg=arg->argnxt;
+          IF flags&execpr
+          THEN prs(s);
+               IF arg THEN blank(); ELSE newline(); FI
+          FI
+       OD
+}
+
+VOID   setname(argi, xp)
+       STRING          argi;
+       INT             xp;
+{
+       REG STRING      argscan=argi;
+       REG NAMPTR      n;
+
+       IF letter(*argscan)
+       THEN    WHILE alphanum(*argscan) DO argscan++ OD
+               IF *argscan=='='
+               THEN    *argscan = 0;
+                       n=lookup(argi);
+                       *argscan++ = '=';
+                       attrib(n, xp);
+                       IF xp&N_ENVNAM
+                       THEN    n->namenv = n->namval = argscan;
+                       ELSE    assign(n, argscan);
+                       FI
+                       return;
+               FI
+       FI
+       failed(argi,notid);
+}
+
+replace(a, v)
+       REG STRING      *a;
+       STRING          v;
+{
+       free(*a); *a=make(v);
+}
+
+dfault(n,v)
+       NAMPTR          n;
+       STRING          v;
+{
+       IF n->namval==0
+       THEN    assign(n,v)
+       FI
+}
+
+assign(n,v)
+       NAMPTR          n;
+       STRING          v;
+{
+       IF n->namflg&N_RDONLY
+       THEN    failed(n->namid,wtfailed);
+       ELSE    replace(&n->namval,v);
+       FI
+}
+
+INT    readvar(names)
+       STRING          *names;
+{
+       FILEBLK         fb;
+       REG FILE        f = &fb;
+       REG CHAR        c;
+       REG INT         rc=0;
+       NAMPTR          n=lookup(*names++); /* done now to avoid storage mess */
+       STKPTR          rel=relstak();
+
+       push(f); initf(dup(0));
+       IF lseek(0,0L,1)==-1
+       THEN    f->fsiz=1;
+       FI
+
+       LOOP    c=nextc(0);
+               IF (*names ANDF any(c, ifsnod.namval)) ORF eolchar(c)
+               THEN    zerostak();
+                       assign(n,absstak(rel)); setstak(rel);
+                       IF *names
+                       THEN    n=lookup(*names++);
+                       ELSE    n=0;
+                       FI
+                       IF eolchar(c)
+                       THEN    break;
+                       FI
+               ELSE    pushstak(c);
+               FI
+       POOL
+       WHILE n
+       DO assign(n, nullstr);
+          IF *names THEN n=lookup(*names++); ELSE n=0; FI
+       OD
+
+       IF eof THEN rc=1 FI
+       lseek(0, (long)(f->fnxt-f->fend), 1);
+       pop();
+       return(rc);
+}
+
+assnum(p, i)
+       STRING          *p;
+       INT             i;
+{
+       itos(i); replace(p,numbuf);
+}
+
+STRING make(v)
+       STRING          v;
+{
+       REG STRING      p;
+
+       IF v
+       THEN    movstr(v,p=alloc(length(v)));
+               return(p);
+       ELSE    return(0);
+       FI
+}
+
+
+NAMPTR         lookup(nam)
+       REG STRING      nam;
+{
+       REG NAMPTR      nscan=namep;
+       REG NAMPTR      *prev;
+       INT             LR;
+
+       IF !chkid(nam)
+       THEN    failed(nam,notid);
+       FI
+       WHILE nscan
+       DO      IF (LR=cf(nam,nscan->namid))==0
+               THEN    return(nscan);
+               ELIF LR<0
+               THEN    prev = &(nscan->namlft);
+               ELSE    prev = &(nscan->namrgt);
+               FI
+               nscan = *prev;
+       OD
+
+       /* add name node */
+       nscan=alloc(sizeof *nscan);
+       nscan->namlft=nscan->namrgt=NIL;
+       nscan->namid=make(nam);
+       nscan->namval=0; nscan->namflg=N_DEFAULT; nscan->namenv=0;
+       return(*prev = nscan);
+}
+
+LOCAL BOOL     chkid(nam)
+       STRING          nam;
+{
+       REG CHAR *      cp=nam;
+
+       IF !letter(*cp)
+       THEN    return(FALSE);
+       ELSE    WHILE *++cp
+               DO IF !alphanum(*cp)
+                  THEN return(FALSE);
+                  FI
+               OD
+       FI
+       return(TRUE);
+}
+
+LOCAL VOID (*namfn)();
+namscan(fn)
+       VOID            (*fn)();
+{
+       namfn=fn;
+       namwalk(namep);
+}
+
+LOCAL VOID     namwalk(np)
+       REG NAMPTR      np;
+{
+       IF np
+       THEN    namwalk(np->namlft);
+               (*namfn)(np);
+               namwalk(np->namrgt);
+       FI
+}
+
+VOID   printnam(n)
+       NAMPTR          n;
+{
+       REG STRING      s;
+
+       sigchk();
+       IF s=n->namval
+       THEN    prs(n->namid);
+               prc('='); prs(s);
+               newline();
+       FI
+}
+
+LOCAL STRING   staknam(n)
+       REG NAMPTR      n;
+{
+       REG STRING      p;
+
+       p=movstr(n->namid,staktop);
+       p=movstr("=",p);
+       p=movstr(n->namval,p);
+       return(getstak(p+1-ADR(stakbot)));
+}
+
+VOID   exname(n)
+       REG NAMPTR      n;
+{
+       IF n->namflg&N_EXPORT
+       THEN    free(n->namenv);
+               n->namenv = make(n->namval);
+       ELSE    free(n->namval);
+               n->namval = make(n->namenv);
+       FI
+}
+
+VOID   printflg(n)
+       REG NAMPTR              n;
+{
+       IF n->namflg&N_EXPORT
+       THEN    prs(export); blank();
+       FI
+       IF n->namflg&N_RDONLY
+       THEN    prs(readonly); blank();
+       FI
+       IF n->namflg&(N_EXPORT|N_RDONLY)
+       THEN    prs(n->namid); newline();
+       FI
+}
+
+VOID   getenv()
+{
+       REG STRING      *e=environ;
+
+       WHILE *e
+       DO setname(*e++, N_ENVNAM) OD
+}
+
+LOCAL INT      namec;
+
+VOID   countnam(n)
+       NAMPTR          n;
+{
+       namec++;
+}
+
+LOCAL STRING   *argnam;
+
+VOID   pushnam(n)
+       NAMPTR          n;
+{
+       IF n->namval
+       THEN    *argnam++ = staknam(n);
+       FI
+}
+
+STRING *setenv()
+{
+       REG STRING      *er;
+
+       namec=0;
+       namscan(countnam);
+       argnam = er = getstak(namec*BYTESPERWORD+BYTESPERWORD);
+       namscan(pushnam);
+       *argnam++ = 0;
+       return(er);
+}
diff --git a/usr/src/cmd/sh/name.h b/usr/src/cmd/sh/name.h
new file mode 100644 (file)
index 0000000..4686107
--- /dev/null
@@ -0,0 +1,25 @@
+#
+/*
+ *     UNIX shell
+ *
+ *     S. R. Bourne
+ *     Bell Telephone Laboratories
+ *
+ */
+
+
+#define N_RDONLY 0100000
+#define N_EXPORT 0040000
+#define N_ENVNAM 0020000
+#define N_ENVPOS 0007777
+
+#define N_DEFAULT 0
+
+struct namnod {
+       NAMPTR  namlft;
+       NAMPTR  namrgt;
+       STRING  namid;
+       STRING  namval;
+       STRING  namenv;
+       INT     namflg;
+};
diff --git a/usr/src/cmd/sh/print.c b/usr/src/cmd/sh/print.c
new file mode 100644 (file)
index 0000000..740268e
--- /dev/null
@@ -0,0 +1,97 @@
+#
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Bell Telephone Laboratories
+ *
+ */
+
+#include       "defs.h"
+
+CHAR           numbuf[6];
+
+
+/* printing and io conversion */
+
+newline()
+{      prc(NL);
+}
+
+blank()
+{      prc(SP);
+}
+
+prp()
+{
+       IF (flags&prompt)==0 ANDF cmdadr
+       THEN    prs(cmdadr); prs(colon);
+       FI
+}
+
+VOID   prs(as)
+       STRING          as;
+{
+       REG STRING      s;
+
+       IF s=as
+       THEN    write(output,s,length(s)-1);
+       FI
+}
+
+VOID   prc(c)
+       CHAR            c;
+{
+       IF c
+       THEN    write(output,&c,1);
+       FI
+}
+
+prt(t)
+       L_INT           t;
+{
+       REG INT hr, min, sec;
+
+       t += 30; t /= 60;
+       sec=t%60; t /= 60;
+       min=t%60;
+       IF hr=t/60
+       THEN    prn(hr); prc('h');
+       FI
+       prn(min); prc('m');
+       prn(sec); prc('s');
+}
+
+prn(n)
+       INT             n;
+{
+       itos(n); prs(numbuf);
+}
+
+itos(n)
+{
+       REG char *abuf; REG POS a, i; INT pr, d;
+       abuf=numbuf; pr=FALSE; a=n;
+       FOR i=10000; i!=1; i/=10
+       DO      IF (pr |= (d=a/i)) THEN *abuf++=d+'0' FI
+               a %= i;
+       OD
+       *abuf++=a+'0';
+       *abuf++=0;
+}
+
+stoi(icp)
+STRING icp;
+{
+       REG CHAR        *cp = icp;
+       REG INT         r = 0;
+       REG CHAR        c;
+
+       WHILE (c = *cp, digit(c)) ANDF c ANDF r>=0
+       DO r = r*10 + c - '0'; cp++ OD
+       IF r<0 ORF cp==icp
+       THEN    failed(icp,badnum);
+       ELSE    return(r);
+       FI
+}
+
diff --git a/usr/src/cmd/sh/setbrk.c b/usr/src/cmd/sh/setbrk.c
new file mode 100644 (file)
index 0000000..84745c7
--- /dev/null
@@ -0,0 +1,17 @@
+#
+/*
+ *     UNIX shell
+ *
+ *     S. R. Bourne
+ *     Bell Telephone Laboratories
+ *
+ */
+
+#include       "defs.h"
+
+setbrk(incr)
+{
+       REG BYTPTR      a=sbrk(incr);
+       brkend=a+incr;
+       return(a);
+}
diff --git a/usr/src/cmd/sh/stak.c b/usr/src/cmd/sh/stak.c
new file mode 100644 (file)
index 0000000..ed36f08
--- /dev/null
@@ -0,0 +1,81 @@
+#
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Bell Telephone Laboratories
+ *
+ */
+
+#include       "defs.h"
+
+STKPTR         stakbot=nullstr;
+
+
+
+/* ========    storage allocation      ======== */
+
+STKPTR getstak(asize)
+       INT             asize;
+{      /* allocate requested stack */
+       REG STKPTR      oldstak;
+       REG INT         size;
+
+       size=round(asize,BYTESPERWORD);
+       oldstak=stakbot;
+       staktop = stakbot += size;
+       return(oldstak);
+}
+
+STKPTR locstak()
+{      /* set up stack for local use
+        * should be followed by `endstak'
+        */
+       IF brkend-stakbot<BRKINCR
+       THEN    setbrk(brkincr);
+               IF brkincr < BRKMAX
+               THEN    brkincr += 256;
+               FI
+       FI
+       return(stakbot);
+}
+
+STKPTR savstak()
+{
+       assert(staktop==stakbot);
+       return(stakbot);
+}
+
+STKPTR endstak(argp)
+       REG STRING      argp;
+{      /* tidy up after `locstak' */
+       REG STKPTR      oldstak;
+       *argp++=0;
+       oldstak=stakbot; stakbot=staktop=round(argp,BYTESPERWORD);
+       return(oldstak);
+}
+
+VOID   tdystak(x)
+       REG STKPTR      x;
+{
+       /* try to bring stack back to x */
+       WHILE ADR(stakbsy)>ADR(x)
+       DO free(stakbsy);
+          stakbsy = stakbsy->word;
+       OD
+       staktop=stakbot=max(ADR(x),ADR(stakbas));
+       rmtemp(x);
+}
+
+stakchk()
+{
+       IF (brkend-stakbas)>BRKINCR+BRKINCR
+       THEN    setbrk(-BRKINCR);
+       FI
+}
+
+STKPTR cpystak(x)
+       STKPTR          x;
+{
+       return(endstak(movstr(x,locstak())));
+}
diff --git a/usr/src/cmd/sh/stak.h b/usr/src/cmd/sh/stak.h
new file mode 100644 (file)
index 0000000..09b853d
--- /dev/null
@@ -0,0 +1,76 @@
+#
+/*
+ *     UNIX shell
+ *
+ *     S. R. Bourne
+ *     Bell Telephone Laboratories
+ *
+ */
+
+/* To use stack as temporary workspace across
+ * possible storage allocation (eg name lookup)
+ * a) get ptr from `relstak'
+ * b) can now use `pushstak'
+ * c) then reset with `setstak'
+ * d) `absstak' gives real address if needed
+ */
+#define                relstak()       (staktop-stakbot)
+#define                absstak(x)      (stakbot+Rcheat(x))
+#define                setstak(x)      (staktop=absstak(x))
+#define                pushstak(c)     (*staktop++=(c))
+#define                zerostak()      (*staktop=0)
+
+/* Used to address an item left on the top of
+ * the stack (very temporary)
+ */
+#define                curstak()       (staktop)
+
+/* `usestak' before `pushstak' then `fixstak'
+ * These routines are safe against heap
+ * being allocated.
+ */
+#define                usestak()       {locstak();}
+
+/* for local use only since it hands
+ * out a real address for the stack top
+ */
+STKPTR         locstak();
+
+/* Will allocate the item being used and return its
+ * address (safe now).
+ */
+#define                fixstak()       endstak(staktop)
+
+/* For use after `locstak' to hand back
+ * new stack top and then allocate item
+ */
+STKPTR         endstak();
+
+/* Copy a string onto the stack and
+ * allocate the space.
+ */
+STKPTR         cpystak();
+
+/* Allocate given ammount of stack space */
+STKPTR         getstak();
+
+/* A chain of ptrs of stack blocks that
+ * have become covered by heap allocation.
+ * `tdystak' will return them to the heap.
+ */
+BLKPTR         stakbsy;
+
+/* Base of the entire stack */
+STKPTR         stakbas;
+
+/* Top of entire stack */
+STKPTR         brkend;
+
+/* Base of current item */
+STKPTR         stakbot;
+
+/* Top of current item */
+STKPTR         staktop;
+
+/* Used with tdystak */
+STKPTR         savstak();
diff --git a/usr/src/cmd/sh/string.c b/usr/src/cmd/sh/string.c
new file mode 100644 (file)
index 0000000..5ad20e8
--- /dev/null
@@ -0,0 +1,55 @@
+#
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Bell Telephone Laboratories
+ *
+ */
+
+#include       "defs.h"
+
+
+/* ========    general purpose string handling ======== */
+
+
+STRING movstr(a,b)
+       REG STRING      a, b;
+{
+       WHILE *b++ = *a++ DONE
+       return(--b);
+}
+
+INT    any(c,s)
+       REG CHAR        c;
+       STRING          s;
+{
+       REG CHAR d;
+
+       WHILE d = *s++
+       DO      IF d==c
+               THEN    return(TRUE);
+               FI
+       OD
+       return(FALSE);
+}
+
+INT    cf(s1, s2)
+       REG STRING s1, s2;
+{
+       WHILE *s1++ == *s2
+       DO      IF *s2++==0
+               THEN    return(0);
+               FI
+       OD
+       return(*--s1 - *s2);
+}
+
+INT    length(as)
+       STRING as;
+{
+       REG STRING s;
+
+       IF s=as THEN WHILE *s++ DONE FI
+       return(s-as);
+}
diff --git a/usr/src/cmd/sh/sym.h b/usr/src/cmd/sh/sym.h
new file mode 100644 (file)
index 0000000..0ed5623
--- /dev/null
@@ -0,0 +1,46 @@
+#
+/*
+ *     UNIX shell
+ */
+
+
+/* symbols for parsing */
+#define DOSYM  0405
+#define FISYM  0420
+#define EFSYM  0422
+#define ELSYM  0421
+#define INSYM  0412
+#define BRSYM  0406
+#define KTSYM  0450
+#define THSYM  0444
+#define ODSYM  0441
+#define ESSYM  0442
+#define IFSYM  0436
+#define FORSYM 0435
+#define WHSYM  0433
+#define UNSYM  0427
+#define CASYM  0417
+
+#define SYMREP 04000
+#define ECSYM  (SYMREP|';')
+#define ANDFSYM        (SYMREP|'&')
+#define ORFSYM (SYMREP|'|')
+#define APPSYM (SYMREP|'>')
+#define DOCSYM (SYMREP|'<')
+#define EOFSYM 02000
+#define SYMFLG 0400
+
+/* arg to `cmd' */
+#define NLFLG  1
+#define MTFLG  2
+
+/* for peekc */
+#define MARK   0100000
+
+/* odd chars */
+#define DQUOTE '"'
+#define SQUOTE '`'
+#define LITERAL        '\''
+#define DOLLAR '$'
+#define ESCAPE '\\'
+#define BRACE  '{'
diff --git a/usr/src/cmd/sh/word.c b/usr/src/cmd/sh/word.c
new file mode 100644 (file)
index 0000000..d194446
--- /dev/null
@@ -0,0 +1,124 @@
+#
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Bell Telephone Laboratories
+ *
+ */
+
+#include       "defs.h"
+#include       "sym.h"
+
+
+/* ========    character handling for command lines    ========*/
+
+
+word()
+{
+       REG CHAR        c, d;
+       REG CHAR        *argp=locstak()+BYTESPERWORD;
+       INT             alpha=1;
+
+       wdnum=0; wdset=0;
+
+       WHILE (c=nextc(0), space(c)) DONE
+       IF !eofmeta(c)
+       THEN    REP     IF c==LITERAL
+                       THEN    *argp++=(DQUOTE);
+                               WHILE (c=readc()) ANDF c!=LITERAL
+                               DO *argp++=(c|QUOTE); chkpr(c) OD
+                               *argp++=(DQUOTE);
+                       ELSE    *argp++=(c);
+                               IF c=='=' THEN wdset |= alpha FI
+                               IF !alphanum(c) THEN alpha=0 FI
+                               IF qotchar(c)
+                               THEN    d=c;
+                                       WHILE (*argp++=(c=nextc(d))) ANDF c!=d
+                                       DO chkpr(c) OD
+                               FI
+                       FI
+               PER (c=nextc(0), !eofmeta(c)) DONE
+               argp=endstak(argp);
+               IF !letter(argp->argval[0]) THEN wdset=0 FI
+
+               peekc=c|MARK;
+               IF argp->argval[1]==0 ANDF (d=argp->argval[0], digit(d)) ANDF (c=='>' ORF c=='<')
+               THEN    word(); wdnum=d-'0';
+               ELSE    /*check for reserved words*/
+                       IF reserv==FALSE ORF (wdval=syslook(argp->argval,reserved))==0
+                       THEN    wdarg=argp; wdval=0;
+                       FI
+               FI
+
+       ELIF dipchar(c)
+       THEN    IF (d=nextc(0))==c
+               THEN    wdval = c|SYMREP;
+               ELSE    peekc = d|MARK; wdval = c;
+               FI
+       ELSE    IF (wdval=c)==EOF
+               THEN    wdval=EOFSYM;
+               FI
+               IF iopend ANDF eolchar(c)
+               THEN    copy(iopend); iopend=0;
+               FI
+       FI
+       reserv=FALSE;
+       return(wdval);
+}
+
+nextc(quote)
+       CHAR            quote;
+{
+       REG CHAR        c, d;
+       IF (d=readc())==ESCAPE
+       THEN    IF (c=readc())==NL
+               THEN    chkpr(NL); d=nextc(quote);
+               ELIF quote ANDF c!=quote ANDF !escchar(c)
+               THEN    peekc=c|MARK;
+               ELSE    d = c|QUOTE;
+               FI
+       FI
+       return(d);
+}
+
+readc()
+{
+       REG CHAR        c;
+       REG INT         len;
+       REG FILE        f;
+
+retry:
+       IF peekc
+       THEN    c=peekc; peekc=0;
+       ELIF (f=standin, f->fnxt!=f->fend)
+       THEN    IF (c = *f->fnxt++)==0
+               THEN    IF f->feval
+                       THEN    IF estabf(*f->feval++)
+                               THEN    c=EOF;
+                               ELSE    c=SP;
+                               FI
+                       ELSE    goto retry; /* = c=readc(); */
+                       FI
+               FI
+               IF flags&readpr ANDF standin->fstak==0 THEN prc(c) FI
+               IF c==NL THEN f->flin++ FI
+       ELIF f->feof ORF f->fdes<0
+       THEN    c=EOF; f->feof++;
+       ELIF (len=readb())<=0
+       THEN    close(f->fdes); f->fdes = -1; c=EOF; f->feof++;
+       ELSE    f->fend = (f->fnxt = f->fbuf)+len;
+               goto retry;
+       FI
+       return(c);
+}
+
+LOCAL  readb()
+{
+       REG FILE        f=standin;
+       REG INT         len;
+
+       REP     IF trapnote&SIGSET THEN newline(); sigchk() FI
+       PER (len=read(f->fdes,f->fbuf,f->fsiz))<0 ANDF trapnote DONE
+       return(len);
+}
diff --git a/usr/src/cmd/spell/american b/usr/src/cmd/spell/american
new file mode 100644 (file)
index 0000000..7015f97
--- /dev/null
@@ -0,0 +1,319 @@
+acknowledgment
+aggrandize
+aluminize
+aluminum
+amor
+amorous
+amphitheater
+analog
+analyze
+anemia
+anemic
+anesthesia
+anesthetic
+anesthetize
+antagonize
+apologize
+appareled
+appareling
+appetize
+arbor
+archeology
+ardor
+arithmetize
+armor
+armory
+axiomatize
+baptize
+barreled
+barreling
+behavior
+behoove
+belabor
+beveled
+beveler
+beveling
+canceled
+canceler
+canceling
+candor
+catalog
+catalyze
+catechize
+categorize
+cauterize
+center
+channeled
+channeler
+channeling
+chiseled
+chiseler
+chiseling
+clamor
+clamorous
+clangor
+color
+colorable
+colorful
+colorist
+corbeled
+corbeling
+counseled
+counseling
+crystallize
+cudgeled
+cudgeler
+cudgeling
+decentralize
+decriminalize
+defense
+dehumanize
+deionize
+demagnetize
+demeanor
+demineralize
+demoralize
+depersonalize
+depolarize
+desensitize
+detribalize
+dialyze
+diarrhea
+discolor
+disemboweled
+disemboweling
+disfavor
+disheveled
+disheveler
+disheveling
+dishonor
+dishonorable
+disorganize
+doweled
+doweler
+doweling
+dramatize
+dueled
+dueler
+dueling
+duelist
+economize
+ecumenical
+edema
+emphasize
+enameled
+enameling
+enamor
+encyclopedia
+endeavor
+energize
+eon
+epicenter
+esophagus
+eulogize
+favor
+favorable
+favorite
+fervor
+fiber
+flavor
+fraternize
+fueled
+fueler
+fueling
+funneled
+funneler
+funneling
+furor
+galvanize
+gaveled
+gaveler
+gaveling
+glamorize
+gram
+graveled
+graveling
+groveled
+groveler
+groveling
+gynecology
+harbor
+harmonize
+hiccup
+hiccupped
+hiccupping
+homeopathy
+homogenize
+honor
+honorable
+humor
+hydrolyze
+hypnotize
+hypostatize
+hypothesize
+jeweled
+jeweler
+jeweling
+judgment
+kilogram
+kinesthetic
+labeled
+labeler
+labeling
+labor
+laborite
+legitimize
+leveled
+leveler
+leveling
+libeled
+libeler
+libeling
+license
+liter
+logorrhea
+louver
+luster
+marveled
+marveler
+marveling
+mechanize
+medieval
+memorize
+mesmerize
+metallize
+milligram
+milliliter
+millimeter
+modeled
+modeler
+modeling
+nanogram
+naught
+neighbor
+neighborhood
+notarize
+ocher
+odor
+offense
+optimize
+orientation
+ostracize
+pajama
+pallor
+paneled
+paneling
+paralleled
+paralleling
+paralyze
+parametrize
+parceled
+parceler
+parceling
+parenthesize
+parlor
+peptize
+photolyze
+photosynthesize
+picogram
+plagiarize
+preprogram
+program
+proselytize
+psychoanalyze
+psycoanalyze
+pulverize
+pummeled
+pummeler
+pummeling
+pyorrhea
+pyrolyze
+quantize
+quarreled
+quarreler
+quarreling
+rancor
+raveled
+raveler
+raveling
+realize
+recognize
+reconnoiter
+reveled
+reveler
+reveling
+rigor
+rumor
+saber
+saltpeter
+savior
+savor
+savory
+scepter
+schematize
+scrutinize
+sensitize
+sepulcher
+shoveled
+shoveler
+shoveling
+shriveled
+shriveling
+siphon
+sniveled
+sniveler
+sniveling
+soliloquize
+specialty
+specter
+spirochete
+splendor
+squirreled
+squirreling
+stigmatize
+succor
+summarize
+swiveled
+swiveling
+symmetrize
+sympathize
+synchronize
+synthesize
+systematize
+tantalize
+tasseled
+tasseling
+temporize
+theater
+theatergoer
+theatergoing
+theorize
+tinseled
+tinseling
+titer
+toweled
+toweling
+trammeled
+traumatize
+traveled
+traveler
+traveling
+tricolor
+tumor
+tunneled
+tunneler
+tunneling
+tyrannize
+valor
+vapor
+varicolored
+vigor
+vulcanize
+wagon
+watercolor
+watercolorist
+weaseled
+weaseling
+whiskey
+yodeled
+yodeling
diff --git a/usr/src/cmd/spell/british b/usr/src/cmd/spell/british
new file mode 100644 (file)
index 0000000..9d58195
--- /dev/null
@@ -0,0 +1,324 @@
+acclimatise
+aeon
+aerodrome
+aeroplane
+aggrandise
+alarum
+aluminium
+amour
+amourous
+amphitheatre
+anaemia
+anaemic
+anaesthesia
+anaesthetic
+anaesthetise
+analyse
+antagonise
+apologise
+apparelled
+apparelling
+appetise
+arbour
+archaeology
+ardour
+arithmetise
+armour
+armoury
+axiomatise
+baptise
+barrelled
+barrelling
+behaviour
+behavioural
+behove
+belabour
+bevelled
+beveller
+bevelling
+cancelled
+canceller
+cancelling
+candour
+catalyse
+catechise
+categorise
+cauterise
+centimetre
+centre
+channelled
+channeller
+channelling
+cheque
+chequer
+chiselled
+chiseller
+chiselling
+clamour
+clamourous
+clangour
+colour
+colourable
+colourist
+connexion
+corbelled
+corbelling
+counselled
+counselling
+crystallise
+cudgelled
+cudgeller
+cudgelling
+decentralise
+decriminalise
+defence
+dehumanise
+deionise
+demagnetise
+demeanour
+demineralise
+demoralise
+depersonalise
+depolarise
+desensitise
+detribalise
+dialyse
+diarrhoea
+discolour
+disembowelled
+disembowelling
+disfavour
+dishevelled
+disheveller
+dishevelling
+dishonour
+dishonourable
+disorganise
+dowelled
+doweller
+dowelling
+dramatise
+draught
+duelled
+dueller
+duelling
+duellist
+economise
+emphasise
+enamelled
+enamelling
+enamour
+encyclopaedia
+endeavour
+energise
+epicentre
+eulogise
+favour
+favourable
+favourite
+fervour
+fibre
+flavour
+fraternise
+fuelled
+fueller
+fuelling
+funnelled
+funneller
+funnelling
+furore
+fuze
+galvanise
+gaol
+gavelled
+gaveller
+gavelling
+glamourise
+gramme
+gravelled
+gravelling
+grovelled
+groveller
+grovelling
+gynaecology
+harbour
+harmonise
+homoeopathy
+homogenise
+honour
+honourable
+humour
+hydrolyse
+hypnotise
+hypostatise
+hypothesise
+jewelled
+jeweller
+jewelling
+kilogramme
+kilometre
+kinaesthetic
+labelled
+labeller
+labelling
+labour
+labourite
+legitimise
+levelled
+leveller
+levelling
+libelled
+libeller
+libelling
+licence
+litre
+logorrhoea
+lustre
+marvelled
+marveller
+marvelling
+mechanise
+mediaeval
+memorise
+mesmerise
+metallise
+metre
+milligramme
+millilitre
+millimetre
+modelled
+modeller
+modelling
+nanogramme
+nanometre
+neighbour
+neighbourhood
+notarise
+nought
+ochre
+odour
+oecumenical
+oedema
+oesophagus
+offence
+optimise
+orientate
+ostracise
+pallour
+panelled
+panelling
+parallelled
+parallelling
+paralyse
+parametrise
+parcelled
+parceller
+parcelling
+parenthesise
+parlour
+peptise
+photolyse
+photosynthesise
+picogramme
+plagiarise
+practise
+preprogramme
+programme
+proselytise
+psychoanalyse
+pulverise
+pummelled
+pummeller
+pummelling
+pyjama
+pyorrhoea
+pyrolyse
+quantise
+quarrelled
+quarreller
+quarrelling
+rancour
+ravelled
+raveller
+ravelling
+realise
+recognise
+reconnoitre
+revelled
+reveller
+revelling
+rigour
+rumour
+sabre
+saltpetre
+saviour
+savour
+savoury
+sceptre
+schematise
+scrutinise
+sensitise
+sepulchre
+shovelled
+shoveller
+shovelling
+shrivelled
+shrivelling
+snivelled
+sniveller
+snivelling
+soliloquise
+speciality
+spectre
+splendour
+squirrelled
+squirrelling
+stigmatise
+succour
+summarise
+millimetre
+swivelled
+swivelling
+symmetrise
+sympathise
+synchronise
+synthesise
+syphon
+systematise
+tantalise
+tasselled
+tasselling
+temporise
+theatre
+theorise
+tinselled
+tinselling
+titre
+towelled
+towelling
+trammelled
+traumatise
+travelled
+traveller
+travelling
+tricolour
+tumour
+tunnelled
+tunneller
+tunnelling
+tyrannise
+tyre
+valour
+vapour
+varicoloured
+vigour
+vulcanise
+waggon
+watercolour
+watercolourist
+weaselled
+weaselling
+whilst
+whisky
+yodelled
+yodelling
diff --git a/usr/src/cmd/spell/local b/usr/src/cmd/spell/local
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/usr/src/cmd/spell/spell.c b/usr/src/cmd/spell/spell.c
new file mode 100644 (file)
index 0000000..13369c4
--- /dev/null
@@ -0,0 +1,535 @@
+#include "spell.h"
+#define DLEV 2
+
+char   *strcat();
+int    strip();
+char   *skipv();
+int    an();
+int    s();
+int    es();
+int    ily();
+int    ncy();
+int    CCe();
+int    VCe();
+int    bility();
+int    tion();
+int    ize();
+int    y_to_e();
+int    i_to_y();
+int    nop();
+int    metry();
+
+struct suftab {
+       char *suf;
+       int (*p1)();
+       int n1;
+       char *d1;
+       char *a1;
+       int (*p2)();
+       int n2;
+       char *d2;
+       char *a2;
+} suftab[] = {
+       {"ssen",ily,4,"-y+iness","+ness" },
+       {"ssel",ily,4,"-y+i+less","+less" },
+       {"se",s,1,"","+s",              es,2,"-y+ies","+es" },
+       {"s'",s,2,"","+'s"},
+       {"s",s,1,"","+s"},
+       {"ecn",ncy,1,"","-t+ce"},
+       {"ycn",ncy,1,"","-cy+t"},
+       {"ytilb",nop,0,"",""},
+       {"ytilib",bility,5,"-le+ility",""},
+       {"elbaif",i_to_y,4,"-y+iable",""},
+       {"elba",CCe,4,"-e+able","+able"},
+       {"yti",CCe,3,"-e+ity","+ity"},
+       {"ylb",y_to_e,1,"-e+y",""},
+       {"yl",ily,2,"-y+ily","+ly"},
+       {"laci",strip,2,"","+al"},
+       {"latnem",strip,2,"","+al"},
+       {"lanoi",strip,2,"","+al"},
+       {"tnem",strip,4,"","+ment"},
+       {"gni",CCe,3,"-e+ing","+ing"},
+       {"reta",nop,0,"",""},
+       {"re",strip,1,"","+r",          i_to_y,2,"-y+ier","+er"},
+       {"de",strip,1,"","+d",          i_to_y,2,"-y+ied","+ed"},
+       {"citsi",strip,2,"","+ic"},
+       {"cihparg",i_to_y,1,"-y+ic",""},
+       {"tse",strip,2,"","+st",        i_to_y,3,"-y+iest","+est"},
+       {"cirtem",i_to_y,1,"-y+ic",""},
+       {"yrtem",metry,0,"-ry+er",""},
+       {"cigol",i_to_y,1,"-y+ic",""},
+       {"tsigol",i_to_y,2,"-y+ist",""},
+       {"tsi",VCe,3,"-e+ist","+ist"},
+       {"msi",VCe,3,"-e+ism","+ist"},
+       {"noitacif",i_to_y,6,"-y+ication",""},
+       {"noitazi",ize,5,"-e+ation",""},
+       {"rota",tion,2,"-e+or",""},
+       {"noit",tion,3,"-e+ion","+ion"},
+       {"naino",an,3,"","+ian"},
+       {"na",an,1,"","+n"},
+       {"evit",tion,3,"-e+ive","+ive"},
+       {"ezi",CCe,3,"-e+ize","+ize"},
+       {"pihs",strip,4,"","+ship"},
+       {"dooh",ily,4,"-y+hood","+hood"},
+       {"ekil",strip,4,"","+like"},
+       0
+};
+
+char *preftab[] = {
+       "anti",
+       "bio",
+       "dis",
+       "electro",
+       "en",
+       "fore",
+       "hyper",
+       "intra",
+       "inter",
+       "iso",
+       "kilo",
+       "magneto",
+       "meta",
+       "micro",
+       "milli",
+       "mis",
+       "mono",
+       "multi",
+       "non",
+       "out",
+       "over",
+       "photo",
+       "poly",
+       "pre",
+       "pseudo",
+       "re",
+       "semi",
+       "stereo",
+       "sub",
+       "super",
+       "thermo",
+       "ultra",
+       "under",        /*must precede un*/
+       "un",
+       0
+};
+
+int vflag;
+int xflag;
+char word[100];
+char original[100];
+char *deriv[40];
+char affix[40];
+
+main(argc,argv)
+char **argv;
+{
+       register char *ep, *cp;
+       register char *dp;
+       int fold;
+       int j;
+       FILE *file, *found;
+       if(!prime(argc,argv)) {
+               fprintf(stderr,
+                   "spell: cannot initialize hash table\n");
+               exit(1);
+       }
+       found = fopen(argv[2],"w");
+       for(argc-=3,argv+=3; argc>0 && argv[0][0]=='-'; argc--,argv++)
+               switch(argv[0][1]) {
+               case 'b':
+                       ise();
+                       break;
+               case 'v':
+                       vflag++;
+                       break;
+               case 'x':
+                       xflag++;
+                       break;
+               }
+       for(;; fprintf(file,"%s%s\n",affix,original)) {
+               affix[0] = 0;
+               file = found;
+               for(ep=word;(*ep=j=getchar())!='\n';ep++)
+                       if(j == EOF)
+                               exit(0);
+               for(cp=word,dp=original; cp<ep; )
+                       *dp++ = *cp++;
+               *dp = 0;
+               fold = 0;
+               for(cp=word;cp<ep;cp++)
+                       if(islower(*cp))
+                               goto lcase;
+               if(putsuf(ep,".",0))
+                       continue;
+               ++fold;
+               for(cp=original+1,dp=word+1;dp<ep;dp++,cp++)
+                       *dp = Tolower(*cp);
+lcase:
+               if(putsuf(ep,".",0)||suffix(ep,0))
+                       continue;
+               if(isupper(word[0])) {
+                       for(cp=original,dp=word; *dp = *cp++; dp++)
+                               if (fold) *dp = Tolower(*dp);
+                       word[0] = Tolower(word[0]);
+                       goto lcase;
+               }
+               file = stdout;
+       }
+}
+
+suffix(ep,lev)
+char *ep;
+{
+       register struct suftab *t;
+       register char *cp, *sp;
+       lev += DLEV;
+       deriv[lev] = deriv[lev-1] = 0;
+       for(t= &suftab[0];sp=t->suf;t++) {
+               cp = ep;
+               while(*sp)
+                       if(*--cp!=*sp++)
+                               goto next;
+               for(sp=cp; --sp>=word&&!vowel(*sp); ) ;
+               if(sp<word)
+                       return(0);
+               if((*t->p1)(ep-t->n1,t->d1,t->a1,lev+1))
+                       return(1);
+               if(t->p2!=0) {
+                       deriv[lev] = deriv[lev+1] = 0;
+                       return((*t->p2)(ep-t->n2,t->d2,t->a2,lev));
+               }
+               return(0);
+next:          ;
+       }
+       return(0);
+}
+
+nop()
+{
+       return(0);
+}
+
+strip(ep,d,a,lev)
+char *ep,*d,*a;
+{
+       return(putsuf(ep,a,lev)||suffix(ep,lev));
+}
+
+s(ep,d,a,lev)
+char *ep,*d,*a;
+{
+       if(lev>DLEV+1)
+               return(0);
+       if(*ep=='s'&&ep[-1]=='s')
+               return(0);
+       return(strip(ep,d,a,lev));
+}
+
+an(ep,d,a,lev)
+char *ep,*d,*a;
+{
+       if(!isupper(*word))     /*must be proper name*/
+               return(0);
+       return(putsuf(ep,a,lev));
+}
+
+ize(ep,d,a,lev)
+char *ep,*d,*a;
+{
+       *ep++ = 'e';
+       return(strip(ep,"",d,lev));
+}
+
+y_to_e(ep,d,a,lev)
+char *ep,*d,*a;
+{
+       *ep++ = 'e';
+       return(strip(ep,"",d,lev));
+}
+
+ily(ep,d,a,lev)
+char *ep,*d,*a;
+{
+       if(ep[-1]=='i')
+               return(i_to_y(ep,d,a,lev));
+       else
+               return(strip(ep,d,a,lev));
+}
+
+ncy(ep,d,a,lev)
+char *ep, *d, *a;
+{
+       if(skipv(skipv(ep-1))<word)
+               return(0);
+       ep[-1] = 't';
+       return(strip(ep,d,a,lev));
+}
+
+bility(ep,d,a,lev)
+char *ep,*d,*a;
+{
+       *ep++ = 'l';
+       return(y_to_e(ep,d,a,lev));
+}
+
+i_to_y(ep,d,a,lev)
+char *ep,*d,*a;
+{
+       if(ep[-1]=='i') {
+               ep[-1] = 'y';
+               a = d;
+       }
+       return(strip(ep,"",a,lev));
+}
+
+es(ep,d,a,lev)
+char *ep,*d,*a;
+{
+       if(lev>DLEV)
+               return(0);
+       switch(ep[-1]) {
+       default:
+               return(0);
+       case 'i':
+               return(i_to_y(ep,d,a,lev));
+       case 's':
+       case 'h':
+       case 'z':
+       case 'x':
+               return(strip(ep,d,a,lev));
+       }
+}
+
+metry(ep,d,a,lev)
+char *ep, *d,*a;
+{
+       ep[-2] = 'e';
+       ep[-1] = 'r';
+       return(strip(ep,d,a,lev));
+}
+
+tion(ep,d,a,lev)
+char *ep,*d,*a;
+{
+       switch(ep[-2]) {
+       case 'c':
+       case 'r':
+               return(putsuf(ep,a,lev));
+       case 'a':
+               return(y_to_e(ep,d,a,lev));
+       }
+       return(0);
+}
+
+/*     possible consonant-consonant-e ending*/
+CCe(ep,d,a,lev)
+char *ep,*d,*a;
+{
+       switch(ep[-1]) {
+       case 'l':
+               if(vowel(ep[-2]))
+                       break;
+               switch(ep[-2]) {
+               case 'l':
+               case 'r':
+               case 'w':
+                       break;
+               default:
+                       return(y_to_e(ep,d,a,lev));
+               }
+               break;
+       case 's':
+               if(ep[-2]=='s')
+                       break;
+       case 'c':
+       case 'g':
+               if(*ep=='a')
+                       return(0);
+       case 'v':
+       case 'z':
+               if(vowel(ep[-2]))
+                       break;
+       case 'u':
+               if(y_to_e(ep,d,a,lev))
+                       return(1);
+               if(!(ep[-2]=='n'&&ep[-1]=='g'))
+                       return(0);
+       }
+       return(VCe(ep,d,a,lev));
+}
+
+/*     possible consonant-vowel-consonant-e ending*/
+VCe(ep,d,a,lev)
+char *ep,*d,*a;
+{
+       char c;
+       c = ep[-1];
+       if(c=='e')
+               return(0);
+       if(!vowel(c) && vowel(ep[-2])) {
+               c = *ep;
+               *ep++ = 'e';
+               if(putsuf(ep,d,lev)||suffix(ep,lev))
+                       return(1);
+               ep--;
+               *ep = c;
+       }
+       return(strip(ep,d,a,lev));
+}
+
+char *lookuppref(wp,ep)
+char **wp;
+char *ep;
+{
+       register char **sp;
+       register char *bp,*cp;
+       for(sp=preftab;*sp;sp++) {
+               bp = *wp;
+               for(cp= *sp;*cp;cp++,bp++)
+                       if(Tolower(*bp)!=*cp)
+                               goto next;
+               for(cp=bp;cp<ep;cp++) 
+                       if(vowel(*cp)) {
+                               *wp = bp;
+                               return(*sp);
+                       }
+next:  ;
+       }
+       return(0);
+}
+
+putsuf(ep,a,lev)
+char *ep,*a;
+{
+       register char *cp;
+       char *bp;
+       register char *pp;
+       int val = 0;
+       char space[20];
+       deriv[lev] = a;
+       if(putw(word,ep,lev))
+               return(1);
+       bp = word;
+       pp = space;
+       deriv[lev+1] = pp;
+       while(cp=lookuppref(&bp,ep)) {
+               *pp++ = '+';
+               while(*pp = *cp++)
+                       pp++;
+               if(putw(bp,ep,lev+1)) {
+                       val = 1;
+                       break;
+               }
+       }
+       deriv[lev+1] = deriv[lev+2] = 0;
+       return(val);
+}
+
+putw(bp,ep,lev)
+char *bp,*ep;
+{
+       register i, j;
+       char duple[3];
+       if(ep-bp<=1)
+               return(0);
+       if(vowel(*ep)) {
+               if(monosyl(bp,ep))
+                       return(0);
+       }
+       i = dict(bp,ep);
+       if(i==0&&vowel(*ep)&&ep[-1]==ep[-2]&&monosyl(bp,ep-1)) {
+               ep--;
+               deriv[++lev] = duple;
+               duple[0] = '+';
+               duple[1] = *ep;
+               duple[2] = 0;
+               i = dict(bp,ep);
+       }
+       if(vflag==0||i==0)
+               return(i);
+       j = lev;
+       do {
+               if(deriv[j])
+                       strcat(affix,deriv[j]);
+       } while(--j>0);
+       strcat(affix,"\t");
+       return(i);
+}
+
+
+monosyl(bp,ep)
+char *bp, *ep;
+{
+       if(ep<bp+2)
+               return(0);
+       if(vowel(*--ep)||!vowel(*--ep)
+               ||ep[1]=='x'||ep[1]=='w')
+               return(0);
+       while(--ep>=bp)
+               if(vowel(*ep))
+                       return(0);
+       return(1);
+}
+
+char *
+skipv(s)
+char *s;
+{
+       if(s>=word&&vowel(*s))
+               s--;
+       while(s>=word&&!vowel(*s))
+               s--;
+       return(s);
+}
+
+vowel(c)
+{
+       switch(Tolower(c)) {
+       case 'a':
+       case 'e':
+       case 'i':
+       case 'o':
+       case 'u':
+       case 'y':
+               return(1);
+       }
+       return(0);
+}
+
+/* crummy way to Britishise */
+ise()
+{
+       register struct suftab *p;
+       for(p = suftab;p->suf;p++) {
+               ztos(p->suf);
+               ztos(p->d1);
+               ztos(p->a1);
+       }
+}
+ztos(s)
+char *s;
+{
+       for(;*s;s++)
+               if(*s=='z')
+                       *s = 's';
+}
+
+dict(bp,ep)
+char *bp, *ep;
+{
+       register char *wp;
+       long h;
+       register long *lp;
+       register i;
+       if(xflag)
+               printf("=%.*s\n",ep-bp,bp);
+       for(i=0; i<NP; i++) {
+               for (wp = bp, h = 0, lp = pow2[i]; wp < ep; ++wp, ++lp)
+                       h += *wp * *lp;
+               h += '\n' * *lp;
+               h %= p[i];
+               if(get(h)==0)
+                       return(0);
+       }
+       return(1);
+}
diff --git a/usr/src/cmd/spell/spell.h b/usr/src/cmd/spell/spell.h
new file mode 100644 (file)
index 0000000..6ed377c
--- /dev/null
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <ctype.h>
+
+#ifndef unix
+#define SHIFT  5
+#define TABSIZE (int)(400000/(1<<SHIFT))
+int    *tab;   /*honeywell loader deficiency*/
+#else
+#define Tolower(c)     (isupper(c)?tolower(c):c) /* ugh!!! */
+#define SHIFT  4
+#define TABSIZE 25000  /*(int)(400000/(1<<shift))--pdp11 compiler deficiency*/
+short  tab[TABSIZE];
+#endif
+long   p[] = {
+       399871,
+       399887,
+       399899,
+       399911,
+       399913,
+       399937,
+       399941,
+       399953,
+       399979,
+       399983,
+       399989,
+};
+#define        NP      (sizeof(p)/sizeof(p[0]))
+#define        NW      30
+
+/*
+* Hash table for spelling checker has n bits.
+* Each word w is hashed by k different (modular) hash functions, hi.
+* The bits hi(w), i=1..k, are set for words in the dictionary.
+* Assuming independence, the probability that no word of a d-word
+* dictionary sets a particular bit is given by the Poisson formula
+* P = exp(-y)*y**0/0!, where y=d*k/n.
+* The probability that a random string is recognized as a word is then
+* (1-P)**k.  For given n and d this is minimum when y=log(2), P=1/2,
+* whence one finds, for example, that a 25000-word dictionary in a
+* 400000-bit table works best with k=11.
+*/
+
+long   pow2[NP][NW];
+
+prime(argc, argv) register char **argv;
+{
+       int i, j;
+       long h;
+       register long *lp;
+
+#ifndef unix
+       if ((tab = (int *)calloc(sizeof(*tab), TABSIZE)) == NULL)
+               return(0);
+#endif
+       if (argc > 1) {
+               FILE *f;
+               if ((f = fopen(argv[1], "ri")) == NULL)
+                       return(0);
+               if (fread((char *)tab, sizeof(*tab), TABSIZE, f) != TABSIZE)
+                       return(0);
+               fclose(f);
+       }
+       for (i=0; i<NP; i++) {
+               h = *(lp = pow2[i]) = 1<<14;
+               for (j=1; j<NW; j++)
+                       h = *++lp = (h<<7) % p[i];
+       }
+       return(1);
+}
+
+#define get(h) (tab[h>>SHIFT]&(1<<((int)h&((1<<SHIFT)-1))))
+#define set(h) tab[h>>SHIFT] |= 1<<((int)h&((1<<SHIFT)-1))
diff --git a/usr/src/cmd/spell/spell.sh b/usr/src/cmd/spell/spell.sh
new file mode 100755 (executable)
index 0000000..8a8efeb
--- /dev/null
@@ -0,0 +1,28 @@
+: B flags, D dictionary, F files, H history, S stop, V data for -v
+H=${H-/usr/dict/spellhist}
+T=/tmp/spell.$$
+V=/dev/null
+F= B=
+trap "rm -f $T*; exit" 0 1 2 13 15
+for A in $*
+do
+       case $A in
+       -v)     B="$B -v"
+               V=${T}a ;;
+       -a)     ;;
+       -b)     D=${D-/usr/dict/hlistb}
+               B="$B -b" ;;
+       *)      F="$F $A"
+       esac
+       done
+deroff -w $F |\
+  sort -u |\
+  /usr/lib/spell ${S-/usr/dict/hstop} $T |\
+  /usr/lib/spell ${D-/usr/dict/hlista} $V $B |\
+  sort -u +0f +0 - $T |\
+  tee -a $H
+who am i >>$H 2>/dev/null
+case $V in
+/dev/null)     exit
+esac
+sed '/^\./d' $V | sort -u +1f +0
diff --git a/usr/src/cmd/spell/spellin.c b/usr/src/cmd/spell/spellin.c
new file mode 100644 (file)
index 0000000..3f46c2b
--- /dev/null
@@ -0,0 +1,40 @@
+#include "spell.h"
+/* add entries to hash table for use by spell
+   preexisting hash table is first argument
+   words to be added are standard input
+   if no hash table is given, create one from scratch
+*/
+
+main(argc,argv)
+char **argv;
+{
+       register i, j;
+       long h;
+       register long *lp;
+       char word[NW];
+       register char *wp;
+
+       if(!prime(argc,argv)) {
+               fprintf(stderr,
+                   "spellin: cannot initialize hash table\n");
+               exit(1);
+       }
+       while (fgets(word, sizeof(word), stdin)) {
+               for (i=0; i<NP; i++) {
+                       for (wp = word, h = 0, lp = pow2[i];
+                                (j = *wp) != '\0'; ++wp, ++lp)
+                               h += j * *lp;
+                       h %= p[i];
+                       set(h);
+               }
+       }
+#ifdef gcos
+       freopen((char *)NULL, "wi", stdout);
+#endif
+       if (fwrite((char *)tab, sizeof(*tab), TABSIZE, stdout) != TABSIZE) {
+               fprintf(stderr,
+                   "spellin: trouble writing hash table\n");
+               exit(1);
+       }
+       return(0);
+}
diff --git a/usr/src/cmd/spell/spellout.c b/usr/src/cmd/spell/spellout.c
new file mode 100644 (file)
index 0000000..91fa6c9
--- /dev/null
@@ -0,0 +1,43 @@
+#include "spell.h"
+
+main(argc, argv)
+char **argv;
+{
+       register i, j;
+       long h;
+       register long *lp;
+       char word[NW];
+       int dflag = 0;
+       int indict;
+       register char *wp;
+
+       if (argc>1 && argv[1][0]=='-' && argv[1][1]=='d') {
+               dflag = 1;
+               argc--;
+               argv++;
+       }
+       if(argc<=1) {
+               fprintf(stderr,"spellout: arg count\n");
+               exit(1);
+       }
+       if(!prime(argc,argv)) {
+               fprintf(stderr,
+                   "spellout: cannot initialize hash table\n");
+               exit(1);
+       }
+       while (fgets(word, sizeof(word), stdin)) {
+               indict = 1;
+               for (i=0; i<NP; i++) {
+                       for (wp = word, h = 0, lp = pow2[i];
+                               (j = *wp) != '\0'; ++wp, ++lp)
+                               h += j * *lp;
+                       h %= p[i];
+                       if (get(h)==0) {
+                               indict = 0;
+                               break;
+                       }
+               }
+               if (dflag == indict)
+                       fputs(word, stdout);
+       }
+}
diff --git a/usr/src/cmd/spell/stop b/usr/src/cmd/spell/stop
new file mode 100644 (file)
index 0000000..d49fa85
--- /dev/null
@@ -0,0 +1,927 @@
+abator
+abeted
+abeter
+abeting
+abuted
+abuter
+abuting
+accessable
+acclimatize
+acquiter
+acquiting
+acter
+addendums
+adly
+admitable
+admited
+admiter
+admiting
+ahly
+allotable
+alloted
+alloter
+alloting
+amly
+ams
+animadvertion
+anly
+annulable
+annuled
+annuler
+annuling
+ans
+arguement
+arised
+asly
+ation
+ative
+atly
+ator
+ats
+audable
+auditer
+autosuggestable
+avered
+averer
+avering
+avertion
+axises
+axly
+baned
+baning
+beared
+beated
+beator
+bedimed
+bedimer
+bediming
+befited
+befiter
+befiting
+befoged
+befoger
+befoging
+begeted
+begeter
+begeting
+begined
+beginer
+begining
+beholded
+bely
+bes
+besetable
+beseted
+beseter
+beseting
+besoting
+bespeaked
+bestired
+bestirer
+bestiring
+betted
+bidded
+bies
+binded
+bited
+blader
+bleeded
+blowed
+breaked
+breeded
+bringed
+bursted
+buyed
+byly
+Canadan
+Carolinan
+casted
+catched
+cheator
+checksumable
+checksumed
+checksuming
+choosed
+clinged
+collapsable
+collectable
+collecter
+colourate
+colourful
+combustable
+comed
+commitable
+commited
+commiter
+commiting
+compatable
+compeled
+compeler
+compeling
+compositer
+compositon
+comprehensable
+compressable
+condensable
+conducter
+coner
+conferable
+confered
+conferer
+confering
+coning
+constricter
+constructable
+constructer
+contemptable
+contracter
+controlable
+controled
+controler
+controling
+controvertable
+convertable
+convertion
+corpuses
+correcter
+corrigendums
+corrodable
+corruptable
+credable
+crediter
+creeped
+currance
+currancy
+curriculas
+cutted
+datas
+datums
+dealed
+debared
+debarer
+debaring
+debator
+debter
+debuged
+debuger
+debuging
+decontroled
+decontroler
+decontroling
+deductable
+defensable
+deferable
+defered
+deferer
+defering
+deflator
+deflecter
+degased
+degaser
+degasing
+degumed
+degumer
+deguming
+demitable
+demited
+demiter
+demiting
+demured
+demuring
+depositer
+depressable
+desolator
+destructer
+detecter
+deterable
+detered
+deterer
+detering
+detracter
+diffusable
+digestable
+dimed
+dimest
+directer
+discernable
+discomfited
+discomfiter
+discomfiting
+disintered
+disinterer
+disintering
+dispelable
+dispeled
+dispeler
+dispeling
+dispence
+dispersable
+distributory
+divertion
+doged
+doger
+doging
+doly
+doned
+doner
+doning
+drawed
+drinked
+drived
+duely
+dus
+eated
+eator
+eavesdroped
+eavesdroper
+eavesdroping
+edable
+editer
+effluvias
+effluviums
+ehly
+ehs
+ejecter
+electer
+elly
+embedable
+embeded
+embeder
+embeding
+emitable
+emited
+emiter
+emiting
+emly
+emphasises
+enaction
+enbalm
+enbank
+enbark
+enbattle
+enbay
+enbed
+enbit
+enblaze
+enblazon
+enbody
+enbolden
+enboss
+enbow
+enbowel
+enbrace
+enbrittle
+enbroil
+encant
+encur
+endebted
+enend
+enflame
+enform
+enirate
+enit
+enly
+enpanel
+enpathetic
+enplace
+enplane
+enploy
+enpower
+enpress
+enpurple
+enroad
+entend
+entone
+entrapable
+entraped
+entraper
+entraping
+envoice
+equilibriums
+equipable
+equiped
+equiper
+equiping
+erodable
+erosable
+esophaguses
+estoped
+estoper
+estoping
+etly
+ets
+exasperator
+exceled
+exceler
+exceling
+exegesises
+exhaustable
+expansable
+expection
+expelable
+expeled
+expeler
+expeling
+expositer
+expressable
+extendable
+extensable
+extolable
+extoled
+extoler
+extoling
+extracter
+extremums
+extrovertion
+facter
+fadded
+fadding
+fallable
+falled
+feasable
+feeded
+feeled
+fighted
+finded
+flexable
+flinged
+flirtion
+Floridan
+fluter
+foable
+forbeared
+forbided
+forebade
+forebear
+forebid
+forebidden
+forebidding
+forebore
+forefend
+foregave
+foreget
+foregettable
+foregetting
+foregive
+foregiven
+foregot
+foremat
+foremate
+foresake
+foreswear
+forety
+foreward
+forgetable
+forgeted
+forsaked
+freezed
+frustrator
+fusable
+gayly
+genesises
+genuses
+getted
+giddaped
+giddaper
+giddaping
+gived
+glomed
+glumer
+glumest
+goly
+gos
+greator
+grimer
+grimest
+grinded
+growed
+gullable
+haly
+heared
+heator
+hely
+hes
+hesitator
+hily
+holded
+horrable
+huggest
+huging
+hurted
+idly
+ifly
+iily
+iis
+impartion
+impelable
+impeled
+impeler
+impeling
+imperceptable
+implausable
+implementer
+importion
+impressable
+inaccessable
+inaudable
+incombustable
+incompatable
+incomprehensable
+incontrovertable
+incorruptable
+incredable
+incured
+incurer
+incuring
+indefensable
+indelable
+indestructable
+indigestable
+indiscernable
+inducter
+inexhaustable
+inexpressable
+infallable
+infeasable
+inferable
+infered
+inferer
+infering
+inflator
+inflexable
+infusable
+ingestable
+inheriter
+inly
+insensable
+inspecter
+instructer
+intence
+interable
+intered
+interer
+intering
+interruptable
+intimator
+inventer
+invertable
+invertion
+invester
+irresistable
+irresponsable
+irreversable
+isly
+itly
+ivly
+ivs
+ixes
+ixly
+juter
+keeped
+kiloohm
+knowed
+lader
+laly
+lammest
+lapeled
+layed
+lended
+letted
+loaned
+loging
+loly
+losed
+mader
+madest
+mading
+maked
+maly
+maner
+maning
+manumitable
+manumited
+manumiter
+manumiting
+mared
+meaned
+meeted
+mely
+mies
+mily
+moter
+myly
+nely
+nes
+neurosises
+noding
+noly
+notory
+nuly
+objecter
+occured
+occurer
+occuring
+offsetable
+offseted
+offseter
+offseting
+ofly
+ofs
+ohly
+ons
+opuses
+ostensable
+outgaser
+ows
+oxes
+oxly
+padable
+paly
+paner
+paralysises
+parenthesises
+paster
+payed
+perceptable
+perfectable
+permitable
+permited
+permiter
+permiting
+pervertion
+phenomenas
+phenomenons
+photosynthesises
+pily
+pipper
+placator
+plausable
+plugable
+predicter
+preempter
+prefered
+preferer
+prefering
+preseter
+preseting
+presuably
+programable
+programed
+programer
+programing
+projecter
+pronounciation
+propeled
+propeler
+propeling
+prosecuter
+prospecter
+protecter
+quitable
+quiter
+quiting
+ratter
+readed
+reah
+realter
+rean
+reas
+reat
+reax
+rebat
+rebe
+rebeled
+rebeler
+rebeling
+rebutable
+rebuted
+rebuter
+rebuting
+reby
+recapable
+recaped
+recaper
+recaping
+recloth
+recommitable
+recommited
+recommiter
+recommiting
+recured
+recurer
+recuring
+redacter
+redu
+reem
+reen
+reet
+referable
+refered
+referer
+refering
+refited
+refiter
+refiting
+reflecter
+rego
+regretable
+regreted
+regreter
+regreting
+reha
+rehe
+rehi
+reho
+reif
+reii
+reis
+reit
+reiv
+reix
+reknited
+rekniter
+rekniting
+rela
+relo
+rema
+remad
+remaned
+remaner
+remaning
+reme
+remi
+remitable
+remited
+remiter
+remiting
+remu
+remy
+rended
+rene
+renu
+reof
+reoh
+reon
+reor
+reow
+reox
+repa
+repelable
+repeled
+repeler
+repeling
+repi
+reprehensable
+rere
+rerout
+rerunable
+reruned
+reruner
+reruning
+resa
+reshiped
+reshiper
+reshiping
+resistable
+reso
+responsable
+reti
+reto
+reup
+reus
+reversable
+revertion
+revi
+rewe
+rewok
+rexi
+reye
+rided
+risable
+rised
+rocketed
+rocketer
+rocketing
+ruber
+rubing
+runable
+runed
+runned
+saging
+saly
+saturator
+sayed
+sculpter
+secretory
+secter
+seeked
+selecter
+selled
+senation
+senative
+sended
+sensable
+setable
+setted
+shaked
+shedded
+shipable
+shooted
+shrinked
+shutted
+siner
+sining
+sinked
+siply
+sitted
+slank
+slayed
+sleeped
+slided
+slinged
+slinked
+smited
+soliciter
+soly
+speaked
+spended
+spinable
+spiner
+spining
+spinned
+spiting
+splitted
+spotable
+spreaded
+stagged
+stagging
+standed
+stealed
+sticked
+stinked
+stopable
+stratas
+strided
+striked
+subletable
+subleted
+subleter
+subleting
+submitable
+submited
+submiter
+submiting
+suggestable
+suntaned
+suntaning
+suppressable
+susceptable
+sweared
+sweeped
+swimable
+swinged
+synopsises
+synthesises
+taked
+teached
+telled
+terrable
+thesises
+thier
+thinked
+thrombosises
+throwed
+thrusted
+tily
+tiner
+tining
+toly
+tracter
+traiter
+tranquility
+transferable
+transfered
+transferer
+transfering
+transmitable
+transmited
+transmiter
+transmiting
+transportion
+trivias
+triviums
+truely
+typeseter
+typeseting
+unactivate
+unadequacy
+unattention
+unboard
+unbreed
+uncant
+uncapacity
+uncompletion
+uncorporate
+uncrease
+uncredulity
+unculpable
+uncur
+uncurred
+uncurrer
+uncurring
+undebt
+undeed
+undefinite
+undelicate
+undent
+undenture
+undices
+undignity
+undiscriminate
+undisposition
+undoor
+unduct
+undwell
+unefficacy
+unequity
+unfamous
+unfelicity
+unfest
+unfield
+unfiltrate
+unfinity
+unflame
+unflammable
+unflow
+unfluence
+unflux
+unformant
+unformation
+unfuse
+unfusion
+ungather
+ungrate
+ungratitude
+unhabitant
+unhabitation
+unhale
+unhere
+unholding
+unhumane
+unhumanity
+unjure
+unjury
+unnumerable
+unoperable
+unput
+unquest
+unscribe
+unscription
+unsect
+unside
+unspire
+unstall
+unstance
+unstead
+untact
+untake
+untemperance
+untend
+untestate
+untill
+untolerant
+untuition
+unvade
+unvalidate
+unvent
+unverse
+unversion
+unvertebrate
+unviolate
+unvocate
+unward
+unwieldly
+uply
+upseter
+upseting
+usly
+usses
+vendable
+vily
+vis
+visable
+visiter
+waked
+warer
+weared
+weeped
+wely
+wetable
+whitter
+whitting
+winable
+winned
+wringed
+writed
+xily
+yiper
diff --git a/usr/src/cmd/struct/0.alloc.c b/usr/src/cmd/struct/0.alloc.c
new file mode 100644 (file)
index 0000000..08b715e
--- /dev/null
@@ -0,0 +1,153 @@
+#include <stdio.h>
+#include "def.h"
+int routbeg;
+
+extern int debug;
+struct coreblk {struct coreblk *nxtblk;
+                       int blksize;
+                       int nxtfree;
+                       int *blk;
+                       };
+
+long space;
+challoc(n)
+int n;
+       {
+       int i;
+       i = malloc(n);
+       if(i) { space += n; return(i); }
+       fprintf(stderr,"alloc out of space\n");
+       fprintf(stderr,"total space alloc'ed = %D\n",space);
+       fprintf(stderr,"%d more bytes requested\n",n);
+       exit(1);
+       }
+
+
+chfree(p,n)
+int *p,n;
+       {
+       ASSERT(p,chfree);
+       space -= n;
+       free(p);
+       }
+
+
+struct coreblk *tcore, *gcore;
+int tblksize=12, gblksize=300;
+
+
+balloc(n,p,size)               /* allocate n bytes from coreblk *p */
+int n,size;            /* use specifies where called */
+struct coreblk **p;
+       {
+       int i;
+       struct coreblk *q;
+       n = (n+sizeof(i)-1)/sizeof(i);  /* convert bytes to wds to ensure ints always at wd boundaries */
+       for (q = *p; ; q = q->nxtblk)
+               {
+               if (!q)
+                       {
+                       q = morespace(n,p,size);
+                       break;
+                       }
+               if (q-> blksize - q->nxtfree >= n)  break;
+               }
+       i = q->nxtfree;
+       q ->nxtfree += n;
+       return( &(q->blk)[i]);
+       }
+
+talloc(n)              /* allocate from line-by-line storage area */
+int n;
+       {return(balloc(n,&tcore,tblksize)); }
+
+galloc(n)              /* allocate from graph storage area */
+int n;
+       {
+       return(balloc(n,&gcore,gblksize));
+       }
+
+reuse(p)               /* set nxtfree so coreblk can be reused */
+struct coreblk *p;
+       {
+       for (; p; p=p->nxtblk)  p->nxtfree = 0;  
+       }
+
+bfree(p)               /* free coreblk p */
+struct coreblk *p;
+       {
+       if (!p) return;
+       bfree(p->nxtblk);
+       p->nxtblk = 0;
+       free(p);
+       }
+
+
+morespace(n,p,size)            /* get at least n more wds for coreblk *p */
+int n,size;
+struct coreblk **p;
+       {struct coreblk *q;
+       int t,i;
+
+       t = n<size?size:n;
+       q = malloc(i=t*sizeof(*(q->blk))+sizeof(*q));
+       if(!q){
+               error(": alloc out of space","","");
+               fprintf(stderr,"space = %D\n",space);
+               fprintf(stderr,"%d more bytes requested\n",n);
+               exit(1);
+               }
+       space += i;
+       q->nxtblk = *p;
+       *p = q;
+       q -> blksize = t;
+       q-> nxtfree = 0;
+       q->blk = q + 1;
+       return(q);
+       }
+
+
+
+
+freegraf()
+       {
+       bfree(gcore);
+       gcore = 0;
+
+
+       }
+
+
+
+
+
+
+
+
+
+error(mess1, mess2, mess3)
+char *mess1, *mess2, *mess3;
+       {
+       static lastbeg;
+       if (lastbeg != routbeg)
+               {
+               fprintf(stderr,"routine beginning on line %d:\n",routbeg);
+               lastbeg = routbeg;
+               }
+       fprintf(stderr,"error %s %s %s\n",mess1, mess2, mess3);
+       }
+
+
+faterr(mess1, mess2, mess3)
+char *mess1, *mess2, *mess3;
+       {
+       error(mess1, mess2, mess3);
+       exit(1);
+       }
+
+
+strerr(mess1, mess2, mess3)
+char *mess1, *mess2, *mess3;
+       {
+       error("struct error: ",mess1, mess2);
+       }
diff --git a/usr/src/cmd/struct/0.args.c b/usr/src/cmd/struct/0.args.c
new file mode 100644 (file)
index 0000000..8df41c7
--- /dev/null
@@ -0,0 +1,98 @@
+#include <stdio.h>
+#
+#include "def.h"
+int errflag;
+FILE *infd;
+
+
+int intcase=1, arbcase=0;
+int exitsize=0;                        /* max number of nodes to be left in loop without iterating */
+int maxnode=400;       /* max number of nodes */
+int maxhash=347;       /* prime number = size of hash table */
+int progress=0;                /* if not 0, print line number every n lines, n = progress */
+int labinit=10;                        /* labels generated starting with labinit */
+int labinc=10;                 /* labels increase by labinc */
+int inputform=0;               /* = 0 if freeform input, 1 if standard form input */
+int debug=0;
+int levbrk=1;  /* true implies multilevel breaks; false implies single-level breaks only */
+int levnxt=1;  /* true implies multilevel nexts; false implies single-level nexts only */
+
+
+int maxprogsw=12;              /* number of program switches which can be set */
+char *progsw[]         = {"i", "a",
+                       "e", "m",
+                       "h", "p",
+                       "t", "c",
+                       "s", "d",
+                       "b", "n"
+                       };
+
+
+int *swval[]           = {&intcase, &arbcase,
+                       &exitsize, &maxnode,
+                       &maxhash, &progress,
+                       &labinit, &labinc,
+                       &inputform, &debug,
+                       &levbrk, &levnxt
+                       };
+
+
+char *getargs(argc, argv)
+int argc; char *argv[];
+       {
+       int n, infile;
+       infile = 0;
+
+       for (n = 1; n < argc; ++n)
+               {
+               if (argv[n][0] == '-')
+                       setsw(&argv[n][1]);
+               else
+                       {
+                       if (infile != 0)
+                               error("multiple input files - using first one: ", argv[infile],"");
+                       else
+                               infile = n;
+                       }
+               }
+       if (errflag)
+               exit(1);
+       if (!infile) faterr("no input file","","");
+       infd = fopen(argv[infile],"r");
+       if (infd == NULL)
+               faterr("can't open input file:",argv[infile],"");
+       return;
+       }
+
+setsw(str)
+char *str;
+       {
+       int i, val, swnum;
+#define maxtemp 15
+       char temp[maxtemp];
+       for (i = 0; 'a' <= str[i] && str[i] <= 'z'; ++i)
+               {
+               if (i >= maxtemp)
+                       {
+                       error("invalid switch:",str,"");
+                       errflag = 1;
+                       }
+               temp[i] = str[i];
+               }
+       temp[i] = '\0';
+
+       swnum = find(temp,progsw,maxprogsw);
+       if (swnum == -1)
+               {
+               error("invalid switch:", str,"");
+               errflag = 1;
+               return;
+               }
+       if (str[i] == '\0')
+               *(swval[swnum]) = !*(swval[swnum]);
+       else
+               {
+               sscanf(&str[i],"%d",&val);
+               *(swval[swnum]) = val;
+               }
+       }
diff --git a/usr/src/cmd/struct/0.def.c b/usr/src/cmd/struct/0.def.c
new file mode 100644 (file)
index 0000000..4c4b32d
--- /dev/null
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include "def.h"
+
+int routnum;
+FILE *debfd;
+LOGICAL routerr;
+int nodenum, accessnum;
+int **graph;
+int progtype;
+VERT stopvert, retvert;
+VERT START;
diff --git a/usr/src/cmd/struct/0.extr.c b/usr/src/cmd/struct/0.extr.c
new file mode 100644 (file)
index 0000000..a558e23
--- /dev/null
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include "def.h"
+struct lablist {long labelt;  struct lablist *nxtlab; };
+struct lablist *endlab, *errlab, *reflab, *linelabs, *newlab;
+
+int nameline;                  /* line number of function/subroutine st., if any */
+int stflag;            /* determines whether at beginning or middle of block of straight line code */
+
+
+
+int   nlabs, lswnum, swptr, flag,
+        counter, p1, p3, begline, endline, r1,r2, endcom;
+long begchar, endchar, comchar;
+
+
+char *pred, *inc, *prerw, *postrw, *exp, *stcode;
+
+#define maxdo  20      /* max nesting of do loops */
+long dostack[maxdo];           /* labels of do nodes */
+int doloc[maxdo];              /* loc of do node */
+int doptr;
+
+
+struct list *FMTLST;           /* list of FMTVX's generated */
+struct list *ENTLST;           /* list of STLNVX nodes corresponding to entry statements */
+long rtnbeg;   /* number of chars up to beginning of current routine */
diff --git a/usr/src/cmd/struct/0.graph.c b/usr/src/cmd/struct/0.graph.c
new file mode 100644 (file)
index 0000000..f2618f6
--- /dev/null
@@ -0,0 +1,59 @@
+#include <stdio.h>
+#include "def.h"
+
+#define TABOVER(n)     tabover(n,stderr)
+prgraph()
+       {
+       VERT v;
+       int i;
+       if (progress) fprintf(stderr,"prgraph():\n");
+       for (v = 0; v < nodenum; ++v)
+               {
+               fprintf(stderr,"%d %s:",v, typename[NTYPE(v)]);
+               for (i = 0; i < ARCNUM(v); ++i)
+                       {
+                       printf("%d ",ARC(v,i));
+                       ASSERT(UNDEFINED <= ARC(v,i) && ARC(v,i) < nodenum, prgraph);
+                       }
+               printf("\n");
+               }
+       printf("\n\n");
+       }
+
+prtree()
+       {
+       prtr(START,1);
+       }
+
+prtr(v,tab)            /* print tree in form of program indenting by tab */
+VERT v;
+int tab;
+       {
+       int i;
+       TABOVER(tab);
+       fprintf(stderr,"%d %s:",v,typename[NTYPE(v)]);
+       for (i = 0; i < ARCNUM(v); ++i)
+               fprintf(stderr," %d",ARC(v,i));
+       printf("\n");
+       for (i = 0; i < CHILDNUM(v); ++i)
+               {
+               TABOVER(tab+1);
+               fprintf(stderr,"{\n");
+               if (DEFINED(LCHILD(v,i)))
+                       prtr(LCHILD(v,i),tab+1);
+               TABOVER(tab+1);
+               fprintf(stderr,"}\n");
+               }
+       if (DEFINED(RSIB(v)))
+               prtr(RSIB(v),tab);
+       }
+
+
+tabover(n,fd)          /* tab n times */
+int n;
+FILE *fd;
+       {
+       int i;
+       for (i = 0; i < n; ++i)
+               putc('\t',fd);
+       }
diff --git a/usr/src/cmd/struct/0.list.c b/usr/src/cmd/struct/0.list.c
new file mode 100644 (file)
index 0000000..de8d1ae
--- /dev/null
@@ -0,0 +1,66 @@
+#include <stdio.h>
+#include "def.h"
+
+struct list *consls(v,ls)              /* make list */
+VERT v;
+struct list *ls;
+       {
+       struct list *temp;
+       temp = challoc(sizeof(*temp));
+       temp->elt = v;
+       temp->nxtlist = ls;
+       return(temp);
+       }
+
+struct list *append(v,ls)              /* return ls . v */
+VERT v;
+struct list *ls;
+       {
+       struct list *temp;
+       if (!ls) return(consls(v,0));
+       for (temp = ls; temp -> nxtlist; temp = temp->nxtlist)
+               ;
+       temp->nxtlist = consls(v,0);
+       return(ls);
+       }
+
+
+freelst(ls)
+struct list *ls;
+       {
+       if (!ls) return;
+       if (ls->nxtlist)
+               freelst(ls->nxtlist);
+       chfree(ls,sizeof(*ls));
+       }
+
+
+oneelt(ls)             /* return w if w is only elt of ls, UNDEFINED otherwise */
+struct list *ls;
+       {
+       if (!ls) return(UNDEFINED);
+       if (ls->nxtlist) return(UNDEFINED);
+       return(ls->elt);
+       }
+
+
+lslen(ls)              /* return number of elements in list ls */
+struct list *ls;
+       {
+       int count;
+       struct list *lp;
+       count = 0;
+       for (lp = ls; lp; lp = lp->nxtlist)
+               ++count;
+       return(count);
+       }
+
+
+prlst(ls)
+struct list *ls;
+       {
+       struct list *lp;
+       for (lp = ls; lp; lp = lp->nxtlist)
+               printf("%d,",lp->elt);
+       fprintf(stderr,"\n");
+       }
diff --git a/usr/src/cmd/struct/0.parts.c b/usr/src/cmd/struct/0.parts.c
new file mode 100644 (file)
index 0000000..e924171
--- /dev/null
@@ -0,0 +1,120 @@
+#include <stdio.h>
+#include "def.h"
+
+char *typename[TYPENUM]        = {"STLNVX",    "IFVX",         "DOVX",         "IOVX", "FMTVX",
+                       "COMPVX",       "ASVX",         "ASGOVX",       "LOOPVX",       "WHIVX",
+                       "UNTVX",        "ITERVX",       "THENVX",       "STOPVX",       "RETVX",
+                       "DUMVX",        "GOVX",         "BRKVX",        "NXTVX",        "SWCHVX",
+                       "ACASVX",       "ICASVX"
+       };
+int hascom[TYPENUM]    = {2,           2,              2,              2,              2,
+                       2,              2,              2,              0,              0,
+                       0,              0,              2,              0,              0,
+                       0,              0,              0,              0,              2,
+                       2,              0
+                       };
+
+int nonarcs[TYPENUM]   = {FIXED+3,     FIXED+4,        FIXED+2,        FIXED+3,        FIXED+2,
+                       FIXED+2,        FIXED+2,        FIXED+2,        FIXED+1,        FIXED+1,
+                       FIXED+1,        FIXED+4,        FIXED+3,        FIXED,          FIXED,
+                       FIXED+2,        FIXED+1,        FIXED + 1,      FIXED + 1,      FIXED+3,
+                       FIXED+4,        FIXED+2
+                       };
+
+int childper[TYPENUM]  = {0,   2,      1,      0,      0,
+                       0,      0,      0,      1,      1,
+                       1,      1,      1,      0,      0,
+                       1,      0,      0,      0,      1,
+                       2,      1
+                       };
+
+int arcsper[TYPENUM]   = {1,           2,              2,      3,      0,
+                       -(FIXED+1),     1,      -(FIXED+1),     1,      1,
+                       1,              1,              2,      0,      0,
+                       -FIXED,         1,      1,              1,      -(FIXED+1),
+                       2,              1
+                       };
+
+VERT *arc(v,i)
+VERT v;
+int i;
+       {
+       ASSERT(DEFINED(v),arc);
+       ASSERT(0 <= i && i < ARCNUM(v), arc);
+       return(&graph[v][nonarcs[NTYPE(v)] + i ]);
+       }
+
+VERT *lchild(v,i)
+VERT v; int i;
+       {
+       ASSERT(DEFINED(v),lchild);
+       ASSERT(0 <= i && i < childper[NTYPE(v)],lchild);
+       return(&graph[v][nonarcs[NTYPE(v)]-i-1]);
+       }
+
+int *vxpart(v,type,j)
+VERT v;
+int type,j;
+       {
+       ASSERT((NTYPE(v) == type) && (0 <= j) && (j < nonarcs[type] - FIXED), vxpart);
+       return(&graph[v][FIXED+j]);
+       }
+
+int *expres(v)
+VERT v;
+       {
+       int ty;
+       ty = NTYPE(v);
+       ASSERT(ty == COMPVX || ty == ASGOVX || ty == ASVX || ty == SWCHVX || ty == ICASVX,expres);
+       return(&graph[v][FIXED]);
+       }
+
+int *negpart(v)
+VERT v;
+       {
+       ASSERT(NTYPE(v) == IFVX || NTYPE(v) == ACASVX,negpart);
+       return(&graph[v][FIXED+1]);
+       }
+
+int *predic(v)
+VERT v;
+       {
+       ASSERT(NTYPE(v) == IFVX || NTYPE(v) == ACASVX, predic);
+       return(&graph[v][FIXED]);
+       }
+
+int *level(v)
+VERT v;
+       {
+       ASSERT(NTYPE(v) == GOVX || NTYPE(v) == BRKVX || NTYPE(v) == NXTVX, level);
+       return(&graph[v][FIXED]);
+       }
+int *stlfmt(v,n)
+VERT v;
+int n;
+       {
+       ASSERT(NTYPE(v) == STLNVX || NTYPE(v) == FMTVX,stlfmt);
+       return(&graph[v][FIXED + n]);
+       }
+
+create(type,arcnum)
+int type, arcnum;
+       {
+       int i, *temp, wds;
+       if (nodenum >= maxnode)
+               {
+               maxnode += 100;
+               temp=realloc(graph,maxnode*sizeof(*graph));
+               free(graph);
+               graph=temp;
+               }
+       wds = nonarcs[type] + arcnum;
+       graph[nodenum] = galloc(sizeof(*graph) * wds);
+       for (i = 0; i < wds; i++)  graph[nodenum][i] = 0;
+       NTYPE(nodenum) = type;
+       if (arcsper[type] < 0)
+               ARCNUM(nodenum) = arcnum;
+       
+       return(nodenum++);
+       }
+
diff --git a/usr/src/cmd/struct/0.string.c b/usr/src/cmd/struct/0.string.c
new file mode 100644 (file)
index 0000000..994ec42
--- /dev/null
@@ -0,0 +1,106 @@
+#include <stdio.h>
+#include "def.h"
+#include "1.defs.h"
+
+str_copy(s,ptr,length) /* copy s at ptr, return length of s */
+char *s, *ptr;
+int length;
+       {int i;
+       for (i = 0; i < length; i++)
+               {
+               ptr[i] = s[i];
+               if (ptr[i] == '\0')
+                       return(i + 1);
+               }
+       faterr("string too long to be copied at given address:\n",s,"");
+       }
+
+
+find(s,ar,size)
+char *s,*ar[];
+int size;
+       {
+       int i;
+       for (i=0; i < size; i++)
+               {if (str_eq(s, ar[i])) return(i);}
+       return(-1);
+       }
+
+
+str_eq(s,t)
+char s[],t[];
+       {int j;
+       for (j = 0; s[j] == t[j]; j++)
+               {if (s[j] == '\0') return(1);}
+       return(0);
+       }
+
+
+classmatch(c,i)
+char c;
+int i;
+       {switch(i)
+               {case _digit:
+                       if ('0' <= c && c <= '9')  return(1);
+                       else return(0);
+
+               case _letter:
+                       if ( ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
+                               return(1);
+                       else return(0);
+
+               case _diglet:  return(classmatch(c,_digit)||classmatch(c,_letter) );
+
+               case _arith:
+                       if (050 <= c && c<= 057)  return(1);
+                       else return(0);
+               case _nl:
+                       return(c=='\n');
+               case _other:
+                       return(1);
+               }
+       }
+
+
+copychars(cbeg,target,n)               /* copy n chars from cbeg to target */
+char *cbeg, *target;
+int n;
+       {
+       int i;
+       for (i = 0; i < n; i++)
+               target[i] = cbeg[i];
+       }
+
+
+
+copycs(cbeg,target,n)                  /* copy n chars from cbeg to target, add '\0' */
+char *cbeg, *target;
+int n;
+       {
+       copychars(cbeg,target,n);
+       target[n] = '\0';
+       }
+
+
+slength(s)                     /* return number of chars in s, not counting '\0' */
+char *s;
+       {
+       int i;
+       if (!s) return(-1);
+       for (i = 0; s[i] != '\0'; i++);
+       return(i);
+       }
+
+
+concat(x,y)                    /* allocate space, return xy */
+char *x, *y;
+       {
+       char *temp;
+       int i,j;
+       i = slength(x);
+       j = slength(y);
+       temp = galloc(i + j + 1);
+       sprintf(temp,"%s",x);
+       sprintf(&temp[i],"%s",y);
+       return(temp);
+       }
diff --git a/usr/src/cmd/struct/1.defs.h b/usr/src/cmd/struct/1.defs.h
new file mode 100644 (file)
index 0000000..d0ab63f
--- /dev/null
@@ -0,0 +1,152 @@
+#define snum   145
+#define _s0    0
+#define _s1    1
+#define _s2    2
+#define _s3    3
+#define _s4    4
+#define _start 5
+#define _g     6
+#define _go    7
+#define _got   8
+#define _goto  9
+#define _ugo   10
+#define _ago   11
+#define _agoc  12
+#define _agol  13
+#define _agor  14
+#define _cgo   15
+#define _cgold 16
+#define _cgor  17
+#define _cgoc  18
+#define _i     19
+#define _if    20
+#define _if1   21
+#define _if2   22
+#define _pard  23
+#define _arif  24
+#define _c     25
+#define _co    26
+#define _con   27
+#define _cont  28
+#define _conti 29
+#define _contin        30
+#define _con_u 31
+#define _con_ue        32
+#define _d     33
+#define _do    34
+#define _dol   35
+#define _dov   36
+#define _doveq 37
+#define _a     38
+#define _as    39
+#define _ass   40
+#define _assi  41
+#define _assig 42
+#define _assign        43
+#define _assd  44
+#define _ast   45
+#define _asto  46
+#define _fr    47
+#define _fre   48
+#define _frea  49
+#define _1func 50
+#define _1f    51
+#define _fu    52
+#define _fun   53
+#define _func  54
+#define _funct 55
+#define _fncti 56
+#define _fncto 57
+#define _fin   58
+#define _fint  59
+#define _finte 60
+#define _fintg 61
+#define _finge 62
+#define _fc    63
+#define _fco   64
+#define _fcom  65
+#define _fcomp 66
+#define _fcmpl 67
+#define _fcple 68
+#define _fdou  69
+#define _fdoub 70
+#define _fdobl 71
+#define _fdble 72
+#define _fp    73
+#define _fpr   74
+#define _fpre  75
+#define _fprec 76
+#define _fprci 77
+#define _fpris 78
+#define _fprsi 79
+#define _fprco 80
+#define _fl    81
+#define _flo   82
+#define _flog  83
+#define _flogi 84
+#define _flgic 85
+#define _flgca 86
+#define _s     87
+#define _st    88
+#define _sto   89
+#define _su    90
+#define _sub   91
+#define _subr  92
+#define _subro 93
+#define _subrt 94
+#define _subri 95
+#define _subrn 96
+#define _r     97
+#define _re    98
+#define _ret   99
+#define _retu  100
+#define _retr  101
+#define _e     102
+#define _en    103
+#define _end   104
+#define _ent   105
+#define _entr  106
+#define _fo    107
+#define _for   108
+#define _form  109
+#define _fma   110
+#define _fmt   111
+#define _w     112
+#define _wr    113
+#define _wri   114
+#define _writ  115
+#define _write 116
+#define _read  117
+#define _rdig  118
+#define _rwp   119
+#define _rwlab 120
+#define _rwe   121
+#define _rwen  122
+#define _rwend 123
+#define _endeq 124
+#define _rwer  125
+#define _rwerr 126
+#define _p     127
+#define _pr    128
+#define _pri   129
+#define _prin  130
+#define _pu    131
+#define _pun   132
+#define _punc  133
+#define _bd    134
+#define _bl    135
+#define _blo   136
+#define _blc   137
+#define _blk   138
+#define _bld   139
+#define _blda  140
+#define _bldt  141
+#define ABORT  142
+#define endrt  143
+#define nulls  144
+#define _other 1
+#define _digit 2
+#define _letter        3
+#define _diglet        4
+#define _arith 5
+#define _nl    6
diff --git a/usr/src/cmd/struct/1.finish.c b/usr/src/cmd/struct/1.finish.c
new file mode 100644 (file)
index 0000000..14045fd
--- /dev/null
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include "def.h"
+#include "1.incl.h"
+
+fingraph()
+       {
+       /* if any entry statements, add a DUMVX with arcs to all entry statements */
+       if (ENTLST)
+               {
+               ARC(START,0) = addum(ARC(START,0),ENTLST);
+               freelst(ENTLST);
+               }
+       /* if any FMTVX, add a DUMVX with arcs to all FMTVX's */
+       if (FMTLST)
+               {
+               ARC(START,0) = addum(ARC(START,0),FMTLST);
+               freelst(FMTLST);
+               }
+       }
+
+addum(v,lst)
+VERT v;
+struct list *lst;
+       {
+       VERT new;
+       int count,i;
+       struct list *ls;
+       count = lslen(lst);             /* length of lst */
+       new = create(DUMVX,1+count);
+       ARC(new,0) = v;
+       for (i = count, ls = lst; i >= 1; --i, ls = ls->nxtlist)
+               {
+               ASSERT(ls,addum);
+               ARC(new,i) = ls->elt;
+               }
+       ASSERT(!ls, addum);
+       return(new);
+       }
diff --git a/usr/src/cmd/struct/1.form.c b/usr/src/cmd/struct/1.form.c
new file mode 100644 (file)
index 0000000..df8173c
--- /dev/null
@@ -0,0 +1,218 @@
+#include <stdio.h>
+#include "1.defs.h"
+#include "def.h"
+extern int linechar, errflag, debug;
+extern int (*input)(), (*unput)();
+
+
+
+uptolow(c)             /*translates upper to lower case */
+int c;
+       {
+       if ('A' <= c && c <= 'Z')
+               return(c+'a'-'A');
+       else
+               return(c);
+       }
+
+rdfree(func)
+int (*func)();
+       {
+       int c;
+       while ( (c = (*input)()) != '\n')
+               {
+               (*func)(c);
+               }
+       }
+
+rdstand(func)
+int (*func)();
+       {
+       int c;
+       while ( (c=(*input)()) != '\n')
+               {
+               (*func)(c);
+               }
+       }
+
+labfree(func)                  /* labels in freeform input */
+int (*func)();
+       {
+       int c;
+       int temp[6];
+       int j;
+       for (j = 0; j < 5; ++j)
+               {
+               while ( (c = (*input)()) == ' ' || c == '\t' );
+               if (c == '\n')
+                       {
+                       if (j != 0)
+                               {
+                               temp[j] = '\0';
+                               error("label without code - ignored:","","");
+                               }
+                       }
+               if (c < '0' || c > '9')
+                       {
+                       (*unput)(c);
+                       break;
+                       }
+               else
+                       {
+                       temp[j] = c;
+                       (*func)(c);
+                       }
+               }
+       for ( ; j < 5; ++j)
+               (*func)(' ');
+       }
+
+labstand(func)                 /* labels in standard form input */
+int (*func)();
+       {
+       int c;
+       int j;
+
+       for (j = 0; j < 5; ++j)
+               {
+               c = (*input)();
+               if (c == '\n')
+                       {
+                       error("line shorter than 5 characters","","");
+                       errflag = 1;
+                       (*unput)('\n');
+                       }
+               if (c == '\t' || c == '\n')
+                       {
+                       for ( ;j<5; ++j)
+                               (*func)(' ');
+                       return;
+                       }
+               (*func)(c);
+               }
+       (*input)();                     /* throw away continuation char */
+       }
+
+
+
+contfree()                     /* identify continuation lines in free-form input */
+       {
+       return(nonblchar(_diglet,0));   /* any non-alpha non-digit */
+       }
+
+
+nonblchar(class,yesno)
+int class,yesno;
+       {
+#define CARDSIZE       121
+       int temp[CARDSIZE];
+       int j;
+       for (j=0; (temp[j]=(*input)()) == ' ' || temp[j] == '\t'; ++j)
+               if (j>=CARDSIZE-1)
+                       {
+                       temp[CARDSIZE-1] = '\0';
+                        error ("line unexpectedly long","","");
+                       break;
+                       }
+       if (temp[j]!=EOF && classmatch(temp[j],class)==yesno)
+               return(1);
+       else
+               {
+               for ( ; j >= 0; --j)
+                       (*unput)(temp[j]);
+               return(0);
+               }
+       }
+
+
+contstand()                    /* continuation lines in standard form input */
+       {
+       int temp[6];
+       int i;
+
+       for (i = 0; i < 6; ++i)
+               {
+               temp[i] = (*input)();
+               if (temp[i] == '\t' || temp[i] == '\n' || temp[i] == '\0' || temp[i] == EOF)
+                       {
+                       for ( ;i >= 0; --i)
+                               (*unput)(temp[i]);
+                       return(0);
+                       }
+               }
+       if (temp[5] != '0' && temp[5] != ' ')
+               return(1);
+       else
+               {
+               for ( i = 5 ; i >= 0; --i)
+                       (*unput)(temp[i]);
+               return(0);
+               }
+       }
+
+
+
+comstand(posafter)                     /* standard form comments */
+int posafter;
+       {
+       int c;
+       c = (*input)();
+       if (!posafter)
+               (*unput)(c);
+       if (c == 'c' || c == '*' || c== '#')
+               return(1);
+       else
+               return(0);
+       }
+
+
+comfree(posafter)
+int posafter;
+       {
+       return(comstand(posafter));
+       }
+int (*rline[])()               = {rdfree,rdstand};
+int (*comment[])()             = {comfree,comstand};
+int (*getlabel[])()            = {labfree, labstand};
+int (*chkcont[])()             = {contfree,contstand};
+
+blankline()
+       {
+       if ( nonblchar(_nl,1) )         /* first non-blank is nl */
+               {
+               (*unput) ('\n');
+               return(1);
+               }
+       else return(0);
+       }
+
+#define maxunbp        80
+char unbuf[maxunbp+1];
+int unbp;
+
+empseek(linebeg)
+int linebeg;
+       {
+       unbp = 0;
+       if (fseek(infd,(long)(linebeg+rtnbeg),0) == -1)
+               faterr("in disk seek","","");
+       }
+
+inchar()
+       {
+       if (unbp > 0)
+               return( unbuf[--unbp] );
+       else
+               {
+               return( uptolow(getc(infd)) );
+               }
+       }
+
+
+unchar(c)
+int c;
+       {
+       if (unbp >= maxunbp)
+               faterr("dec.rat: unbuf size exceeded","","");
+       if(c!=EOF)unbuf[unbp++] = c;
+       }
diff --git a/usr/src/cmd/struct/1.fort.c b/usr/src/cmd/struct/1.fort.c
new file mode 100644 (file)
index 0000000..5dc0658
--- /dev/null
@@ -0,0 +1,260 @@
+#include <stdio.h>
+#include "1.incl.h"
+#include  "1.defs.h"
+#include "def.h"
+
+
+act(k,c,bufptr)
+int k,bufptr;
+char c;
+       {
+       long ftemp;
+       struct lablist *makelab();
+       switch(k)
+               /*handle labels */
+               {case 1:
+                       if (c != ' ')
+                               {
+                       ftemp = c - '0';
+                               newlab->labelt = 10L * newlab->labelt + ftemp;
+
+                               if (newlab->labelt > 99999L)
+                                       {
+                               error("in syntax:\n","","");
+                                       fprintf(stderr,"line %d: label beginning %D too long\n%s\n",
+                                               begline,newlab->labelt,buffer);
+                                       fprintf(stderr,"treating line as straight line code\n");
+                                       return(ABORT);
+                                       }
+                               }
+                       break;
+
+               case 3:  nlabs++;
+                       newlab = newlab->nxtlab = makelab(0L);
+                       break;
+
+               /* handle labsw- switches and labels */
+               /* handle if statements */
+               case 30:  counter++;  break;
+
+               case 31:
+                       counter--;
+                       if (counter)  return(_if1);
+                       else
+                               {
+                               pred = remtilda(stralloc(&buffer[p1],bufptr - p1));
+                               p3 = bufptr + 1;        /* p3 pts. to 1st symbol after ) */
+                               flag = 1;
+                               return(_if2);  }
+
+               case 45:                        /* set p1 to pt.to 1st symbol of pred */
+                       p1 = bufptr + 1;
+                       act(30,c,bufptr);  break;
+
+               /* handle do loops */
+               case 61:  p1 = bufptr;  break;   /* p1 pts. to 1st symbol of increment  string */
+
+               case 62:  counter ++;  break;
+
+               case 63:  counter --; break;
+
+               case 64: 
+                       if (counter != 0) break;
+                       act(162,c,bufptr);
+                       return(ABORT);
+
+               case 70:  if (counter)  return(_rwp);
+                       r1 = bufptr;
+                       return(_rwlab);
+
+               case 72:        exp = remtilda( stralloc(&buffer[r1+1],bufptr - r1 - 1));  break;
+
+               case 73:  endlab = newlab;  
+                       break;
+
+               case 74:  errlab = newlab;  
+                       break;
+
+               case 75:  reflab = newlab;
+                       act(3,c,bufptr);
+                       break;
+
+               case 76:  r1 = bufptr;  break;
+
+               case 77:
+                       if (!counter)
+                       {
+                               act(111,c,bufptr);
+                               return(ABORT);
+                               }
+                       counter--;
+                       break;
+               /* generate nodes of all types */
+               case 111:               /* st. line code */
+                       stcode = remtilda(stralloc(&buffer[p3],endbuf - p3));
+                       recognize(STLNVX,flag);
+                       return(ABORT);
+
+               case 122:                       /* uncond. goto */
+                       recognize(ungo,flag);
+                       break;
+
+               case 123:                       /* assigned goto */
+                       act(72,c,bufptr);
+                       faterr("in parsing:\n","assigned goto must have list of labels","");
+
+               case 124:                       /* ass. goto, labels */
+                       recognize(ASGOVX, flag);
+                       break;
+
+               case 125:                       /* computed goto*/
+                       exp = remtilda( stralloc(&buffer[r1+1],bufptr - r1 - 1));
+                       recognize(COMPVX, flag);
+                       return(ABORT);
+
+               case 133:                       /* if() =  is a simple statement, so reset flag to 0 */
+                       flag = 0;
+                       act(111,c,bufptr);
+                       return(ABORT);
+
+               case 141:                       /* arith. if */
+                       recognize(arithif, 0);
+                       break;
+
+               case 150:                       /* label assignment */
+                       exp = remtilda( stralloc(&buffer[r1+1],bufptr - r1 - 1));
+                       recognize(ASVX, flag);
+                       break;
+
+               case 162:                       /*  do node */
+                       inc = remtilda(stralloc(&buffer[p1],endbuf - p1));
+                       recognize(DOVX, 0);
+                       break;
+
+               case 180:                       /* continue statement */
+                       recognize(contst, 0);
+                       break;
+
+               case 200:               /* function or subroutine statement */
+                       progtype = sub;
+                       nameline = begline;
+                       recognize(STLNVX,0);
+                       break;
+
+
+               case 210:               /* block data statement */
+                       progtype = blockdata;
+                       act(111,c,bufptr);
+                       return(ABORT);
+
+               case 300:                       /* return statement */
+                       recognize(RETVX,flag);
+                       break;
+
+
+               case 350:                       /* stop statement */
+                       recognize(STOPVX, flag);
+                       break;
+
+
+               case 400:                       /* end statement */
+                       if (progtype == sub)
+                               act(300, c, bufptr);
+                       else
+                               act(350, c, bufptr);
+                       return(endrt);
+
+               case 500:
+                       prerw = remtilda(stralloc(&buffer[p3],r1 - p3 + 1));
+                       postrw = remtilda(stralloc(&buffer[r2],endbuf - r2));
+                       if (reflab || endlab || errlab)  recognize(IOVX,flag);
+                       else recognize(STLNVX,flag);
+                       return(ABORT);
+
+               case 510:  r2 = bufptr;
+                       act(3,c,bufptr);
+                       act(500,c,bufptr);
+                       return(ABORT);
+
+               case 520:               r2 = bufptr;
+                       reflab = newlab;
+                       act(3,c,bufptr);
+                       act(500,c,bufptr);
+                       return(ABORT);
+
+
+               case 600:
+                       recognize(FMTVX,0);  return(ABORT);
+
+               case 700:
+                       stcode = remtilda(stralloc(&buffer[p3],endbuf - p3));
+                       recognize(entry,0);  return(ABORT);
+               /* error */
+               case 999:
+                       printf("error: symbol '%c' should not occur as %d'th symbol of: \n%s\n",
+                               c,bufptr, buffer);
+                       return(ABORT);
+               }
+       return(nulls);
+       }
+
+
+
+struct lablist *makelab(x)
+long x;
+       {
+       struct lablist *p;
+       p = challoc (sizeof(*p));
+       p->labelt = x;
+       p->nxtlab = 0;
+       return(p);
+       }
+
+
+long label(i)
+int i;
+       {
+       struct lablist *j;
+       for (j = linelabs; i > 0; i--)
+               {
+               if (j == 0) return(0L);
+               j = j->nxtlab;
+               }
+       if (j)
+               return(j->labelt);
+       else
+               return(0L);
+       }
+
+
+freelabs()
+       {
+       struct lablist *j,*k;
+       j = linelabs;
+       while(j != 0)
+               {
+               k = j->nxtlab;
+               chfree(j,sizeof(*j));
+               j = k;
+               }
+       }
+
+
+stralloc(ad,n)                 /* allocate space, copy n chars from address ad, add '0' */
+int n; char *ad;
+       {
+       char *cp;
+       cp = galloc(n+1);
+       copycs(ad,cp,n);
+       return(cp);
+       }
+
+
+remtilda(s)                    /* change ~ to blank */
+char *s;
+       {
+       int i;
+       for (i = 0; s[i] != '\0'; i++)
+               if (s[i] == '~') s[i] = ' ';
+       return(s);
+       }
diff --git a/usr/src/cmd/struct/1.hash.c b/usr/src/cmd/struct/1.hash.c
new file mode 100644 (file)
index 0000000..db0847e
--- /dev/null
@@ -0,0 +1,238 @@
+#include <stdio.h>
+#include "1.incl.h"
+#include "1.defs.h"
+#include"def.h"
+
+extern int match[], symclass[],  action[], newstate[];
+extern char symbol[];
+long *hashtab;
+int *value, *chain;
+
+extern FILE *infd;
+
+
+parse()
+       {int i,j,found,current, someread;
+       char c;
+
+       hash_init();
+       routinit();
+       line_init();
+
+       someread = 0;                   /* indicates haven't read part of a routine */
+
+       empseek(0);
+       endbuf = getline(&endline, &endchar, &endcom, & comchar);
+       if (progress && endbuf != -1) fprintf(stderr,"parsing\n");
+       while(endbuf != -1)                     /* getline returns -1 when no more input */
+               {
+               someread = 1;
+               if (progress > 0)
+                       {
+                       for (i = begline; i <= endline; i++)
+                               if (!(i % progress)) fprintf(stderr,"parsing line %d\n",i);
+                       }
+               current = 0;
+               for (i = 0; i < endbuf; i++)
+                       {
+
+                       c = buffer[i];
+                       if(c != '~') 
+                               {
+                               found = 0;
+                               if ( (current < 0 || current >= snum) && current != ABORT)
+                                       {
+                                       strerr("in parsing:","","");
+                                       fprintf(stderr,"line %d of file, parser in invalid state", begline,current);
+                                       fprintf(stderr,"treating it as straight line code\n");
+                                       current = ABORT;
+                                       }
+                               else
+                                       for (j = match[current];  j < match[current + 1]; j++)
+                                               {
+                                               if ((symclass[j] == 0 && c == symbol[j]) ||
+                                                   (symclass[j] != 0 && classmatch(c,symclass[j]) ))
+                                                       {found = 1;  break;
+                                                       }
+                                               }
+                               if (!found)
+                                       {
+                                       error("in syntax:","","");
+                                       fprintf(stderr,"between lines %d and %d of file\n",begline, endline);
+                                       if (debug)
+                                       fprintf(stderr,"symbol '%c' does not match entries for state %d\n",c,current);
+                                       fprintf(stderr,"treating it as straight line code\n");
+                                       current = ABORT;
+                                       }
+                               else if (!action[j])  
+                                       current = newstate[j];
+                               else
+                                       {
+                                       current = act(action[j],c,i);
+                                       if (current == nulls)  current = newstate[j];
+                                       }
+                               if (current == ABORT)  break;
+                               if (current == endrt)
+                                       {
+                                       return(1);
+                                       }
+                               }
+                       }
+               line_init();
+               endbuf = getline(&endline, &endchar, &endcom,&comchar);
+               }
+       if (someread) return(1);
+       else return(0);
+       }
+
+
+hash_init()
+       {
+       int i;
+       hashtab = challoc(sizeof(*hashtab) * maxhash);
+       chain = challoc(sizeof(*chain) * maxhash);
+       value = challoc(sizeof(*value) * maxhash);
+       for (i = 0; i < maxhash; i++)
+               {
+               hashtab[i] = -1L;
+               value[i] = -2;
+               chain[i] = 0;
+               }
+       }
+
+
+hash_check()
+       {
+       int i;
+       for (i = 0; i < maxhash; ++i)
+               if (value[i] == -2 && hashtab[i] != -1L)
+                       {
+                       error("in syntax; label used but does not appear as statement label:","","");
+                       fprintf(stderr,"%D\n",hashtab[i]);
+                       routerr = 1;
+                       }
+       }
+
+hash_free()
+       {
+       chfree(hashtab,sizeof(*hashtab) * maxhash);
+       hashtab = 0;
+       chfree(chain,sizeof(*chain) * maxhash);
+       chain = 0;
+       chfree(value,sizeof(*value) * maxhash);
+       value = 0;
+       }
+hash(x)
+long x;
+       {
+       int quo, rem, hcount, temp;
+
+       ASSERT(x >= 0L, hash);
+       quo = x/maxhash;
+       rem = x - (quo * maxhash);
+       if (quo == 0)  quo = 1;
+
+       temp = rem;
+       for (hcount=0; (hashtab[temp] != -1L) && (hashtab[temp] != x) && (hcount<maxhash); hcount++)
+               temp = (temp + quo)%maxhash;
+       if(hcount>=maxhash) faterr("hash table overflow - too many labels","","");
+       hashtab[temp] = x;
+       return(temp);
+       }
+
+addref(x,ptr)                          /* put ptr in chain for x or assign value of x to *ptr */
+long x;
+int *ptr;
+       {
+       int index;
+       index = hash(x);
+
+       if (value[index]  == -1)
+               {                       /* x already assigned value */
+               *ptr = chain[index];
+               return;
+               }
+       
+       /* add ptr to chain */
+       
+       if (chain[index] == 0)
+               *ptr = 0;
+       else
+               *ptr = chain[index];
+       chain[index] = ptr;
+       }
+
+fixvalue (x,ptr)
+long x;
+int ptr;
+       {
+       int *temp1, *temp2, index, temp0;
+       index = hash(x);
+
+       while (index != -2)
+               {                       /* trace chain of linked labels */
+
+               if (value[index]  == -1)
+                       {
+                       error("in syntax:  ","","");
+                       fprintf(stderr,"attempt to redefine value of label %D between lines %d and %d\n",
+                               x,begline,endline);
+                       routerr = 1;
+                       return;
+                       }
+       
+               temp1 = &chain[index];          /* trace chain for each label */
+               while (temp1 != 0)
+                       {
+                       temp2 = *temp1;
+                       *temp1 = ptr;
+                       temp1 = temp2;
+                       }
+               temp0 = index;
+               index = value[index];
+               value[temp0] = -1;
+               }
+       }
+
+connect(x,y)
+long x,y;
+       {
+       int *temp, index, temp2;
+       index = hash(x);
+
+       if (value[index] == -1)
+               fixvalue(y, chain[index]);
+       else
+               {
+               if (y == implicit)
+               {               /* attach implicit chain to x chain */
+               temp = &chain[index];
+       
+               while (*temp != 0)
+                       temp = *temp;
+       
+               *temp = chain[hash(y)];
+               }
+               temp2 = index;          /* attach y linked labels to x linked labels */
+               while (value[temp2] >= 0)
+                       temp2 = value[temp2];
+               if (y == implicit)
+                       value[temp2] = value[hash(y)];
+               else
+                       value[temp2] = hash(y);
+               }
+       if (y == implicit)  clear(y);
+       }
+       
+       
+clear(x)
+long x;
+       {
+       int index;
+       index = hash(x);
+       value[index] = -2;
+       chain[index] = 0;
+       hashtab[index] = -1L;
+       }
+
+
diff --git a/usr/src/cmd/struct/1.incl.h b/usr/src/cmd/struct/1.incl.h
new file mode 100644 (file)
index 0000000..1ff82a9
--- /dev/null
@@ -0,0 +1,39 @@
+#define maxlsw         10      /* max number of switches and labels per statement */
+#define implicit 0L            /* "label" of following line so all flow can be treated as jump to label */
+struct lablist {long labelt;  struct lablist *nxtlab; };
+extern struct lablist *endlab, *errlab, *reflab, *linelabs, *newlab;
+extern long label();
+
+extern int routbeg;                    /* line number of first line of routine */
+extern int nameline;                   /* line number of function/subroutine st., if any */
+extern int stflag;             /* determines whether at beginning or middle of block of straight line code */
+
+
+
+extern char buffer[];
+extern int endbuf;
+
+extern int   nlabs, lswnum, swptr, flag,
+        counter, p1, p3, begline, endline, r1,r2, endcom;
+extern long begchar, endchar, comchar;
+
+
+/* statement types not associated with actual node types */
+#define contst         -1
+#define ungo           -2
+#define arithif                -3
+#define readst         -8
+#define writest                -9
+#define entry  -10
+
+
+extern char *pred, *inc, *prerw, *postrw, *exp, *stcode;
+
+#define maxdo  20      /* max nesting of do loops */
+extern long dostack[maxdo];            /* labels of do nodes */
+extern int doloc[maxdo];               /* loc of do node */
+extern int doptr;
+
+
+extern struct list *FMTLST;            /* list of FMTVX's generated */
+extern struct list *ENTLST;            /* list of STLNVX nodes corresponding to entry statements */
diff --git a/usr/src/cmd/struct/1.init.c b/usr/src/cmd/struct/1.init.c
new file mode 100644 (file)
index 0000000..5f907e3
--- /dev/null
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include "1.defs.h"
+#include  "1.incl.h"
+#include "def.h"
+
+
+prog_init()
+       {
+       endline = endcom = 0;   endchar = -1;
+       comchar = -1;
+       graph = challoc(sizeof(*graph) * maxnode);
+       }
+
+routinit()
+       {
+       graf_init();
+       progtype = !sub;
+       routbeg = endline + 1;
+       rtnbeg = endchar + 1;
+       nameline = 0;
+       stflag = UNDEFINED;
+       }
+line_init()
+       {
+       struct lablist *makelab();
+       freelabs();
+       newlab = linelabs = makelab(0L);
+       flag = counter = nlabs = lswnum = swptr = p1 = 0;
+       p3 = 5;
+       endcom = endline;
+       comchar = endchar;
+       begline = endline + 1;  begchar = endchar + 1;
+       reflab = endlab = errlab = 0;
+       r1 = r2 = 0;
+       }
+graf_init()
+       {
+       int arctype[3];  long arclab[3];
+       nodenum = 0;
+       doptr = UNDEFINED;
+       retvert = stopvert = UNDEFINED;
+       ENTLST = FMTLST = 0;
+
+       
+       arctype[0] = -2;  arclab[0] = implicit;
+       START = makenode(DUMVX,FALSE,FALSE,implicit,1,arctype,arclab);
+       }
+
diff --git a/usr/src/cmd/struct/1.line.c b/usr/src/cmd/struct/1.line.c
new file mode 100644 (file)
index 0000000..7cc98e9
--- /dev/null
@@ -0,0 +1,116 @@
+#include <stdio.h>
+#
+#include "def.h"
+#define bufsize 1601
+char buffer[bufsize];
+int bufcount;
+extern int errflag;
+long stchars;                  /* counts number of chars at most recent \n read */
+#ifndef unix
+long ostchars;
+extern long ftell();
+#endif
+int newline;                   /* counts number of lines read so far in file */
+extern int rdfree(), comfree(),labfree(), contfree();
+extern int rdstand(), comstand(), labstand(), contstand();
+extern int (*rline[])();
+extern int (*comment[])();
+extern int (*getlabel[])();
+extern int (*chkcont[])();
+
+
+
+flush()
+       {bufcount = 0; }
+
+addchar(c)
+       {
+       buffer[bufcount++] = c;
+       }
+
+getline(lastline,lastchar,linecom,charcom)
+int *lastline, *linecom;
+long *lastchar, *charcom;
+                               /* set *lastline to number of last line of statement,
+                               set *lastchar to number of last char of statement,
+                               set *linecom to number of last line of comment preceding statement */
+       {
+
+       int i;
+       flush();
+       while ( unput1(input1()) != EOF)
+               {
+               while ( (*comment[inputform])(0)  || blankline() )
+                       {
+                       (*rline[inputform])(addchar);
+                       flush();
+                       }
+               *linecom = newline;
+                       /* set charcom to number of last char of comment, starting at 0
+                                       if at start of file and no comment, will be -1  */
+               *charcom = stchars - 1;
+               if (unput1(input1()) == EOF)  break;
+               (*getlabel[inputform])(addchar);
+               (*rline[inputform])(addchar);
+       
+               while ( blankline() || ( !(*comment[inputform])(0) &&  (*chkcont[inputform])() ))
+                       (*rline[inputform])(addchar);
+       
+               addchar('\0');
+               *lastline = newline;
+               *lastchar = stchars - 1;
+if (debug == 40)
+fprintf(stderr,"line %d; bufcount: %d\n",newline,bufcount);
+       
+               for (i = 5; i < bufcount; ++i)
+                       if (buffer[i] == ' ' || buffer[i] == '\t' || buffer[i] == '\n')
+                               buffer[i] = '~';
+               return(bufcount);
+               }
+       return(-1);
+       }
+
+
+int linechars;                 /* counts number of chars read so far in current line */
+long newchar;                  /* counts number of chars read so far in file */
+
+
+input1()
+       {
+       static int c;
+       if (c == '\n') linechars = 0;
+       c = inchar();
+       ++linechars;
+       ++newchar;
+       if (c == '\n')
+               {
+               ++newline;
+#ifdef unix
+               stchars = newchar; 
+#else
+               ostchars=stchars; stchars=ftell(infd);
+#endif
+               }
+       return(c);
+       }
+
+unput1(c)
+       {
+       --linechars;
+       --newchar;
+       unchar(c);
+       if (c == '\n')
+               {
+#ifdef unix
+               stchars = newchar; 
+#else
+               stchars=ostchars;
+#endif
+               --newline;
+               }
+       return(c);
+       }
+
+
+
+
diff --git a/usr/src/cmd/struct/1.main.c b/usr/src/cmd/struct/1.main.c
new file mode 100644 (file)
index 0000000..40e7848
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include "def.h"
+int endbuf;
+
+mkgraph()
+       {
+       if (!parse())
+               return(FALSE);
+       hash_check();
+       hash_free();
+       fingraph();
+       return(TRUE);
+       }
diff --git a/usr/src/cmd/struct/1.node.c b/usr/src/cmd/struct/1.node.c
new file mode 100644 (file)
index 0000000..b57ff11
--- /dev/null
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include "def.h"
+#include "1.incl.h"
+
+makenode(type,addimp,addcom, labe,arcnum,arctype,arclab)
+LOGICAL addimp,addcom;
+int type, arctype[], arcnum;
+long arclab[], labe;
+       {
+       int i;
+       VERT num;
+       
+       ASSERT(arcsper[type] < 0 || arcnum == arcsper[type], makenode);
+       num = create(type,arcnum);
+       
+       if (addimp)  fiximp(num,labe);
+       
+       for (i = 0; i < arcnum; ++i)
+               {
+               if (arctype[i] == -2)
+                       addref(arclab[i],&ARC(num,i));
+               else
+                       ARC(num,i) = arctype[i];
+               }
+       
+       
+       if (hascom[type] )
+               {
+               if (!addcom || endcom < begline)
+                       BEGCOM(num) = UNDEFINED;
+               else
+                       BEGCOM(num) = begchar - rtnbeg;
+               }
+       return(num);
+       }
+
+
+
+
+
+fiximp(num,labe)               /* fix implicit links, check nesting */
+VERT num;
+long labe;
+       {
+       fixvalue(implicit, num);                /* set implicit links to this node */
+       clear(implicit);
+       if(labe != implicit) fixvalue(labe, num);
+       }
diff --git a/usr/src/cmd/struct/1.recog.c b/usr/src/cmd/struct/1.recog.c
new file mode 100644 (file)
index 0000000..6e15c84
--- /dev/null
@@ -0,0 +1,374 @@
+#include <stdio.h>
+#include "1.incl.h"
+#include "def.h"
+
+
+recognize(type, ifflag)                        /* if ifflag = 1, statement is if()type; otherwise is type */
+int type, ifflag;                              /* do whatever is needed for this statement */
+       {
+       int *arctype,   i,   sp;
+       VERT num, num1, nest, loophead;
+       extern long label();
+       long *arclab;
+       if (nlabs > 3) sp = nlabs; else sp = 3;
+       arctype = challoc(sizeof(*arctype) * sp);  arclab = challoc(sizeof(*arclab) * sp);
+       for( i=0; i < endbuf; i++)  {if (buffer[i] == '~')  buffer[i] = ' ';}
+       loophead = nest = innerdo(label(0));
+       if (DEFINED(nest))
+               {
+                       /* this statement is last line of do loop */
+               nest = ARC(nest,0);             /* nest is ITERVX of the innermost do ending here */
+               }
+
+
+       if (ifflag)
+               {
+               if (type == ungo)
+                       {
+                       arctype[0] = -2;
+                       arclab[0] = label(1);
+                       }
+               else
+                       arctype[0] = 0;
+
+               arctype[1] = (nest >= 0) ? nest : -2;
+               arclab[1] = implicit;
+               num1 = makenode(IFVX,TRUE,TRUE,label(0),2,arctype,arclab);
+               PRED(num1) = pred;
+               }
+
+       arctype[0] = (nest >= 0) ? nest : -2;
+       arclab[0] = implicit;
+
+       switch(type)
+               {
+               case ungo:
+                       if (!ifflag)
+                               {
+                               connect(label(1),implicit);
+                               if (label(0) != implicit)  connect(label(1),label(0));
+                               }
+                       break;
+               case RETVX:
+               case STOPVX:
+                       if (type == RETVX)
+                               {
+                               if (retvert == UNDEFINED)
+                                       retvert = makenode(type,FALSE,FALSE,implicit,0,arctype,arclab);
+                               num = retvert;
+                               }
+                       else
+                               {
+                               if (stopvert == UNDEFINED)
+                                       stopvert = makenode(type,FALSE,FALSE,implicit,0,arctype,arclab);
+                               num = stopvert;
+                               }
+                       if (!ifflag)
+                               {
+                               fixvalue(implicit,num);
+                               clear(implicit);
+                               if (label(0) != implicit) fixvalue(label(0),num);
+                               }
+                       break;
+
+
+               case contst:
+                       contin(label(0),loophead);
+                       break;
+
+               case FMTVX:
+                       num = makenode(FMTVX,FALSE,TRUE,implicit,0,arctype,arclab);
+                       BEGCODE(num) = comchar + 1 - rtnbeg;
+                       ONDISK(num) = endline - endcom;
+                       if (label(0) != implicit)
+                               fixvalue(label(0),num);
+                       FMTLST = append(num,FMTLST);
+                       break;
+               case STLNVX:
+                       if (DEFINED(stflag) && !ifflag && (label(0) == implicit))
+                               {
+                               ++CODELINES(stflag);
+                               ONDISK(stflag) += endline - begline + 1;
+                               }
+                       else
+                               {
+                               num = makenode(STLNVX,!ifflag,!ifflag,label(0),1,arctype,arclab);
+                               if (!ifflag)
+                                       {
+                                       stflag = num;
+                                       BEGCODE(num) = comchar + 1 - rtnbeg;
+                                       ONDISK(num) = endline - endcom;
+                                       CODELINES(num) = 1;
+                                       }
+                               else
+                                       {
+                                       BEGCODE(num) = stcode;
+                                       ONDISK(num) = FALSE;
+                                       CODELINES(num) = 1;
+                                       }
+                               }
+                       break;
+
+               case DOVX:
+                       if (arctype[0] != -2) 
+                               {
+                               error("illegal do range, ","","");
+                               fprintf(stderr," between lines %d and %d\n",begline, endline);
+                               exit(1);
+                               }
+                       arctype[1] = UNDEFINED;
+                       num1 = makenode(DOVX,TRUE,TRUE,label(0),2,arctype,arclab);
+                       if (++doptr >= maxdo)
+                               {
+                               faterr("in parsing:\n","do loops nested deeper than allowed","");
+                               }
+                       dostack[doptr] = label(1);
+                       doloc[doptr] = num1;                    /* stack link to node after loop */
+                       INC(num1) = inc;
+                       num = makenode(ITERVX,TRUE,FALSE,implicit,1,arctype,arclab);
+                       ARC(num1,0) = num;
+                       FATH(num) = UNDEFINED;  /* number of DOVX can change so leave UNDEFINED until later */
+                       break;
+               case arithif:
+                       if (label(1) == label(2) || label(1) == 0L)
+                               makeif(1,label(0),concat(pred," > 0"),label(3),label(2));
+                       else if (label(1) == label(3) || label(3) == 0L)
+                               makeif(1,label(0),concat(pred," == 0"),label(2),label(1));
+                       else if (label(2) == label(3) || label(2) == 0L)
+                               makeif(1,label(0),concat(pred," < 0"),label(1),label(3));
+                       else
+                               {
+                               makeif(1,label(0),concat(pred," < 0"),label(1),implicit);
+                               makeif(1,implicit,concat(pred," == 0"),label(2),label(3));
+                               }
+                       break;
+
+               case IOVX:
+                       if (endlab)
+                               {
+                               arctype[1] = -2;
+                               arclab[1] = endlab->labelt;
+                               }
+                       else
+                               arctype[1] = UNDEFINED;
+                       if (errlab)
+                               {
+                               arctype[2] = -2;
+                               arclab[2] = errlab->labelt;
+                               }
+                       else
+                               arctype[2] = UNDEFINED;
+                       num = makenode(IOVX,!ifflag,!ifflag,label(0),3,arctype,arclab);
+                       PRERW(num) = prerw;
+                       POSTRW(num) = postrw;
+                       if (reflab)
+                               addref(reflab->labelt, &FMTREF(num));
+                       else
+                               FMTREF(num) = UNDEFINED;
+                       break;
+
+               case COMPVX:
+                               if (intcase)
+                                       {
+                                       num = compcase(ifflag);
+                                       break;
+                                       }
+               case ASGOVX:
+                       for (i = 0; i < nlabs - 1; i++)
+                               {
+                               arctype[i] = -2;
+                               arclab[i] = label(nlabs-i-1);
+                               }
+                       num = makenode(type,!ifflag,!ifflag,label(0),nlabs - 1, arctype, arclab);
+                       EXP(num) = exp;
+                       break;
+               case ASVX:
+                       num = makenode(ASVX,!ifflag,!ifflag,label(0),1,arctype,arclab);
+                       EXP(num) = exp;
+                       addref(label(1),&LABREF(num));
+                       break;
+               case entry:
+                       num = makenode(STLNVX,FALSE,TRUE,label(0),1,arctype,arclab);
+                       BEGCODE(num) = comchar + 1 - rtnbeg;
+                       ONDISK(num) = endline - endcom;
+                       CODELINES(num) = 1;
+                       ENTLST = append(num,ENTLST);
+                       break;
+               }
+       if (ifflag && type != ungo)
+               {
+               ARC(num1,0) = num;
+               }
+       if (DEFINED(loophead))  nesteddo(label(0), loophead);
+       if (ifflag || DEFINED(loophead) || type != STLNVX)  stflag = UNDEFINED;
+
+
+       chfree(arctype,sizeof(*arctype) * sp);  chfree(arclab,sizeof(*arclab) * sp);
+       if (debug)
+               {
+               fprintf(debfd,"line %d:  ", begline);
+               if (ifflag) fprintf(debfd,"if()  ");
+               switch(type)
+                       {case RETVX:    fprintf(debfd,"return");        break;
+                       case STOPVX:    fprintf(debfd,"stop");  break;
+                       case contst:    fprintf(debfd,"continue");      break;
+                       case ungo:      fprintf(debfd,"uncond. goto");  break;
+                       case COMPVX:    fprintf(debfd,"comp. goto");    break;
+                       case ASGOVX:    fprintf(debfd,"ass. goto, labs");       break;
+                       case ASVX:      fprintf(debfd,"label assignment");      break;
+                       case STLNVX:    fprintf(debfd,"simple statement");      break;
+                       case arithif:   fprintf(debfd,"arith if");      break;
+                       case DOVX:      fprintf(debfd,"do ");   break;
+                       case FMTVX:  fprintf(debfd,"format st");  break;
+                       case IOVX:  fprintf(debfd,"IOVX statement ");  break;
+case entry:    fprintf(debfd,"entry statement ");  break;
+                       }
+               fprintf(debfd,"\n%s\n", buffer);
+               }
+       }
+
+
+
+makeif(first,labe,test,arc1,arc2)                      /* construct IFVX with arcs to labels arc1,arc2 */
+int first;
+long labe, arc1,arc2;
+char *test;
+       {
+       int num, arctype[2];
+       long arclab[2];
+       arctype[0] = arctype[1] = -2;
+       arclab[0] = arc1;
+       arclab[1] = arc2;
+       num = makenode(IFVX,first,first,labe,2,arctype,arclab);
+       PRED(num) = test;
+       return(num);
+       }
+
+
+innerdo(labe)          /* return number of DOVX associated with labe, or UNDEFINED */
+long labe;
+       {
+       if (DEFINED(doptr))
+               {if (dostack[doptr] == labe)
+                       return(doloc[doptr--]);
+               }
+       return(UNDEFINED);
+       }
+
+
+
+
+contin(labe,nest)              /* handle continue statements */
+long labe;
+int nest;
+       {
+       VERT y;
+       
+       if (!DEFINED(nest))
+               {               /* not nested */
+               if (labe != implicit) connect(implicit,labe);   /* labe pts to next node */
+               }
+       else
+               {               /* nested */
+               y = ARC(nest,0);
+               fixvalue(labe,y);                       /* labe pts to ITERVX */
+               fixvalue(implicit, y);          /* implicit links pt to ITERVX */
+               clear(implicit);
+               }
+       }
+
+
+
+
+nesteddo(labe,v)
+                       /* if multiple do's end on same label, add arc from inner DOVX
+                               to enclosing DOVX;
+                       add implicit link out of outermost DOVX with this label */
+long labe;
+int v;
+       {
+       
+       while (DEFINED(doptr) && dostack[doptr] == labe)
+               {
+               ARC(v,1) = ARC(doloc[doptr],0);         /*set inner DOVX to point to outer ITERVX */
+               v = doloc[doptr--];
+               }
+       addref(implicit, &ARC(v,1));
+       }
+
+
+
+compcase(ifflag)               /* turn computed goto into case statement */
+LOGICAL ifflag;
+       {
+       int *arctype, i, num, d, arct;
+       extern long label();
+       long *arclab;
+       char *str;
+       arctype = challoc(sizeof(*arctype) * nlabs);
+       arclab = challoc (sizeof(*arclab) * nlabs);
+
+       d = distinct(linelabs->nxtlab,arctype,arclab,nlabs-1);
+                       /* puts distinct labels in arclab, count of each in arctype */
+       arct = -2;
+       for (i = 0; i < d; ++i)
+               arctype[i] = makenode(ICASVX,FALSE,FALSE,implicit,1,&arct,&arclab[i]);
+       num = makenode(SWCHVX,!ifflag,!ifflag,label(0),d,arctype,arclab);
+       EXP(num) = exp;
+
+       str = challoc(6*(nlabs-1));     /* 5 digits + , or \0 per label */
+       for (i = 0; i < d; ++i)         /* construct list of values for each label */
+               EXP(arctype[i]) = stralloc(str,accum(str,linelabs->nxtlab,arclab[i]));
+       chfree(str,6*(nlabs-1));
+       chfree(arctype,sizeof(*arctype) * nlabs);  chfree(arclab,sizeof(*arclab) * nlabs);
+       return(num);
+       }
+
+
+accum(str,vlist,f)             /* build string of indices in compnode  corr. to label f */
+char *str;  long f;  struct lablist *vlist;
+       {
+       int s,j;  struct lablist  *p;
+
+       s = 0;
+       j = 1;
+       for (p = vlist; p ; p = p->nxtlab)              /* search for occurrences of f */
+               {
+               if (p->labelt ==f)
+                       {
+                       if (s)
+                               {
+                               str[s] = ',';
+                               ++s;
+                               }
+                       sprintf(&str[s],"%d",j);
+                       while (str[s] != '\0') ++s;
+                       }
+               ++j;
+               }
+       return(s+1);
+       }
+
+
+distinct(vlist,count,dlist,size)               /* make dlist into list of distinct labels in vlist */
+struct lablist *vlist;  long dlist[];          /*count[] gets count of each label;  d distinct labels */
+int count[],size;
+       {int d,i;
+       d = 0;
+       for(i = 0; i < size; i++)  count[i] = 0;
+
+       for (;vlist && vlist->labelt != 0L; vlist = vlist ->nxtlab)
+               {
+               for (i = 0; ;i++)
+                       {
+                       if (i == d)  dlist[d++] = vlist->labelt;
+                       if (dlist[i] == vlist->labelt)
+                               {
+                               ++count[i];  break;
+                               }
+                       }
+               }
+       return(d);
+       }
+
+
diff --git a/usr/src/cmd/struct/1.tables.c b/usr/src/cmd/struct/1.tables.c
new file mode 100644 (file)
index 0000000..490456e
--- /dev/null
@@ -0,0 +1,220 @@
+#include <stdio.h>
+
+int match[146]
+                       = {
+                          0,   1,   2,   3,   4,   5,  19,  21,
+                         23,  25,  29,  32,  36,  38,  42,  44,
+                         46,  50,  52,  56,  59,  61,  65,  74,
+                         77,  81,  83,  85,  87,  89,  91,  93,
+                         95,  97,  99, 102, 105, 108, 114, 116,
+                        118, 120, 122, 124, 126, 129, 131, 134,
+                        136, 139, 142, 144, 147, 149, 151, 153,
+                        155, 157, 159, 161, 163, 165, 167, 169,
+                        171, 174, 176, 178, 180, 182, 184, 186,
+                        188, 190, 192, 194, 196, 198, 200, 202,
+                        204, 206, 208, 210, 212, 214, 216, 218,
+                        221, 223, 225, 227, 229, 231, 233, 235,
+                        237, 239, 241, 243, 245, 247, 249, 251,
+                        254, 256, 258, 260, 262, 264, 266, 268,
+                        270, 272, 274, 276, 278, 280, 283, 287,
+                        292, 298, 303, 307, 311, 316, 320, 324,
+                        327, 329, 331, 333, 335, 337, 339, 341,
+                        343, 345, 347, 349, 351, 353, 355, 356,
+                        357, 359
+                       };
+
+int symclass[358]
+                       = {
+                          1,   1,   1,   1,   1,   0,   0,   0,
+                          0,   0,   0,   0,   0,   0,   0,   0,
+                          0,   0,   1,   0,   1,   0,   1,   0,
+                          1,   2,   3,   0,   1,   2,   0,   1,
+                          4,   0,   0,   1,   0,   1,   2,   0,
+                          0,   1,   0,   1,   2,   1,   2,   0,
+                          0,   1,   0,   1,   4,   5,   0,   1,
+                          0,   0,   1,   0,   1,   0,   0,   0,
+                          1,   0,   0,   0,   0,   0,   0,   0,
+                          2,   1,   2,   0,   1,   2,   0,   0,
+                          1,   0,   1,   0,   1,   0,   1,   0,
+                          1,   0,   1,   0,   1,   0,   1,   0,
+                          1,   0,   1,   2,   0,   1,   2,   3,
+                          1,   4,   0,   1,   4,   0,   0,   0,
+                          5,   1,   0,   1,   0,   1,   0,   1,
+                          0,   1,   0,   1,   2,   1,   2,   0,
+                          1,   0,   1,   4,   0,   1,   0,   1,
+                          0,   0,   1,   0,   0,   1,   0,   1,
+                          0,   0,   1,   0,   1,   0,   1,   0,
+                          1,   0,   1,   0,   1,   0,   1,   0,
+                          1,   0,   1,   0,   1,   0,   1,   0,
+                          1,   0,   1,   0,   0,   1,   0,   1,
+                          0,   1,   0,   1,   0,   1,   0,   1,
+                          0,   1,   0,   1,   0,   1,   0,   1,
+                          0,   1,   0,   1,   0,   1,   0,   1,
+                          0,   1,   0,   1,   0,   1,   0,   1,
+                          0,   1,   0,   1,   0,   1,   0,   1,
+                          0,   1,   0,   0,   1,   0,   1,   0,
+                          1,   0,   1,   0,   1,   0,   1,   0,
+                          1,   0,   1,   0,   1,   0,   1,   0,
+                          1,   0,   1,   0,   1,   0,   1,   0,
+                          1,   0,   1,   0,   0,   1,   0,   1,
+                          0,   1,   0,   1,   0,   1,   0,   1,
+                          0,   1,   0,   1,   0,   1,   0,   1,
+                          0,   1,   0,   1,   0,   1,   0,   1,
+                          0,   2,   1,   2,   0,   0,   1,   0,
+                          0,   0,   0,   1,   2,   0,   0,   0,
+                          0,   1,   0,   0,   0,   0,   1,   0,
+                          0,   0,   1,   0,   0,   0,   1,   2,
+                          0,   0,   0,   1,   0,   0,   0,   1,
+                          0,   0,   0,   1,   0,   0,   1,   0,
+                          1,   0,   1,   0,   1,   0,   1,   0,
+                          1,   0,   1,   0,   1,   0,   1,   0,
+                          1,   0,   1,   0,   1,   0,   1,   0,
+                          1,   0,   1,   0,   0,   0
+                       };
+
+char symbol[358]
+                       = {
+                           '_',    '_',    '_',    '_',    '_',    'i',    'd',    'g',
+                           'a',    'r',    'w',    'c',    'l',    's',    'e',    'p',
+                           'f',    'b',    '_',    'o',    '_',    't',    '_',    'o',
+                           '_',    '_',    '_',    '(',    '_',    '_',    '\0',    '_',
+                           '_',    ',',    '\0',    '_',    '(',    '_',    '_',    ',',
+                           ')',    '_',    '\0',    '_',    '_',    '_',    '_',    ',',
+                           ')',    '_',    ',',    '_',    '_',    '_',    '\0',    '_',
+                           'f',    'n',    '_',    '(',    '_',    '(',    ')',    '\0',
+                           '_',    '=',    'g',    'a',    'r',    'p',    'w',    's',
+                           '_',    '_',    '_',    ',',    '_',    '_',    ',',    '\0',
+                           '_',    'o',    '_',    'n',    '_',    't',    '_',    'i',
+                           '_',    'n',    '_',    'u',    '_',    'e',    '_',    '\0',
+                           '_',    'o',    '_',    '_',    'u',    '_',    '_',    '_',
+                           '_',    '_',    '=',    '_',    '_',    '(',    ')',    ',',
+                           '_',    '_',    's',    '_',    's',    '_',    'i',    '_',
+                           'g',    '_',    'n',    '_',    '_',    '_',    '_',    't',
+                           '_',    'o',    '_',    '_',    '\0',    '_',    'e',    '_',
+                           'a',    't',    '_',    'l',    'd',    '_',    'f',    '_',
+                           'u',    'o',    '_',    'n',    '_',    'c',    '_',    't',
+                           '_',    'i',    '_',    'o',    '_',    'n',    '_',    't',
+                           '_',    'e',    '_',    'g',    '_',    'e',    '_',    'r',
+                           '_',    'o',    '_',    'm',    'n',    '_',    'p',    '_',
+                           'l',    '_',    'e',    '_',    'x',    '_',    'b',    '_',
+                           'l',    '_',    'e',    '_',    'p',    '_',    'r',    '_',
+                           'e',    '_',    'c',    '_',    'i',    '_',    's',    '_',
+                           'i',    '_',    'o',    '_',    'n',    '_',    'o',    '_',
+                           'g',    '_',    'i',    '_',    'c',    '_',    'a',    '_',
+                           'l',    '_',    't',    'u',    '_',    'o',    '_',    'p',
+                           '_',    'b',    '_',    'r',    '_',    'o',    '_',    't',
+                           '_',    'i',    '_',    'n',    '_',    'e',    '_',    'e',
+                           '_',    't',    '_',    'u',    '_',    'r',    '_',    'n',
+                           '_',    'n',    '_',    'd',    't',    '_',    '\0',    '_',
+                           'r',    '_',    'y',    '_',    'r',    '_',    'm',    '_',
+                           'a',    '_',    't',    '_',    '(',    '_',    'r',    '_',
+                           'i',    '_',    't',    '_',    'e',    '_',    '(',    '_',
+                           '(',    '_',    '_',    '_',    ',',    '\0',    '_',    '(',
+                           ')',    ',',    '\0',    '_',    '_',    'e',    ',',    '\0',
+                           ')',    '_',    'n',    'r',    ')',    '\0',    '_',    'd',
+                           ')',    '\0',    '_',    '=',    ')',    '\0',    '_',    '_',
+                           ',',    ')',    '\0',    '_',    'r',    ')',    '\0',    '_',
+                           '=',    ')',    '\0',    '_',    'r',    'u',    '_',    'i',
+                           '_',    'n',    '_',    't',    '_',    'n',    '_',    'c',
+                           '_',    'h',    '_',    'l',    '_',    'o',    '_',    'c',
+                           '_',    'k',    '_',    'd',    '_',    'a',    '_',    't',
+                           '_',    'a',    '_',    '_',    '_',    '_'
+                       };
+
+int action[358]
+                       = {
+                             1,      1,      1,      1,      1,      3,      3,      3,
+                             3,      3,      3,      3,      3,      3,      3,      3,
+                             3,      3,    111,      0,    111,      0,    111,     76,
+                           111,      1,      0,      0,    111,      1,    122,    111,
+                             0,     72,    123,    111,      0,    111,      1,      3,
+                             3,    111,    124,    111,      1,    111,      1,      3,
+                             3,    111,     76,    111,      0,      0,    125,    111,
+                             0,      0,    111,     45,    111,     30,     31,    111,
+                             0,    133,      0,      0,      0,      0,      0,      0,
+                             1,    111,      1,      3,    111,      1,      3,    141,
+                           111,      0,    111,      0,    111,      0,    111,      0,
+                           111,      0,    111,      0,    111,      0,    111,    180,
+                           111,      0,    111,      1,      0,    111,      1,     61,
+                           111,      0,      0,    111,      0,     62,     63,     64,
+                             0,    111,      0,    111,      0,    111,      0,    111,
+                             0,    111,      0,    111,      1,    111,      1,      3,
+                           111,     76,    111,      0,    150,    111,      0,    111,
+                             0,      0,    111,      0,     76,    111,      0,    111,
+                             0,      0,    111,      0,    111,      0,    111,      0,
+                           111,      0,    111,      0,    111,    200,    111,      0,
+                           111,      0,    111,      0,    111,      0,    111,      0,
+                           111,      0,    111,      0,      0,    111,      0,    111,
+                             0,    111,      0,    111,      0,    111,      0,    111,
+                             0,    111,      0,    111,      0,    111,      0,    111,
+                             0,    111,      0,    111,      0,    111,      0,    111,
+                             0,    111,      0,    111,      0,    111,      0,    111,
+                             0,    111,      0,    111,      0,    111,      0,    111,
+                             0,    111,      0,      0,    111,      0,    111,    350,
+                           111,      0,    111,      0,    111,      0,    111,      0,
+                           111,      0,    111,      0,    111,    200,    111,      0,
+                           111,      0,    111,      0,    111,      0,    111,    300,
+                           111,      0,    111,      0,      0,    111,    400,    111,
+                             0,    111,    700,    111,      0,    111,      0,    111,
+                             0,    111,      0,    111,    600,    111,      0,    111,
+                             0,    111,      0,    111,      0,    111,      0,    111,
+                             0,      1,    111,      1,    520,    520,    111,     62,
+                            77,     70,    111,      0,      1,      0,     75,    111,
+                           520,      0,      0,      0,    510,    111,      0,      0,
+                           510,    111,      0,     73,    510,    111,      0,      1,
+                             3,    510,    111,      0,      0,    510,    111,      0,
+                            74,    510,    111,      0,      0,      0,    111,      0,
+                           111,      0,    111,     76,    111,      0,    111,      0,
+                           111,     76,    111,      0,    111,      0,    111,      0,
+                           111,      0,    111,      0,    111,      0,    111,      0,
+                           111,    210,    111,      0,      0,      0
+                       };
+
+int newstate[358]
+                       = {
+                          1,   2,   3,   4,   5,  19,  33,   6,
+                         38,  47, 112,  63,  81,  87, 102, 127,
+                         51, 134, 142,   7, 142,   8,  -5,   9,
+                         -5,  10,  11,  15,  -5,  10, 142,  -5,
+                         11,  12, 142,  -5,  13,  -5,  13,  13,
+                         14,  -5, 142,  -5,  16, 142,  16,  15,
+                         17, 142,  18, 142,  18,  18, 142,  -5,
+                         20,  58, 142,  21,  -5,  21,  -5,  -5,
+                         21, 142,   6,  38,  47, 127, 112,  87,
+                         23, 142,  23,  24, 142,  24,  24, 142,
+                         -5,  26,  -5,  27,  -5,  28,  -5,  29,
+                         -5,  30,  -5,  31,  -5,  32,  -5, 142,
+                        142,  34,  -5,  35,  69,  -5,  35,  36,
+                         -5,  36,  37,  -5,  37,  37,  37,  37,
+                         37,  -5,  39,  -5,  40,  -5,  41,  -5,
+                         42,  -5,  43,  -5,  44, 142,  44,  45,
+                        142,  46,  -5,  46, 142,  -5,  48, 142,
+                         49,  99, 142,  50, 117, 142,  51, 142,
+                         52, 107, 142,  53, 142,  54, 142,  55,
+                        142,  56, 142,  57, 142, 142, 142,  59,
+                        142,  60, 142,  61, 142,  62, 142,  50,
+                        142,  64, 142,  65,  27, 142,  66, 142,
+                         67, 142,  68, 142,  50, 142,  70, 142,
+                         71, 142,  72, 142,  73, 142,  74, 142,
+                         75, 142,  76, 142,  77, 142,  78, 142,
+                         79, 142,  80, 142,  50, 142,  82, 142,
+                         83, 142,  84, 142,  85, 142,  86, 142,
+                         50, 142,  88,  90, 142,  89, 142, 142,
+                        142,  91, 142,  92, 142,  93, 142,  94,
+                        142,  95, 142,  96, 142, 142, 142,  98,
+                        142,  99, 142, 100, 142, 101, 142, 142,
+                        142, 103, 142, 104, 105, 142, 142, 142,
+                        106, 142, 142, 142, 108,  -5, 109,  -5,
+                        110,  -5, 111,  -5,  -5,  -5, 113,  -5,
+                        114,  -5, 115,  -5, 116,  -5, 119,  -5,
+                        119, 118,  -5, 118,  -5,  -5,  -5, 119,
+                        119,  -5,  -5, 119, 120, 121, 120,  -5,
+                         -5, 119, 122, 125,  -5,  -5, 119, 123,
+                         -5,  -5, 119, 124,  -5,  -5, 119, 124,
+                        120,  -5,  -5, 119, 126,  -5,  -5, 119,
+                        124,  -5,  -5, 119, 128, 131, 142, 129,
+                        142, 130, 142, 117, 142, 132, 142, 133,
+                        142, 117, 142, 135,  -5, 136,  -5, 137,
+                         -5, 138,  -5, 139,  -5, 140,  -5, 141,
+                         -5,  -5,  -5,  -5,  -5,  -5
+                       };
diff --git a/usr/src/cmd/struct/2.def.h b/usr/src/cmd/struct/2.def.h
new file mode 100644 (file)
index 0000000..7f6795e
--- /dev/null
@@ -0,0 +1,4 @@
+extern int accessnum;          /* number of nodes accessible from START */
+extern VERT *after;            /* node numbers associated with after numbers of depth first search */
+extern int *ntobef;            /* before numbers associated with nodes */
+extern int *ntoaft;            /* after numbers associated with nodes */
diff --git a/usr/src/cmd/struct/2.dfs.c b/usr/src/cmd/struct/2.dfs.c
new file mode 100644 (file)
index 0000000..36eeb1b
--- /dev/null
@@ -0,0 +1,173 @@
+#include <stdio.h>
+#
+/* depth-first search used to identify back edges, unreachable nodes;
+       each node v entered by back edge replaced by
+       LOOPVX ->ITERVX -> v,
+       so that back edges entering v now enter the ITERVX,
+       and other edges entering v now enter the LOOPVX.
+       Nodes are numbered according to depth-first search:
+               before numbering- ntobef[v] = i => node numbered v is i'th
+                       node in order of first visit during the search;
+               after numbering- ntoaft[v] = i => node numbered v is i'th
+                       node visited in order of last visit during the search.
+                       Also, in this case after[i] = v.
+*/
+
+#include "def.h"
+#include "2.def.h"
+
+#define MAXINS 3       /* spacing needed between numbers generated during depth first search */
+
+int *status;
+int befcount, aftcount;
+/* following defines used to mark back edges and nodes entered by back edges */
+#define UNPROCESSED    0
+#define STACKED        1
+#define FINISHED       2
+#define MARK(v)        {REACH(v) = 1; }        /* mark node v */
+#define UNMARK(v)      {REACH(v) = 0; }
+#define MARKED(v)      (REACH(v))
+#define MKEDGE(e)      {if (e >= -1) e = -(e+3); }     /* mark edge e */
+#define UNMKEDGE(e)    {if (e < -1) e = -(e+3); }
+#define BACKEDGE(e)    (e < -1)
+
+
+dfs(v)         /* depth first search */
+VERT v;
+       {
+       int i; VERT w;
+       accessnum = 0;
+       status = challoc(sizeof(*status) * nodenum);
+       for (w = 0; w < nodenum; ++w)
+               {
+               status[w] = UNPROCESSED;
+               UNMARK(w);
+               }
+       search(v);
+       chreach();
+       chfree(status, sizeof(*status) * nodenum);
+       addloop();
+       after = challoc(sizeof(*after) * accessnum);
+       for (i = 0; i < accessnum; ++i)
+               after[i] = UNDEFINED;
+       ntoaft = challoc(sizeof(*ntoaft) * nodenum);
+       ntobef = challoc(sizeof(*ntobef) * nodenum);
+       for (w = 0; w < nodenum; ++w)
+               ntobef[w] = ntoaft[w] = UNDEFINED;
+       befcount = 0;
+       aftcount = 0;
+       repsearch(v);
+       }
+
+
+search(v)
+       /* using depth first search, mark back edges using MKEDGE, and nodes entered by back
+       edges using MARK */
+VERT v;
+       {
+       VERT adj; int i;
+       status[v] = STACKED;
+       for(i = 0; i < ARCNUM(v); ++i)
+               {
+               adj = ARC(v,i);
+               if (!DEFINED(adj)) continue;
+               else if (status[adj] == UNPROCESSED)
+                       search(adj);
+               else if (status[adj] == STACKED)
+                       {
+                       MARK(adj);              /* mark adj as entered by back edge */
+                       MKEDGE(ARC(v,i));       /* mark edge ARC(v,i) as being back edge */
+                       }
+               }
+       status[v] = FINISHED;
+       ++accessnum;
+       }
+
+chreach()              /* look for unreachable nodes */
+       {
+       VERT v;
+       LOGICAL unreach;
+       unreach = FALSE;
+       for (v = 0; v < nodenum; ++v)
+               if (status[v] == UNPROCESSED && NTYPE(v) != FMTVX
+                       && NTYPE(v) != STOPVX && NTYPE(v) != RETVX)
+                       {
+                       unreach = TRUE;
+                       if (debug)
+                               fprintf(stderr,"node %d unreachable\n",v);
+                       }
+       if (unreach)
+               error(": unreachable statements - ","will be ignored","");
+       }
+
+
+addloop()      /* add LOOPVX, ITERVX at nodes entered by back edges, and adjust edges */
+       {
+       VERT v, adj;
+       int j, oldnum;
+       for (v = 0, oldnum = nodenum; v < oldnum; ++v)  /* insloop increases nodenum */
+               if (MARKED(v))
+                       {
+                       UNMARK(v);      /* remove mark indicating v entered by back edge */
+                       if (NTYPE(v) != ITERVX)                 /* DO loops already have ITERVX */
+                                insloop(v);  /* add LOOPVX, ITERVX since v entered by back edge*/
+                       }
+       /* arcs which used to enter v now enter LOOPVX; must make back edges enter ITERVX */
+       for (v = 0; v < nodenum; ++v)
+               for (j = 0; j < ARCNUM(v); ++j)
+                       {
+                       if (BACKEDGE(ARC(v,j)))
+                               {
+                               UNMKEDGE(ARC(v,j));             /* return edge to normal value */
+                               adj = ARC(v,j);
+                               if (NTYPE(adj) == ITERVX) continue;
+                               ASSERT(NTYPE(adj) == LOOPVX,addloop);
+                               ARC(v,j) = ARC(adj,0);  /* change arc to point to ITERVX */
+                               ASSERT(NTYPE(ARC(v,j)) == ITERVX,addloop);
+                               }
+                       }
+       }
+
+insloop(v)             /* insert LOOPVX, ITERVX at node number v */
+VERT v;
+       {
+       VERT loo, iter;
+       loo = create(LOOPVX, 1);
+       iter = create(ITERVX,1);
+       accessnum += 2;
+       /* want LOOPVX to take on node number v, so that arcs other than back arcs
+               entering v will enter the LOOPVX automatically */
+       exchange(&graph[v], &graph[loo]);
+       exchange(&v, &loo);
+       ARC(loo,0) = iter;
+       ARC(iter,0) = v;
+       FATH(iter) = UNDEFINED; /* will be defined later along with FATH for DOVX */
+       }
+
+exchange(p1,p2)                /* exchange values of p1,p2 */
+int *p1,*p2;
+       {
+       int temp;
+       temp = *p1;
+       *p1 = *p2;
+       *p2 = temp;
+       }
+
+
+repsearch(v)           /* repeat df search in order to fill in after, ntoaft, ntobef tables */
+VERT v;
+       {
+       VERT adj; int i,temp;
+       ntobef[v] = befcount;
+       ++befcount;
+       for(i = 0; i < ARCNUM(v); ++i)
+               {
+               adj = ARC(v,i);
+               if (DEFINED(adj) && ntobef[adj] == UNDEFINED)
+                       repsearch(adj);
+               }
+       ++aftcount;
+       temp = accessnum - aftcount;
+       after[temp] = v;
+       ntoaft[v] = temp;
+       }
diff --git a/usr/src/cmd/struct/2.dom.c b/usr/src/cmd/struct/2.dom.c
new file mode 100644 (file)
index 0000000..e0a9f85
--- /dev/null
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#
+/*
+set dom[v] to immediate dominator of v, based on arcs as stored in inarcs
+(i.e. pretending the graph is reducible if it isn't).
+Algorithm is from Hecht and Ullman, Analysis of a simple algorithm for global
+flow analysis problems, except bit vector operations replaced by search
+through DOM to save quadratic blowup in space 
+*/
+#include "def.h"
+#include "2.def.h"
+
+
+getdom(inarc,dom)
+struct list **inarc;
+VERT *dom;
+       {
+       VERT v;
+       int i;
+       struct list *ls;
+       for (v = 0; v < nodenum; ++v)
+               dom[v] = UNDEFINED;
+       for (i = 1; i < accessnum; ++i)
+               {
+               v = after[i];
+               for (ls = inarc[v]; ls; ls = ls->nxtlist)
+                       {
+                       ASSERT(ntoaft[ls->elt] < i,getdom);
+                       dom[v] = comdom(dom[v],ls->elt,dom);
+                       }
+
+               }
+       }
+
+
+comdom(u,v,dom)                        /* find closest common dominator of u,v */
+VERT u,v, *dom;
+       {
+       if (u == UNDEFINED) return(v);
+       if (v == UNDEFINED) return(u);
+       while(u != v)
+               {
+               ASSERT(u != UNDEFINED && v != UNDEFINED, comdom);
+               if (ntoaft[u] < ntoaft[v])      
+                       v = dom[v];
+               else
+                       u = dom[u];
+               }
+       return(u);
+       }
diff --git a/usr/src/cmd/struct/2.head.c b/usr/src/cmd/struct/2.head.c
new file mode 100644 (file)
index 0000000..f538bce
--- /dev/null
@@ -0,0 +1,107 @@
+#include <stdio.h>
+#
+/*
+set head[v] to ITERVX heading smallest loop containing v, for each v
+*/
+#include "def.h"
+#include "2.def.h"
+
+/* define ANC(v,w) true if v == w or v is ancestor of w */
+#define ANC(v,w)       (ntobef[v] <= ntobef[w] && ntoaft[v] <= ntoaft[w])      /* reflexive ancestor */
+
+
+gethead(head)
+VERT *head;
+       {
+       VERT v, w, adj; int i, j;
+       /* search nodes in reverse of after numbering so that all paths from
+               a node to an ancestor are searched before the node */
+       /* at any point, the current value of head allows chains of nodes
+               to be reached from any node v by taking head[v], head[head[v]], etc.
+               until an UNDEFINED value is reached.  Upon searching each arc, 
+               the appropriate chains must be merged to avoid losing information.
+               For example, from one path out of a node v it may be known that
+                v is in a loop headed by z, while from another
+               it may be known that v is in a loop headed by w.
+               Thus, head[v] must be set to whichever of z,w is the closer ancestor,
+               and the fact that this node is in a loop headed by the other must be
+               recorded in head.       */
+       for (v = 0; v < nodenum; ++v)
+               head[v] = UNDEFINED;
+       for (i = accessnum -1; i >= 0; --i)
+               {
+               v = after[i];
+               for (j = 0; j < ARCNUM(v); ++j)
+                       {
+                       adj = ARC(v,j);
+                       if (!DEFINED(adj)) continue;
+                       if (ntoaft[adj] < i)            /* back edge */
+                               merge(v,adj,head);
+                       else if (ANC(v,adj))            /* not back edge or cross edge */
+                               {
+                               /* need to do only tree edges - must not do edge (v,adj)
+                                       when head[adj] is not ANC of v */
+                               if (DEFINED(head[adj]) && ANC(head[adj],v))
+                                       merge(v,head[adj],head);
+                               }
+                       else                            /* cross edge */
+                               {
+                               w = lowanc(adj,v,head);
+                               if (DEFINED(w))
+                                       merge(w,v,head);
+                               }
+                       }
+               if (NTYPE(v) == LOOPVX || NTYPE(v) == DOVX)
+                       head[ARC(v,0)] = head[v];       /* head of ITERVX must be different ITERVX */
+               }
+       }
+
+
+lowanc(y,z,head)               /* find the first node in chain of y which is anc of z, if it exists */
+VERT y,z, *head;
+       {
+       while (y != -1 && !ANC(y,z))
+               y = head[y];
+       return(y);
+       }
+
+
+merge(w,y,head)                /* merge chains of w and y according to ANC relation */
+VERT w,y, *head;
+       {
+       VERT t, min;
+       if (w == y) return;
+
+       if (ANC(w,y))           /* set t to min of w,y */
+               {
+               t = y;
+                y = head[y];
+               }
+       else
+               {
+               t = w;
+                w = head[w];
+               }
+
+       while (w != -1 && y != -1)              /* construct chain at t by adding min of remaining elts */
+               {
+               if (ANC(w,y))
+                       {
+                       min = y;
+                       y = head[y];
+                       }
+               else
+                       {
+                       min = w;
+                       w = head[w];
+                       }
+               if (t != min)
+                       {
+                       head[t] = min;
+                       t = min;
+                       }
+               }
+       if (w == -1)  min = y;  else  min = w;
+       if (t != min)  head[t] = min;
+
+       }
diff --git a/usr/src/cmd/struct/2.inarc.c b/usr/src/cmd/struct/2.inarc.c
new file mode 100644 (file)
index 0000000..dc9f060
--- /dev/null
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#
+/* find forward in-arcs for each node, pretending that arcs which jump into a loop 
+       jump to the head of the largest such loop instead, based on the
+       depth first search tree */
+#include "def.h"
+#include "2.def.h"
+
+getinarc(inarc,head)           /* construct array "inarc" containing in arcs for each node */
+struct list **inarc;
+VERT *head;
+       {
+       VERT v,adj,x;
+       int i, j;
+
+       for (v=0; v < nodenum; ++v) inarc[v] = 0;
+
+       /* fill in inarc nodes */
+
+       for (i = 0; i < accessnum; ++i)
+               {
+               v = after[i];
+               for (j = 0; j < ARCNUM(v); ++j)
+                       {
+                       adj = ARC(v,j);
+                       if (!DEFINED(adj))
+                               continue;
+                       if (ntoaft[adj] > ntoaft[v])            /* not a back edge */
+                               /* if edge jumps into loop, pretend jumps to head of
+                                       largest loop jumped into */
+                               {
+                               x = maxentry(v,adj,head);
+                               if (!DEFINED(x)) x = adj;
+                               else x = FATH(x);
+
+                               inarc[x] = consls(v,inarc[x]);  /* insert v in list inarc[x] */
+                               }
+                       }
+               }
+       }
+
+
+
+maxentry(x,y,head)     /* return z if z is ITERVX of largest loop containing y but not x, UNDEFINED otherwise */
+VERT x,y, *head;
+       {
+       if (head[y] == UNDEFINED)  return(UNDEFINED);
+       if (loomem(x,head[y], head)) return (UNDEFINED);
+       y = head[y];
+       while (head[y] != UNDEFINED)
+               {
+               if (loomem(x,head[y],head))  return(y);
+               y = head[y];
+               }
+       return(y);
+       }
+
+
+
+loomem(x,y,head)                       /* return TRUE if x is in loop headed by y, FALSE otherwise */
+VERT x,y, *head;
+       {
+       VERT w;
+       if (!DEFINED(y)) return(TRUE);
+       ASSERT(NTYPE(y) == ITERVX, loomem);
+       for (w = (NTYPE(x) == ITERVX) ? x : head[x]; DEFINED(w); w = head[w])
+               if (w == y)  return (TRUE);
+       return(FALSE);
+       }
diff --git a/usr/src/cmd/struct/2.main.c b/usr/src/cmd/struct/2.main.c
new file mode 100644 (file)
index 0000000..4e0bf65
--- /dev/null
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include "def.h"
+#include "2.def.h"
+
+VERT *after;
+int *ntobef, *ntoaft;
+build()
+       {
+       VERT v, *dom, *head;
+       int type;
+       struct list **inarc;
+       dfs(START);
+       if (routerr) return;
+       for (v = 0; v < nodenum; ++v)
+               {
+               type = NTYPE(v);
+               if (type == LOOPVX || type == DOVX)
+                       FATH(ARC(v,0)) = v;
+               }
+
+       head = challoc(sizeof(*head) * nodenum);
+       if (progress) fprintf(stderr,"  gethead:\n");
+       gethead(head);  /* sets head[v] to ITERVX heading smallest loop containing v or UNDEFINED */
+
+       if (routerr) return;
+       inarc = challoc(nodenum * sizeof(*inarc));
+       if (progress) fprintf(stderr,"  getinarc:\n");
+       getinarc(inarc,head);           /* sets inarc[v] to list of forward arcs entering v */
+
+       dom = challoc(nodenum * sizeof(*dom));
+       if (progress) fprintf(stderr,"  getdom:\n");
+       getdom(inarc,dom);      /* sets dom[v] to immediate dominator of v or UNDEFINED */
+       if (routerr) return;
+       if (progress) fprintf(stderr,"  gettree:\n");
+       gettree(inarc, dom, head);
+       if (routerr) return;
+
+       chfree(head, nodenum * sizeof(*head)); head = 0;
+       chfree(dom,nodenum * sizeof(*dom)); dom = 0;
+       for (v = 0; v < nodenum; ++v)
+               {
+               freelst(inarc[v]);
+               inarc[v] = 0;
+               }
+       chfree(inarc,sizeof(*inarc) * nodenum); inarc = 0;
+       chfree(ntoaft,sizeof(*ntoaft) * nodenum); ntoaft = 0;
+       chfree(ntobef,sizeof(*ntobef) * nodenum); ntobef = 0;
+       chfree(after, sizeof(*after) * accessnum); after = 0;
+       }
diff --git a/usr/src/cmd/struct/2.test.c b/usr/src/cmd/struct/2.test.c
new file mode 100644 (file)
index 0000000..7ce2bf4
--- /dev/null
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#
+/* for testing only */
+#include "def.h"
+#include "2.def.h"
+
+testaft()
+       {
+       int i;
+       for (i = 0; i < nodenum; ++i)
+               fprintf(stderr,"ntoaft[%d] = %d, ntobef[%d] = %d\n",i,ntoaft[i],i,ntobef[i]);
+       fprintf(stderr,"\n");
+       for (i = 0; i < accessnum; ++i)
+               fprintf(stderr,"after[%d] = %d\n",i,after[i]);
+       }
+
+testhead(head)
+VERT *head;
+       {
+       VERT v;
+       for (v = 0; v < nodenum; ++v)
+               fprintf(stderr,"head[%d] = %d\n",v,head[v]);
+       }
+
+testdom(dom)
+VERT *dom;
+       {
+       VERT v;
+       for (v = 0; v < nodenum; ++v)
+               fprintf(stderr,"dom[%d] = %d\n",v,dom[v]);
+       }
+
+
+testtree()
+       {
+       VERT v;
+       int i;
+       for (v = 0; v < nodenum; ++v)
+               {
+               fprintf(stderr,"%d: RSIB %d, ",v,RSIB(v));
+               for (i = 0; i < CHILDNUM(v); ++i)
+                       fprintf(stderr," %d",LCHILD(v,i));
+               fprintf(stderr,"\n");
+               }
+       }
diff --git a/usr/src/cmd/struct/2.tree.c b/usr/src/cmd/struct/2.tree.c
new file mode 100644 (file)
index 0000000..f8a33e3
--- /dev/null
@@ -0,0 +1,131 @@
+#include <stdio.h>
+#
+/* use inarc, dom, and head to build tree representing structure of program.
+       Each node v has CHILDNUM(v) children denoted by
+       LCHILD(v,0), LCHILD(v,1),...
+       RSIB((v) is right sibling of v or UNDEFINED;
+       RSIB(v) represents code following v at the same level of nesting,
+       while LCHILD(v,i) represents code nested within v
+*/
+#include "def.h"
+#include "2.def.h"
+
+gettree(inarc,dom,head)                /* build tree */
+struct list **inarc;
+VERT *dom, *head;
+       {
+       VERT v,u,from;
+       int i;
+       for ( v = 0; v < nodenum; ++v)
+               {
+               RSIB(v) = UNDEFINED;
+               for (i = 0; i < CHILDNUM(v); ++i)
+                       LCHILD(v,i) = UNDEFINED;
+               }
+       for (i = accessnum-1; i > 0; --i)
+               {
+               v = after[i];
+               from = oneelt(inarc[v]);        /* the unique elt of inarc[v] or UNDEFINED */
+               if (DEFINED(from))
+                       if (NTYPE(from) == IFVX && (head[v] == head[from] || asoc(v,exitsize) != -1) )
+                               /* place in clause of IFVX if in smallest loop containing it
+                               or if size of code for v is <= exitsize */
+                               if (ARC(from,THEN) == v)
+                                       {
+                                       LCHILD(from,THEN) = v;
+                                       continue;
+                                       }
+                               else
+                                       {
+                                       ASSERT(ARC(from,ELSE) == v,gettree);
+                                       LCHILD(from,ELSE) = v;
+                                       continue;
+                                       }
+                       else if (NTYPE(v) == ITERVX || NTYPE(from) == ITERVX )
+                               /* LOOPVX -> ITERVX ->vert always in same loop*/
+                               {
+                               LCHILD(from,0) = v;
+                               continue;
+                               }
+                       else if (NTYPE(from) == SWCHVX)
+                               {
+                               ASSERT(0 < ARCNUM(v),gettree);
+                               if (ARC(from,0) == v)
+                                       LCHILD(from,0) = v;
+                               else
+                                       {
+                                       int j;
+                                       for (j = 1; j < ARCNUM(from); ++j)
+                                               if (ARC(from,j) == v)
+                                                       {insib(ARC(from,j-1),v);
+                                                       break;
+                                                       }
+                                       }
+                               continue;
+                               }
+                       else if (NTYPE(from) == ICASVX && (head[v] == head[from] || asoc(v,exitsize) != -1))
+                               {
+                               LCHILD(from,0) = v;
+                               continue;
+                               }
+                       else if (NTYPE(from) == DUMVX && ARC(from,0) == v)
+                               {
+                               LCHILD(from,0) = v;
+                               continue;
+                               }
+               if (loomem(v,head[dom[v]],head))
+                               /* v is in smallest loop containing dom[v] */
+                       insib(dom[v],v);
+               else
+                       {
+                               /* make v follow LOOPVX heading largest loop
+                                       containing DOM[v] but not v */
+                       ASSERT(DEFINED(head[dom[v]]),gettree);
+                       for (u = head[dom[v]]; head[u] != head[v]; u = head[u])
+                               ASSERT(DEFINED(head[u]),gettree);
+                       ASSERT(NTYPE(u) == ITERVX,gettree);
+                       insib(FATH(u),v);
+                       }
+               }
+       }
+
+
+
+
+insib(w,v)             /* make RSIB(w) = v, and make RSIB(rightmost sib of v) = old RSIB(w) */
+VERT w,v;
+       {
+       VERT u, temp;
+       temp = RSIB(w);
+       RSIB(w) = v;
+       for (u = v; DEFINED(RSIB(u)); u = RSIB(u))
+               ;
+       RSIB(u) = temp;
+       }
+
+
+asoc(v,n)              /* return # of nodes associated with v if <= n, -1 otherwise */
+VERT v;
+int n;
+       {
+       int count,i,temp;
+       VERT w;
+       count = (NTYPE(v) == STLNVX) ? CODELINES(v) : 1;
+       for (i = 0; i < CHILDNUM(v); ++i)
+               {
+               w = LCHILD(v,i);
+               if (!DEFINED(w)) continue;
+               temp = asoc(w,n-count);
+               if (temp == -1) return(-1);
+               count += temp;
+               if (count > n) return(-1);
+               }
+       if (DEFINED(RSIB(v)))
+               {
+               temp = asoc(RSIB(v),n-count);
+               if (temp == -1) return(-1);
+               count += temp;
+               }
+       if (count > n) return(-1);
+       else return(count);
+       }
diff --git a/usr/src/cmd/struct/3.branch.c b/usr/src/cmd/struct/3.branch.c
new file mode 100644 (file)
index 0000000..58768e4
--- /dev/null
@@ -0,0 +1,88 @@
+#include <stdio.h>
+#include "def.h"
+#include "3.def.h"
+
+
+getbranch(head)
+VERT *head;
+       {
+       VERT v;
+       for (v = 0; v < nodenum; ++v)
+               LABEL(v) = FALSE;
+       for (v = START; DEFINED(v); v = RSIB(v))
+               chkbranch(v,head);
+       addlab(START);
+       }
+
+
+
+chkbranch(v,head)
+VERT v,*head;
+       {
+       VERT  w;
+       int i;
+       switch(NTYPE(v))
+               {
+               case GOVX:
+                               for (i = 1, w = head[v]; DEFINED(w); w = head[w], ++i)
+                                       {
+                                       if (i > 1 && !levnxt && !levbrk) break;
+                                       if (ARC(v,0) == BRK(w) && (levbrk || i == 1))
+                                               {
+                                               NTYPE(v) = BRKVX;
+                                               LEVEL(v) = i;
+                                               break;
+                                               }
+                                       else if (ARC(v,0) == NXT(w) && (levnxt || i == 1))
+                                               {
+                                               NTYPE(v) = NXTVX;
+                                               LEVEL(v) = i;
+                                               break;
+                                               }
+                                       }
+                       if (NTYPE(v) == GOVX)
+                               {
+                               if (ARC(v,0) == stopvert)
+                                       NTYPE(v) = STOPVX;
+                               else if (ARC(v,0) == retvert)
+                                       NTYPE(v) = RETVX;
+                               else LABEL(ARC(v,0)) = TRUE;
+                               }
+                       break;
+               case COMPVX:
+               case ASGOVX:
+                       for (i = 0; i < ARCNUM(v); ++i)
+                               LABEL(ARC(v,i)) = TRUE;
+                       break;
+               case IOVX:
+                               if (DEFINED(ARC(v,ENDEQ)))
+                                       LABEL(ARC(v,ENDEQ)) = TRUE;
+                               if (DEFINED(ARC(v,ERREQ)))
+                                       LABEL(ARC(v,ERREQ)) = TRUE;
+                               if (DEFINED(FMTREF(v)))
+                                       LABEL(FMTREF(v)) = TRUE;
+                               break;
+               }
+       for (i = 0; i < CHILDNUM(v); ++i)
+               for (w = LCHILD(v,i); DEFINED(w); w = RSIB(w))
+                       chkbranch(w,head);
+       }
+
+
+addlab(v)              /* add labels */
+VERT v;
+       {
+       int recvar;
+       if (NTYPE(v) != ITERVX && LABEL(v) )
+               LABEL(v) = nxtlab();
+       RECURSE(addlab,v,recvar);
+       if (NTYPE(v) == ITERVX && LABEL(NXT(v)))
+               LABEL(NXT(v)) = nxtlab();
+       }
+
+
+nxtlab()
+       {
+       static count;
+       return(labinit + (count++) * labinc);
+       }
diff --git a/usr/src/cmd/struct/3.def.h b/usr/src/cmd/struct/3.def.h
new file mode 100644 (file)
index 0000000..6722a53
--- /dev/null
@@ -0,0 +1,6 @@
+#define RECURSE(p,v,r) { for (r = 0; r < CHILDNUM(v); ++r) if (DEFINED(LCHILD(v,r))) p(LCHILD(v,r)); if (DEFINED(RSIB(v))) p(RSIB(v)); }
+
+#define IFTHEN(v)              ( NTYPE(v) == IFVX && !DEFINED(LCHILD(v,ELSE)))
+
+#define BRK(v) FATH(v)         /* lexical successor of v, for ITERVX only */
+#define LABEL(v)       REACH(v)
diff --git a/usr/src/cmd/struct/3.flow.c b/usr/src/cmd/struct/3.flow.c
new file mode 100644 (file)
index 0000000..7f3fad4
--- /dev/null
@@ -0,0 +1,89 @@
+#include <stdio.h>
+#
+/*
+correct the flow of control in the new program - use GOTO's which may
+be changed later to NEXT, BREAK, etc.
+*/
+#include "def.h"
+#include "3.def.h"
+
+#define BRANCHTYPE(v)  (NTYPE(v) == GOVX )
+#define HASLEX(t)      (t != GOVX && t != COMPVX && t != ASGOVX  && t != ITERVX )
+                       /* for these, control never flows directly to following statement */
+
+
+getflow()
+       {
+       fixflow(START,UNDEFINED);
+       }
+
+
+fixflow(v,autolex)
+VERT v;
+VERT autolex;          /* lexical successor of v */
+       {
+       VERT lex,chlex,z,x,w;
+       int i;
+       lex = lexval(v,autolex);
+       if (HASLEX(NTYPE(v)) && NTYPE(v) != ICASVX)
+               if (DEFINED(REACH(v)) && REACH(v) != lex)
+                       insib(v,makebr(REACH(v)));
+               else if (NTYPE(v) == DOVX && ARC(v,1) != lex)
+                       insib(v,makebr(ARC(v,1)));
+       if (NTYPE(v) == ITERVX)
+               {
+               BRK(v) = autolex;
+               chlex = v;
+               }
+       else
+               chlex = lexval(v,autolex);
+
+       for (i = 0; i < CHILDNUM(v); ++i)
+               {
+               w = LCHILD(v,i);
+               if (DEFINED(w))
+                       fixflow(w,chlex);
+               else
+                       {
+                       ASSERT(i < ARCNUM(v),fixflow);
+                       z = ARC(v,i);
+                       ASSERT(DEFINED(z), fixflow);
+                       if (z != chlex)
+                               {
+                               x = makebr(z);
+                               LCHILD(v,i) = x;
+                               RSIB(x) = UNDEFINED;
+                               }
+                       }
+               }
+       if (DEFINED(RSIB(v)))
+               fixflow(RSIB(v),autolex);
+       }
+
+
+lexval(v,lastlex)
+VERT v,lastlex;
+       {
+       VERT sib;
+       if (!HASLEX(NTYPE(v))) return(UNDEFINED);
+       sib = RSIB(v);
+       if (NTYPE(v) == ICASVX || NTYPE(v) == ACASVX)
+               return(lastlex);
+       else if (!DEFINED(sib))
+               return(lastlex);
+       else if (BRANCHTYPE(sib))
+               return(ARC(sib,0));
+       else return(sib);
+       }
+
+
+makebr(w)              /* make branching node leading to w */
+VERT w;
+       {
+       VERT new;
+       new = create(GOVX,1);
+       ARC(new,0) = w;
+       RSIB(new) = UNDEFINED;
+       REACH(new) = UNDEFINED;
+       return(new);
+       }
diff --git a/usr/src/cmd/struct/3.loop.c b/usr/src/cmd/struct/3.loop.c
new file mode 100644 (file)
index 0000000..6d5ef5c
--- /dev/null
@@ -0,0 +1,152 @@
+#include <stdio.h>
+#include "def.h"
+#include "3.def.h"
+
+#define ARCCOUNT(v)    REACH(v)
+
+
+fixhd(v,hd,head)
+VERT v,hd,*head;
+       {
+       VERT w,newhd;
+       int i;
+       head[v] = hd;
+       newhd = (NTYPE(v) == ITERVX) ? v : hd;
+       for (i = 0; i < CHILDNUM(v); ++i)
+               for (w = LCHILD(v,i); DEFINED(w); w = RSIB(w))
+                       fixhd(w,newhd,head);
+       }
+
+getloop()
+       {
+       cntarcs();
+       fixloop(START);
+       }
+
+
+cntarcs()      /* count arcs entering each node */
+       {
+       VERT w,v;
+       int i;
+       for (v = 0; v < nodenum; ++v)
+               ARCCOUNT(v) = 0;
+       for (v = 0; v < nodenum; ++v)
+               for (i = 0; i < ARCNUM(v); ++i)
+                       {
+                       w = ARC(v,i);
+                       if (!DEFINED(w)) continue;
+                       ++ARCCOUNT(w);
+                       }
+       }
+
+
+fixloop(v)             /* find WHILE loops  */
+VERT v;
+       {
+       int recvar;
+       if (NTYPE(v) == LOOPVX)
+               {
+               ASSERT(DEFINED(ARC(v,0)),fixloop);
+               NXT(ARC(v,0)) = ARC(v,0);
+               if (!getwh(v))
+                       getun(v);
+               }
+       else if (NTYPE(v) == IFVX && arbcase)
+               getswitch(v);
+       else if (NTYPE(v)==DOVX)
+               {
+               ASSERT(DEFINED(ARC(v,0)),fixloop);
+               NXT(ARC(v,0))=ARC(v,0);
+               }
+       RECURSE(fixloop,v,recvar);
+       }
+
+
+getwh(v)
+VERT v;
+       {
+       VERT vchild, vgrand,vgreat;
+       ASSERT(NTYPE(v) == LOOPVX,getwh);
+       vchild = LCHILD(v,0);
+       ASSERT(DEFINED(vchild),getwh);
+       ASSERT(NTYPE(vchild) == ITERVX,getwh);
+       vgrand = LCHILD(vchild,0);
+       if (!DEFINED(vgrand) || !IFTHEN(vgrand) )
+               return(FALSE);
+       vgreat = LCHILD(vgrand,THEN);
+       if (DEFINED(vgreat) && NTYPE(vgreat) == GOVX && ARC(vgreat,0) == BRK(vchild))
+               {
+               /* turn into WHILE */
+               NTYPE(v) = WHIVX;
+               NEG(vgrand) = !NEG(vgrand);
+               LPRED(vchild) = vgrand; 
+               LCHILD(vchild,0) = RSIB(vgrand);
+               RSIB(vgrand) = UNDEFINED;
+               return(TRUE);
+               }
+       return(FALSE);
+       }
+
+
+
+getun(v)               /* change loop to REPEAT UNTIL if possible */
+VERT v;
+       {
+       VERT vchild, vgrand,  vgreat, before, ch;
+       ASSERT(NTYPE(v) == LOOPVX,getun);
+       vchild = LCHILD(v,0);
+       ASSERT(DEFINED(vchild), getun);
+       if (ARCCOUNT(vchild) > 2) 
+               return(FALSE);          /* loop can be iterated without passing through predicate of UNTIL */
+       vgrand = ARC(vchild,0);
+       if (!DEFINED(vgrand))
+               return(FALSE);
+       for (ch = vgrand,before = UNDEFINED; DEFINED(RSIB(ch)); ch = RSIB(ch))
+               before = ch;
+       if (!IFTHEN(ch))
+               return(FALSE);
+       vgreat = LCHILD(ch,THEN);
+       if (DEFINED(vgreat) && NTYPE(vgreat) == GOVX && ARC(vgreat,0) == BRK(vchild))
+               {
+               /* create  UNTIL node */
+               NTYPE(v) = UNTVX;
+               NXT(vchild) = ch;
+               LPRED(vchild)=ch;
+               RSIB(before) = UNDEFINED;
+               return(TRUE);
+               }
+       return(FALSE);
+       }
+
+
+#define FORMCASE(w)    (DEFINED(w) && !DEFINED(RSIB(w)) && NTYPE(w) == IFVX && ARCCOUNT(w) == 1)
+
+getswitch(v)
+VERT v;
+       {
+       VERT ch, grand, temp;
+       /* must be of form if ... else if ... else if ... */
+       if (NTYPE(v) != IFVX) return(FALSE);
+       ch = LCHILD(v,ELSE);
+       if (!FORMCASE(ch)) return(FALSE);
+       grand = LCHILD(ch,ELSE);
+       if (!FORMCASE(grand)) return(FALSE);
+
+       temp = create(SWCHVX,0);
+       exchange(&graph[temp],&graph[v]);       /* want arcs to enter switch, not first case*/
+       BEGCOM(v) = UNDEFINED;
+       RSIB(v) = RSIB(temp);           /* statements which followed IFVX should follow switch */
+       EXP(v) = UNDEFINED;
+       LCHILD(v,0) = temp;
+       NTYPE(temp) = ACASVX;
+       for (ch = LCHILD(temp,ELSE); FORMCASE(ch); )
+               {
+               LCHILD(temp,ELSE) = UNDEFINED;
+               RSIB(temp) = ch;
+               NTYPE(ch) = ACASVX;
+               temp = ch;
+               ch = LCHILD(temp,ELSE);
+               }
+       ASSERT(!DEFINED(RSIB(temp)),getswitch);
+       return(TRUE);
+       }
diff --git a/usr/src/cmd/struct/3.main.c b/usr/src/cmd/struct/3.main.c
new file mode 100644 (file)
index 0000000..fb4dd59
--- /dev/null
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include "def.h"
+
+structure()
+       {
+       VERT v, *head;
+
+       if (progress)
+               fprintf(stderr,"        getreach:\n");
+       getreach();
+       if (routerr) return;
+       if (progress)
+               fprintf(stderr,"        getflow:\n");
+       getflow();
+       if (progress)
+               fprintf(stderr,"        getthen:\n");
+       getthen(START);
+       head = challoc(nodenum * sizeof(*head));
+       for (v = 0; v < nodenum; ++v)
+               head[v] = UNDEFINED;
+       for (v = START; DEFINED(v); v = RSIB(v))
+               fixhd(v,UNDEFINED,head);
+                       /* fixhd must be called before getloop so that
+                               it gets applied to IFVX which becomes NXT(w) for UNTVX w */
+       if (progress)
+               fprintf(stderr,"        getloop:\n");
+       getloop();
+       if (progress)
+               fprintf(stderr,"        getbranch:\n");
+       getbranch(head);
+       chfree(head,nodenum * sizeof(*head));
+       head = 0;
+       }
diff --git a/usr/src/cmd/struct/3.reach.c b/usr/src/cmd/struct/3.reach.c
new file mode 100644 (file)
index 0000000..99e6a42
--- /dev/null
@@ -0,0 +1,143 @@
+#include <stdio.h>
+#
+/*
+set REACH[v] = w if w is only node outside subtree of v which is reached from within
+       subtree of v, REACH[v] = UNDEFINED otherwise
+*/
+#include "def.h"
+
+/* strategy in obtaining REACH(v) for each node v:
+Since only need to know whether there is exactly one exit from subtree of v,
+need keep track only of 2 farthest exits from each subtree rather than all exits.
+The first may be the unique exit, while the second is used when the children
+of a node has the same first exit.
+To obtain 2 farthest exits of v, look at 2 farthest exits of children of v and
+the nodes entered by arcs from v.  Farthest exits are identified by numbering
+the nodes from -2 to -(accessnum-2) starting at the bottom left corner of tree
+using procedure number().  The farthest exit from the subtree of v is the one
+with the least number according NUM to this numbering.  If a node w is an exit from the
+subtree of v, then NUM(w) < NUM(v).  The negative numbers allow NUM(v) to be stored
+in the same location as REACH(v).  REACH(w) may already be set when an arc (v,w) to a child
+is searched, but the negative numbering is consistent, i.e. NUM(v) < NUM(w) in this case
+as in other cases where w is not an exit from the subtree of v.
+*/
+
+struct pair {
+       int smallest;
+       int second;
+       };
+
+
+getreach()             /* obtain REACH(v) for each node v */
+       {
+       VERT v;
+       struct pair *pr;
+       for (v = 0; v < nodenum; ++v)
+               REACH(v) = UNDEFINED;
+       number(START);
+       for (v = START; DEFINED(v); v = RSIB(v))
+               {
+               pr = exits(v);  /* need to free the space for pr */
+               chfree(pr,sizeof(*pr));
+               }
+       }
+
+
+exits(v)       /* set REACH(v) = w if w is only node outside subtree of v which is reached from within
+                       subtree of v, leave REACH(v) UNDEFINED otherwise */
+VERT v;
+       {
+       struct pair *vpair, *chpair;
+       VERT w,t;
+       int i;
+       vpair = challoc(sizeof(*vpair));
+       vpair ->smallest = vpair ->second = UNDEFINED;
+       for (i = 0; i < CHILDNUM(v); ++i)
+               {
+               w = LCHILD(v,i);
+               if (!DEFINED(w)) continue;
+               for (t = w; DEFINED(t); t = RSIB(t))
+                       {
+                       chpair = exits(t);
+
+                       /* set vpair->smallest,second to two smallest of vpair->smallest,second,
+                               chpair->smallest,second */
+                       if (inspr(chpair->smallest,vpair))
+                               inspr(chpair->second,vpair);
+                       chfree(chpair, sizeof(*chpair));
+                       }
+               }
+       for (i = 0; i < ARCNUM(v); ++i)
+               {
+               w = ARC(v,i);
+               if (!DEFINED(w)) continue;
+                       inspr(w,vpair);
+               }
+       /* throw out nodes in subtree of  v */
+       if (NUM(vpair->second) >= NUM(v))
+               {
+               vpair->second = UNDEFINED;
+               if (NUM(vpair->smallest) >= NUM(v))
+                       vpair->smallest = UNDEFINED;
+               }
+       if (vpair->second == UNDEFINED)
+                REACH(v) = vpair->smallest;    /* vpair->smallest possibly UNDEFINED */
+       else
+               REACH(v) = UNDEFINED;
+       return(vpair);
+       }
+
+
+       /* number nodes from -2 to -(accessnum+2) starting at bottom left corner of tree */
+number(v)
+VERT v;
+       {
+       int i;
+       VERT w;
+       static int count;
+       for (i = 0; i < CHILDNUM(v); ++i)
+               {
+               w = LCHILD(v,i);
+               if (DEFINED(w))
+                       number(w);
+               }
+       SETNUM(v,count-2);
+       --count;
+       if (DEFINED(RSIB(v)))
+               number(RSIB(v));
+       }
+
+
+NUM(v)
+VERT v;
+       {
+       if (!DEFINED(v)) return(UNDEFINED);
+       return(REACH(v));
+       }
+
+SETNUM(v,count)
+VERT v; int count;
+       {
+       /* this reuses REACH to save space;
+       /* appears to be no conflict with setting true value of REACH later */
+       REACH(v) = count;
+       }
+
+
+LOGICAL inspr(w,pr)            /* insert w in order in pr, return TRUE if <= smaller of pr */
+                                       /* don't insert duplicates */
+VERT w;
+struct pair *pr;
+       {
+       if (w == pr-> smallest) return(TRUE);
+       if (NUM(w) < NUM(pr->smallest))
+               {
+               pr->second = pr->smallest;
+               pr->smallest = w;
+               return(TRUE);
+               }
+       if (w == pr->second) return(FALSE);
+       if (NUM(w) < NUM(pr->second))
+               pr->second = w;
+       return(FALSE);
+       }
diff --git a/usr/src/cmd/struct/3.test.c b/usr/src/cmd/struct/3.test.c
new file mode 100644 (file)
index 0000000..b389e4c
--- /dev/null
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#
+/* for testing only */
+#include "def.h"
+
+testreach()
+       {
+       VERT v;
+       for (v = 0; v < nodenum; ++v)
+               fprintf(stderr,"REACH(%d) = %d\n",v,REACH(v));
+       }
diff --git a/usr/src/cmd/struct/3.then.c b/usr/src/cmd/struct/3.then.c
new file mode 100644 (file)
index 0000000..6b056bf
--- /dev/null
@@ -0,0 +1,75 @@
+#include <stdio.h>
+#include "def.h"
+#include "3.def.h"
+
+#define BRANCHTYPE(t)  (t == STOPVX || t == RETVX || t == BRKVX || t == NXTVX || t == GOVX)
+#define MAXCHUNK       20
+               /* if else clause smaller than MAXCHUNK and smaller than then clause,
+                       and there is no reason not to negate the if, negate the if */
+
+getthen(v)             /* turn IFVX into THEN when appropriate, create else ifs where possible  */
+VERT v;
+       {
+       VERT tch, fch;
+       int tn,fn;
+       int recvar;
+
+       if (NTYPE(v) == IFVX)
+               {
+               tch = LCHILD(v,THEN);
+               fch = LCHILD(v,ELSE);
+               if (!DEFINED(fch))
+                       mkthen(v);
+               else if (!DEFINED(tch))
+                       {
+                       negate(v);
+                       mkthen(v);
+                       }
+               else if (BRANCHTYPE(NTYPE(tch)))
+                       mkthen(v);
+               else if (BRANCHTYPE(NTYPE(fch)))
+                       {
+                       negate(v);
+                       mkthen(v);
+                       }
+               else if (NTYPE(fch) != IFVX || DEFINED(RSIB(fch)))      /* not an else if */
+                       if ( NTYPE(tch) == IFVX && !DEFINED(RSIB(tch)))
+                                       /* invert into else if */
+                               negate(v);
+                       else
+                               {
+                               /* asoc(v,n) returns number of statements associated with v
+                                       if <= n, -1 otherwise */
+                               tn = asoc(tch,MAXCHUNK);
+                               fn = asoc(fch,MAXCHUNK);
+                               if (fn >= 0 && (tn < 0 || fn < tn))
+                                       /* else clause smaller */
+                                       negate(v);
+                               }
+               }
+       RECURSE(getthen,v,recvar);
+       }
+
+mkthen(v)
+VERT v;
+       {
+       VERT w,tc;
+       w = LCHILD(v,ELSE);
+       tc = LCHILD(v,THEN);
+       ASSERT(!DEFINED(w) || (DEFINED(tc) && BRANCHTYPE(NTYPE(tc)) ),mkthen);
+       if (DEFINED(w))
+               {
+               insib(v,w);
+               LCHILD(v,ELSE) = UNDEFINED;
+               }
+       ASSERT(IFTHEN(v),mkthen);
+       }
+
+
+negate(v)
+VERT v;
+       {
+       ASSERT(NTYPE(v) == IFVX,negate);
+       exchange(&LCHILD(v,THEN), &LCHILD(v,ELSE));
+       NEG(v) = !NEG(v);
+       }
diff --git a/usr/src/cmd/struct/4.brace.c b/usr/src/cmd/struct/4.brace.c
new file mode 100644 (file)
index 0000000..1d14d78
--- /dev/null
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include "def.h"
+#include "4.def.h"
+#include "3.def.h"
+
+ndbrace(v)                     /* determine whether braces needed around subparts of v */
+                               /* return TRUE if v ends with IF THEN not in braces */
+VERT v;
+       {
+       VERT w;
+       int i;
+       LOGICAL endif;
+       endif = FALSE;
+       for (i = 0; i < CHILDNUM(v); ++i)
+               {
+               endif = FALSE;
+               for (w = LCHILD(v,i); DEFINED(w); w = RSIB(w))
+                       endif = ndbrace(w);
+               if (NTYPE(v) != DUMVX && NTYPE(v) != ITERVX &&
+                       (!DEFINED(LCHILD(v,i)) || compound(v,i) ||
+                       (endif && NTYPE(v) == IFVX && !IFTHEN(v) && i == THEN )))
+                               /* DUMVX doesn't nest, ITERVX doen't nest since
+                                       nesting is done at LOOPNODE, etc., must
+                                       check for IFTHEN followed by unrelated ELSE */
+                       {
+                       YESBRACE(v,i);
+                       endif = FALSE;
+                       }
+               }
+       return(endif || IFTHEN(v) );
+       }
+
+
+compound(v,ch)         /* return TRUE iff subpart ch of v has multiple statements */
+VERT v;
+int ch;
+       {
+       VERT w;
+       w = LCHILD(v,ch);
+       if (!DEFINED(w))
+               return(FALSE);
+       if (NTYPE(w) == ITERVX)
+               {
+               ASSERT(DEFINED(NXT(w)),compound);
+               if (LABEL(NXT(w)))
+                       return(TRUE);           /* loop ends with labeled CONTINUE statement */
+               else
+                       return(compound(w,0));
+               }
+       else if (DEFINED(RSIB(w)))
+               return(TRUE);
+       else if (NTYPE(w) == STLNVX && CODELINES(w) > 1)
+               return(TRUE);
+       else
+               return(FALSE);
+       }
diff --git a/usr/src/cmd/struct/4.def.h b/usr/src/cmd/struct/4.def.h
new file mode 100644 (file)
index 0000000..a5530d1
--- /dev/null
@@ -0,0 +1,11 @@
+#define YESTAB TRUE
+#define NOTAB  FALSE
+#define TABOVER(n)     tabover(n,outfd)
+#define OUTSTR(x)              fprintf(outfd,"%s",x)
+#define OUTNUM(x)              fprintf(outfd,"%d",x)
+
+
+extern LOGICAL *brace;
+#define YESBRACE(v,i)  { if (DEFINED(LCHILD(v,i))) brace[LCHILD(v,i)] = TRUE; }
+#define NOBRACE(v,i)   { if (DEFINED(LCHILD(v,i))) brace[LCHILD(v,i)] = FALSE; }
+#define HASBRACE(v,i)   ((DEFINED(LCHILD(v,i))) ? brace[LCHILD(v,i)] : TRUE)
diff --git a/usr/src/cmd/struct/4.form.c b/usr/src/cmd/struct/4.form.c
new file mode 100644 (file)
index 0000000..c85ec44
--- /dev/null
@@ -0,0 +1,113 @@
+#include <stdio.h>
+#
+#include "def.h"
+#include "4.def.h"
+extern int linechars;
+extern int rdfree(), comfree(), labfree(), contfree();
+extern int rdstand(), comstand(), labstand(), contstand();
+extern int (*rline[])();
+extern int (*comment[])();
+extern int (*getlabel[])();
+extern int (*chkcont[])();
+null(c)
+char c;
+       {return;}
+
+
+
+comprint()
+       {
+       int c, blank, first,count;
+       blank = 1;
+       first = 1;
+       count = 0;
+       while ((c = (*comment[inputform])(0) ) || blankline() )
+               {
+               ++count;
+               if (c)
+                       {
+                       (*comment[inputform])(1);               /* move head past comment signifier */
+                       blank = blankline();
+                       /* if (first && !blank)
+                               OUTSTR("#\n");*/
+                       prline("#");
+                       first = 0;
+                       }
+               else
+                       (*rline[inputform])(null);
+               }
+       /* if (!blank) 
+               OUTSTR("#\n"); */
+       return(count);
+       }
+
+
+
+prcode(linecount,tab)
+int linecount, tab;
+       {
+       int someout;
+       someout = FALSE;
+       while (linecount)
+               {
+               if ( (*comment[inputform])(0) )
+                       {
+                       linecount -= comprint();
+                       someout = TRUE;
+                       continue;
+                       }
+               else if (blankline() )
+                       (*rline[inputform])(null);
+               else if ((*chkcont[inputform])() )
+                       {
+                       TABOVER(tab);
+                       prline("&");
+                       someout  = TRUE;
+                       }
+               else 
+                       {if (someout) TABOVER(tab);
+                       (*getlabel[inputform])(null);
+                       prline("");
+                       someout=TRUE;
+                       }
+               --linecount;
+               }
+       }
+
+
+charout(c)
+char c;
+       {
+       putc(c,outfd);
+       }
+
+
+
+prline(str)
+char *str;
+       {
+       fprintf(outfd,"%s",str);
+       (*rline[inputform]) (charout);
+       putc('\n',outfd);
+       }
+
+
+input2()
+       {
+       static int c;
+       c = inchar();
+       if (c == '\n')
+               linechars = 0;
+       else
+               ++linechars;
+       return(c);
+       }
+
+
+unput2(c)
+int c;
+       {
+       unchar(c);
+       --linechars;
+       return(c);
+       }
diff --git a/usr/src/cmd/struct/4.main.c b/usr/src/cmd/struct/4.main.c
new file mode 100644 (file)
index 0000000..3002a1f
--- /dev/null
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include "def.h"
+#include "4.def.h"
+
+LOGICAL *brace;
+output()
+       {
+       VERT w;
+       int i;
+       brace = challoc(nodenum * sizeof(*brace));
+       for (i = 0; i < nodenum; ++i)
+               brace[i] = FALSE;
+       if (progress) fprintf(stderr,"ndbrace:\n");
+       for (w = START; DEFINED(w); w = RSIB(w))
+               ndbrace(w);
+       if (progress) fprintf(stderr,"outrat:\n");
+       for (w = START; DEFINED(w); w = RSIB(w))
+               outrat(w,0,YESTAB);
+       OUTSTR("END\n");
+       chfree(brace,nodenum * sizeof(*brace));
+       brace = 0;
+       }
diff --git a/usr/src/cmd/struct/4.out.c b/usr/src/cmd/struct/4.out.c
new file mode 100644 (file)
index 0000000..89ec32e
--- /dev/null
@@ -0,0 +1,292 @@
+#include <stdio.h>
+#include "def.h"
+#include "4.def.h"
+#include "3.def.h"
+
+outrat(v,tab,tabfirst)
+VERT v;
+int tab;               /* number of tabs to indent */
+LOGICAL tabfirst;      /* FALSE if doing IF of ELSE IF */
+       {
+       LOGICAL ndcomma;
+       VERT w;
+       int type,i;
+       type = NTYPE(v);
+       if (hascom[type])
+               prcom(v);
+       if (!LABEL(v) && type == FMTVX)
+               {
+               OUTSTR("#following unreferenced format statement commented out\n");
+               OUTSTR("#");
+               }
+       if (LABEL(v) && type != ITERVX)
+               {
+               ASSERT(tabfirst, outrat);
+               prlab(LABEL(v),tab);
+               }
+       else if (tabfirst && type != DUMVX && type != ITERVX)
+               TABOVER(tab);
+
+       switch(type)
+               {
+               case DUMVX:
+                       newlevel(v,0,tab,YESTAB);
+                       break;
+               case GOVX:
+                       OUTSTR("go to ");
+                       OUTNUM(LABEL(ARC(v,0)));
+                       OUTSTR("\n");
+                       break;
+               case STOPVX:
+                       if (progtype != blockdata)
+                               OUTSTR("stop\n");
+                       break;
+               case RETVX:
+                       OUTSTR("return\n");
+                       break;
+               case BRKVX:
+                       if (!levbrk)
+                               {
+                               ASSERT(LEVEL(v) == 1,outrat);
+                               OUTSTR("break\n");
+                               }
+                       else
+                               {
+                               OUTSTR("break ");
+                               OUTNUM(LEVEL(v));
+                               OUTSTR("\n");
+                               }
+                       break;
+               case NXTVX:
+                       if (!levnxt)
+                               {
+                               ASSERT(LEVEL(v) == 1,outrat);
+                               OUTSTR("next\n");
+                               }
+                       else
+                               {
+                               OUTSTR("next ");
+                               OUTNUM(LEVEL(v));
+                               OUTSTR("\n");
+                               }
+                       break;
+               case ASGOVX:
+               case COMPVX:
+                       OUTSTR("goto ");
+                       if (type == ASGOVX)
+                               {
+                               OUTSTR(EXP(v));
+                               OUTSTR(",");
+                               }
+                       OUTSTR("(");
+                       for (i = ARCNUM(v)-1; i >=0; --i)               /* arcs were stored backward */
+                               {
+                               OUTNUM(LABEL(ARC(v,i)));
+                               if (i > 0) OUTSTR(",");
+                               }
+                       OUTSTR(")");
+                       if (type == COMPVX)
+                               {
+                               OUTSTR(",");
+                               OUTSTR(EXP(v));
+                               }
+                       OUTSTR("\n");
+                       break;
+               case ASVX:
+                       OUTSTR("assign ");
+                       OUTNUM(LABEL(LABREF(v)));
+                       OUTSTR(" to ");
+                       OUTSTR(EXP(v));
+                       OUTSTR("\n");
+                       break;
+               case IFVX:
+                       OUTSTR("IF");
+                       prpred(v,TRUE);
+                       if (IFTHEN(v))
+                               newlevel(v,THEN,tab+1,YESTAB);
+                       else
+                               {
+                               newlevel(v,THEN,tab+1,YESTAB);
+                               TABOVER(tab);
+                               OUTSTR("ELSE ");
+                               w = LCHILD(v,ELSE);
+                               ASSERT(DEFINED(w),outrat);
+                               if (NTYPE(w) == IFVX && !LABEL(w) && !DEFINED(RSIB(w)) &&
+                                       !HASBRACE(v,ELSE) )
+                                       newlevel(v,ELSE,tab,NOTAB);
+                               else
+                                       newlevel(v,ELSE,tab+1,YESTAB);
+                               }
+                       break;
+               case ITERVX:
+                       newlevel(v,0,tab,YESTAB);
+                       ASSERT(DEFINED(NXT(v)),outrat);
+                       if (LABEL(NXT(v)))
+                               {
+                               prlab(LABEL(NXT(v)),tab);
+                               OUTSTR("continue\n");
+                               }
+                       break;
+               case DOVX:
+                       OUTSTR("DO ");
+                       OUTSTR(INC(v));
+                       newlevel(v,0,tab+1,YESTAB);
+                       break;
+               case LOOPVX:
+               case UNTVX:
+                       OUTSTR("REPEAT");
+                       newlevel(v,0,tab+1,YESTAB);
+                       if (type == UNTVX)
+                               {
+                               TABOVER(tab+1);
+                               OUTSTR("UNTIL");
+                               ASSERT(DEFINED(ARC(v,0)),outrat);
+                               prpred(LPRED(ARC(v,0)),TRUE);
+                               OUTSTR("\n");
+                               }
+                       break;
+               case WHIVX:
+                       OUTSTR("WHILE");
+                       ASSERT(DEFINED(ARC(v,0)),outrat);
+                       ASSERT(DEFINED(LPRED(ARC(v,0))),outrat);
+                       prpred(LPRED(ARC(v,0)),TRUE);
+                       newlevel(v,0,tab+1,YESTAB);
+                       break;
+               case STLNVX:
+               case FMTVX:
+                       prstln(v,tab);
+                       break;
+               case SWCHVX:
+                               OUTSTR("SWITCH");
+                               if (DEFINED(EXP(v)))
+                                       {
+                                       OUTSTR("(");
+                                       OUTSTR(EXP(v));
+                                       OUTSTR(")");
+                                       }
+                               newlevel(v,0,tab+1,YESTAB);
+                               break;
+               case ICASVX:
+               case ACASVX:
+                       OUTSTR("CASE ");
+                       if (type == ACASVX)
+                               prpred(v,FALSE);
+                       else
+                               OUTSTR(EXP(v));
+                       OUTSTR(":\n");
+                       newlevel(v,0,tab+1,YESTAB);
+                       if (type == ACASVX &&DEFINED(LCHILD(v,ELSE)))
+                               {
+                               TABOVER(tab);
+                               OUTSTR("DEFAULT:\n");
+                               newlevel(v,1,tab+1,YESTAB);
+                               }
+                       break;
+               case IOVX:
+                       OUTSTR(PRERW(v));
+                       ndcomma = FALSE;
+                       if (DEFINED(FMTREF(v)))
+                               {
+                               OUTNUM(LABEL(FMTREF(v)));
+                               ndcomma = TRUE;
+                               }
+                       if (DEFINED(ARC(v,ENDEQ)))
+                               {
+                               if (ndcomma) 
+                                       OUTSTR(",");
+                               OUTSTR("end = ");
+                               OUTNUM(LABEL(ARC(v,ENDEQ)));
+                               ndcomma = TRUE;
+                               }
+                       if (DEFINED(ARC(v,ERREQ)))
+                               {
+                               if (ndcomma)
+                                       OUTSTR(",");
+                               OUTSTR("err = ");
+                               OUTNUM(LABEL(ARC(v,ERREQ)));
+                               ndcomma = TRUE;
+                               }
+                       OUTSTR(POSTRW(v));
+                       OUTSTR("\n");
+                       break;
+               }
+       }
+
+
+newlevel(v,ch,tab,tabfirst)
+VERT v;
+int ch;                /* number of lchild of v being processed */
+int tab;               /* number of tabs to indent */
+LOGICAL tabfirst;      /* same as for outrat */
+       {
+       LOGICAL addbrace;
+       VERT w;
+       if (NTYPE(v) == ACASVX || NTYPE(v) == ICASVX)
+               addbrace = FALSE;
+       else
+               addbrace = HASBRACE(v,ch);
+       ASSERT(tabfirst || !addbrace,newlevel);
+       if (addbrace)
+               OUTSTR(" {");
+       if(tabfirst && NTYPE(v)!=ITERVX && NTYPE(v)!=DUMVX) OUTSTR("\n");
+       for (w = LCHILD(v,ch); DEFINED(w); w = RSIB(w))
+               outrat(w,tab,tabfirst);
+       if (addbrace)
+               {
+               TABOVER(tab);
+               OUTSTR("}\n");
+               }
+       }
+
+
+
+
+
+prpred(v,addpar)
+VERT v;
+LOGICAL addpar;
+       {
+       if (addpar)
+               OUTSTR("(");
+       if (NEG(v)) OUTSTR("!(");
+       OUTSTR(PRED(v));
+       if (NEG(v)) OUTSTR(")");
+       if (addpar)
+               OUTSTR(")");
+       }
+
+prlab(n,tab)
+int n,tab;
+       {
+       TABOVER(tab);
+       OUTSTR("~");
+       OUTNUM(n);
+       OUTSTR(" ");
+       }
+
+prstln(v,tab)
+VERT v;
+int tab;
+       {
+       ASSERT(NTYPE(v) == STLNVX || NTYPE(v) == FMTVX,prstln);
+       if (!ONDISK(v))
+               {
+               OUTSTR(BEGCODE(v));
+               OUTSTR("\n");
+               }
+       else
+               {
+               empseek(BEGCODE(v));
+               prcode(ONDISK(v),tab);
+               }
+       }
+
+prcom(v)
+VERT v;
+       {
+       if (DEFINED(BEGCOM(v)))
+               {
+               empseek(BEGCOM(v));
+               comprint();
+               }
+       }
diff --git a/usr/src/cmd/struct/Makefile b/usr/src/cmd/struct/Makefile
new file mode 100644 (file)
index 0000000..bbbe3e7
--- /dev/null
@@ -0,0 +1,49 @@
+CFLAGS=-O
+YFLAGS=-d
+0FILES.c = 0.alloc.c 0.args.c 0.def.c 0.extr.c 0.graph.c 0.list.c 0.parts.c 0.string.c
+0FILES.o = 0.alloc.o 0.args.o 0.def.o 0.extr.o 0.graph.o 0.list.o 0.parts.o 0.string.o
+
+1FILES.c = 1.finish.c 1.form.c 1.fort.c 1.hash.c 1.init.c 1.line.c 1.main.c 1.node.c 1.recog.c 1.tables.c
+1FILES.o = 1.finish.o 1.form.o 1.fort.o 1.hash.o 1.init.o 1.line.o 1.main.o 1.node.o 1.recog.o 1.tables.o
+
+2FILES.c = 2.dfs.c 2.dom.c 2.head.c 2.inarc.c 2.main.c 2.tree.c
+2FILES.o = 2.dfs.o 2.dom.o 2.head.o 2.inarc.o 2.main.o 2.tree.o
+
+3FILES.c = 3.branch.c 3.flow.c 3.loop.c 3.main.c 3.reach.c 3.then.c
+3FILES.o = 3.branch.o 3.flow.o 3.loop.o 3.main.o 3.reach.o 3.then.o
+
+4FILES.c = 4.brace.c 4.form.c 4.main.c 4.out.c
+4FILES.o = 4.brace.o 4.form.o 4.main.o 4.out.o
+
+all:   structure beautify
+
+install: structure beautify
+       install -s structure $(DESTDIR)/usr/lib/struct
+       install -s beautify $(DESTDIR)/usr/lib/struct
+       install -c struct $(DESTDIR)/usr/bin
+clean:
+       rm -f *.o y.tab.h beauty.c
+
+structure: main.o $(0FILES.o) $(1FILES.o) $(2FILES.o) $(3FILES.o) $(4FILES.o)
+       cc -o structure main.o 0.*.o 1.*.o 2.*.o 3.*.o 4.*.o 
+
+beautify:      beauty.o tree.o lextab.o bdef.o
+       cc -O beauty.o tree.o lextab.o bdef.o -o beautify -lln
+
+lint:
+       lint $(0FILES.c) $(1FILES.c) $(2FILES.c) $(3FILES.c) $(4FILES.c) main.c
+
+main.o $(0FILES.o) $(1FILES.o) $(2FILES.o) $(3FILES.o) $(4FILES.o): def.h
+
+$(1FILES.o): 1.defs.h 1.incl.h
+$(2FILES.o): 2.def.h
+$(3FILES.o): 3.def.h
+$(4FILES.o): 4.def.h
+
+lextab.o tree.o: y.tab.h
+
+y.tab.h: beauty.y
+
+lextab.o tree.o beauty.y: b.h
+
+y.tab.h:       beauty.c
diff --git a/usr/src/cmd/struct/b.h b/usr/src/cmd/struct/b.h
new file mode 100644 (file)
index 0000000..24b7509
--- /dev/null
@@ -0,0 +1,10 @@
+extern int xxindent, xxval, newflag, xxmaxchars, xxbpertab;
+extern int xxlineno;           /* # of lines already output */
+#define xxtop  100             /* max size of xxstack */
+extern int xxstind, xxstack[xxtop], xxlablast, xxt;
+struct node
+       {int op;
+       char *lit;
+       struct node *left;
+       struct node *right;
+       };
diff --git a/usr/src/cmd/struct/bdef.c b/usr/src/cmd/struct/bdef.c
new file mode 100644 (file)
index 0000000..88aa3d2
--- /dev/null
@@ -0,0 +1,4 @@
+#define xxtop  100             /* max size of xxstack */
+int xxindent, xxval, newflag, xxmaxchars, xxbpertab;
+int xxlineno;          /* # of lines already output */
+int xxstind, xxstack[xxtop], xxlablast, xxt;
diff --git a/usr/src/cmd/struct/beauty.y b/usr/src/cmd/struct/beauty.y
new file mode 100644 (file)
index 0000000..067c08c
--- /dev/null
@@ -0,0 +1,410 @@
+%term  xxif 300 xxelse 301 xxwhile 302 xxrept 303 xxdo 304 xxrb 305 xxpred 306
+%term xxident 307 xxle 308 xxge 309 xxne 310 xxnum 311 xxcom 312
+%term xxstring 313 xxexplist 314 xxidpar 315 xxelseif 316  xxlb 318 xxend 319
+%term xxcase 320 xxswitch 321 xxuntil 322 xxdefault 323 
+%term xxeq 324
+
+%left  '|'
+%left  '&'
+%left  '!'
+%binary        '<' '>' xxeq xxne xxge xxle
+%left  '+' '-'
+%left  '*' '/'
+%left  xxuminus
+%right '^'
+
+%{
+#include "b.h"
+#include <stdio.h>
+%}
+
+%%
+%{
+struct node *t;
+%}
+
+
+allprog:       prog xxnew
+       ;
+
+prog:  stat
+       |       prog stat
+       ;
+
+stat:           iftok pred nlevel elsetok nlevel
+       |        iftok  pred  nlevel
+       |       xxtab whtok  pred  nlevel
+       |       xxtab rpttok nlevel optuntil
+       |       xxtab dotok nlevel
+       |       xxtab swtok oppred pindent lbtok caseseq xxtab rbtok mindent
+       |       xxtab fstok
+       |       lbtok prog xxtab rbtok
+       |       lbtok rbtok
+       |        labtok stat
+       |       xxnl comtok stat
+       |       error
+       ;
+
+
+xxtab:         =       {
+                       if (!xxlablast) tab(xxindent);
+                       xxlablast = 0;
+                       }
+
+xxnl:  =       newline();
+xxnew: =       putout('\n',"\n");
+nlevel:        pindent stat mindent;
+pindent:               =
+                               {
+                               if (xxstack[xxstind] != xxlb)
+                                       ++xxindent;
+                               };
+mindent:                       =
+                               {if (xxstack[xxstind] != xxlb && xxstack[xxstind] != xxelseif)
+                                       --xxindent;
+                               pop();
+                               };
+caseseq:       casetok caseseq
+       |       casetok
+       ;
+
+casetok:       xxtab xxctok predlist pindent prog mindent
+       |       xxtab xxctok predlist pindent mindent
+       |       xxtab deftok pindent prog mindent
+       |       xxnl comtok casetok
+       ;
+
+xxctok:        xxcase          =       {putout(xxcase,"case "); free ($1); push(xxcase); }
+
+
+deftok:                xxdefault ':'           =               {
+                                               putout(xxcase,"default");
+                                               free($1);
+                                               putout(':',":");
+                                               free($2);
+                                               push(xxcase);
+                                               }
+swtok: xxswitch                        =       {putout(xxswitch,"switch"); free($1); push(xxswitch); }
+
+fstok: xxend           =       {
+                               free($1);
+                               putout(xxident,"end");
+                               putout('\n',"\n");
+                               putout('\n',"\n");
+                               putout('\n',"\n");
+                               }
+       |       xxident =       {
+                               putout(xxident,$1);
+                               free($1);
+                               newflag = 1;
+                               forst();
+                               newflag = 0;
+                               };
+
+               
+
+identtok:      xxident '(' explist ')' =       {
+                               xxt = addroot($1,xxident,0,0);
+                               $$ = addroot("",xxidpar,xxt,$3);
+                               }
+
+       |       xxident         =       $$ = addroot($1,xxident,0,0);
+       ;
+
+predlist:      explist  ':'            =       {
+                               yield($1,0);
+                               putout(':',":");
+                               freetree($1);
+                               }
+explist:       expr ',' explist                =       $$ = addroot($2,xxexplist,checkneg($1,0),$3);
+       |       expr                                    =       $$ = checkneg($1,0);
+       ;
+
+
+oppred:        pred
+       |
+       ;
+
+pred:  '(' expr ')'    =       { t = checkneg($2,0);
+                               yield(t,100);  freetree(t);     };
+
+expr:          '(' expr ')'    =       $$ = $2;
+       |       '-' expr        %prec xxuminus  =       $$ = addroot($1,xxuminus,$2,0);
+       |       '!' expr        =       $$ = addroot($1,'!',$2,0);
+       |       expr '+' expr   =       $$ = addroot($2,'+',$1,$3);
+       |       expr '-' expr   =       $$ = addroot($2,'-',$1,$3);
+       |       expr '*' expr   =       $$ = addroot($2,'*',$1,$3);
+       |       expr '/' expr   =       $$ = addroot($2,'/',$1,$3);
+       |       expr '^' expr   =       $$ = addroot($2,'^',$1,$3);
+       |       expr '|' expr   =       $$ = addroot($2,'|',$1,$3);
+       |       expr '&' expr   =       $$ = addroot($2,'&',$1,$3);
+       |       expr '>' expr   =       $$ = addroot($2,'>',$1,$3);
+       |       expr '<' expr   =       $$ = addroot($2,'<',$1,$3);
+       |       expr xxeq expr  =       $$ = addroot($2,xxeq,$1,$3);
+       |       expr xxle expr  =       $$ = addroot($2,xxle,$1,$3);
+       |       expr xxge expr  =       $$ = addroot($2,xxge,$1,$3);
+       |       expr xxne expr  =       $$ = addroot($2,xxne,$1,$3);
+       |       identtok                =       $$ = $1;
+       |       xxnum           =       $$ = addroot($1,xxnum,0,0);
+       |       xxstring                =       $$ = addroot($1,xxstring,0,0);
+       ;
+
+iftok: xxif            =
+                               {
+                               if (xxstack[xxstind] == xxelse && !xxlablast)
+                                       {
+                                       --xxindent;
+                                       xxstack[xxstind] = xxelseif;
+                                       putout(' '," ");
+                                       }
+                               else
+                                       {
+                                       if (!xxlablast)
+                                               tab(xxindent);
+                                       xxlablast = 0;
+                                       }
+                               putout(xxif,"if");
+                               free($1);
+                               push(xxif);
+                               }
+elsetok:       xxelse  =
+                               {
+                               tab(xxindent);
+                               putout(xxelse,"else");
+                               free($1);
+                               push(xxelse);
+                               }
+whtok: xxwhile         =       {
+                               putout(xxwhile,"while");
+                               free($1);
+                               push(xxwhile);
+                               }
+rpttok:        xxrept  =                       {
+                                       putout(xxrept,"repeat");
+                                       free($1);
+                                       push(xxrept);
+                                       }
+optuntil:      xxtab unttok pred
+               |
+               ;
+
+unttok:        xxuntil   =     {
+                       putout('\t',"\t");
+                       putout(xxuntil,"until");
+                       free($1);
+                       }
+dotok: dopart opdotok
+       ;
+dopart:        xxdo    identtok '=' expr  ',' expr             =
+                                       {push(xxdo);
+                                       putout(xxdo,"do");
+                                       free($1);
+                                       puttree($2);
+                                       putout('=',"=");
+                                       free($3);
+                                       puttree($4);
+                                       putout(',',",");
+                                       free($5);
+                                       puttree($6);
+                                       }
+opdotok:       ',' expr                =       {
+                                               putout(',',",");
+                                               puttree($2);
+                                               }
+       |       ;
+lbtok: '{'             =       {
+                               putout('{'," {");
+                               push(xxlb);
+                               }
+rbtok: '}'                     =       { putout('}',"}");  pop();   }
+labtok:        xxnum           =       {
+                               tab(xxindent);
+                               putout(xxnum,$1);
+                               putout(' ',"  ");
+                               xxlablast = 1;
+                               }
+comtok:        xxcom           =       { putout(xxcom,$1);  free($1);  xxlablast = 0; }
+       |       comtok xxcom            = { putout ('\n',"\n"); putout(xxcom,$2);  free($2);  xxlablast = 0; };
+%%
+#define ASSERT(X,Y)    if (!(X)) error("struct bug: assertion 'X' invalid in routine Y","","");
+
+yyerror(s)
+char *s;
+       {
+       extern int yychar;
+       fprintf(stderr,"\n%s",s);
+       fprintf(stderr," in beautifying, output line %d,",xxlineno + 1);
+       fprintf(stderr," on input: ");
+               switch (yychar) {
+                       case '\t': fprintf(stderr,"\\t\n"); return;
+                       case '\n': fprintf(stderr,"\\n\n"); return;
+                       case '\0': fprintf(stderr,"$end\n"); return;
+                       default: fprintf(stderr,"%c\n",yychar); return;
+                       }
+       }
+
+yyinit(argc, argv)                     /* initialize pushdown store */
+int argc;
+char *argv[];
+       {
+       xxindent = 0;
+       xxbpertab = 8;
+       xxmaxchars = 120;
+       }
+
+
+#include <signal.h>
+main()
+       {
+       int exit();
+       if ( signal(SIGINT, SIG_IGN) != SIG_IGN)
+               signal(SIGINT, exit);
+       yyinit();
+       yyparse();
+       }
+
+
+putout(type,string)                    /* output string with proper indentation */
+int type;
+char *string;
+       {
+       static int lasttype;
+       if ( (lasttype != 0) && (lasttype != '\n') && (lasttype != ' ') && (lasttype != '\t') && (type == xxcom))
+               accum("\t");
+       else if (lasttype == xxcom && type != '\n')
+               tab(xxindent);
+       else
+               if (lasttype == xxif    ||
+                       lasttype == xxwhile     ||
+                       lasttype == xxdo        ||
+                       type == '='     ||
+                       lasttype == '=' ||
+                       (lasttype == xxident && (type == xxident || type == xxnum) )    ||
+                       (lasttype == xxnum && type == xxnum) )
+                       accum(" ");
+       accum(string);
+       lasttype = type;
+       }
+
+
+accum(token)           /* fill output buffer, generate continuation lines */
+char *token;
+       {
+       static char *buffer;
+       static int lstatus,llen,bufind;
+       int tstatus,tlen,i;
+
+#define NEW    0
+#define MID    1
+#define CONT   2
+
+       if (buffer == 0)
+               {
+               buffer = malloc(xxmaxchars);
+               if (buffer == 0) error("malloc out of space","","");
+               }
+       tlen = slength(token);
+       if (tlen == 0) return;
+       for (i = 0; i < tlen; ++i)
+               ASSERT(token[i] != '\n' || tlen == 1,accum);
+       switch(token[tlen-1])
+               {
+               case '\n':      tstatus = NEW;
+                               break;
+               case '+':
+               case '-':
+               case '*':
+               case ',':
+               case '|':
+               case '&':
+               case '(':       tstatus = CONT;
+                               break;
+               default:        tstatus = MID;
+               }
+       if (llen + bufind + tlen > xxmaxchars && lstatus == CONT && tstatus != NEW)
+               {
+               putchar('\n');
+               ++xxlineno;
+               for (i = 0; i < xxindent; ++i)
+                       putchar('\t');
+               putchar(' ');putchar(' ');
+               llen = 2 + xxindent * xxbpertab;
+               lstatus = NEW;
+               }
+       if (lstatus == CONT && tstatus == MID)
+               {                       /* store in buffer in case need \n after last CONT char */
+               ASSERT(bufind + tlen < xxmaxchars,accum);
+               for (i = 0; i < tlen; ++i)
+                       buffer[bufind++] = token[i];
+               }
+       else
+               {
+               for (i = 0; i < bufind; ++i)
+                       putchar(buffer[i]);
+               llen += bufind;
+               bufind = 0;
+               for (i = 0; i < tlen; ++i)
+                       putchar(token[i]);
+               if (tstatus == NEW) ++xxlineno;
+               llen = (tstatus == NEW) ? 0 : llen + tlen;
+               lstatus = tstatus;
+               }
+       }
+
+tab(n)
+int n;
+       {
+       int i;
+       newline();
+       for ( i = 0;  i < n; ++i)
+               putout('\t',"\t");
+       }
+
+newline()
+       {
+       static int already;
+       if (already)
+               putout('\n',"\n");
+       else
+               already = 1;
+       }
+
+error(mess1, mess2, mess3)
+char *mess1, *mess2, *mess3;
+       {
+       fprintf(stderr,"\nerror in beautifying, output line %d: %s %s %s \n",
+               xxlineno, mess1, mess2, mess3);
+       exit(1);
+       }
+
+
+
+
+
+
+
+push(type)
+int type;
+       {
+       if (++xxstind > xxtop)
+               error("nesting too deep, stack overflow","","");
+       xxstack[xxstind] = type;
+       }
+
+pop()
+       {
+       if (xxstind <= 0)
+               error("stack exhausted, can't be popped as requested","","");
+       --xxstind;
+       }
+
+
+forst()
+       {
+       while( (xxval = yylex()) != '\n')
+               {
+               putout(xxval, yylval);
+               free(yylval);
+               }
+       free(yylval);
+       }
diff --git a/usr/src/cmd/struct/def.h b/usr/src/cmd/struct/def.h
new file mode 100644 (file)
index 0000000..47d86c7
--- /dev/null
@@ -0,0 +1,118 @@
+#define ASSERT(P,R)    {if (!(P)) {fprintf(stderr,"failed assertion in routine R: P\n"); abort();}}
+
+extern int routnum, routerr;
+extern long rtnbeg;            /* number of chars up to beginnine of curernt routing */
+extern int **graph, nodenum;
+extern int stopflg;            /* turns off generation of stop statements */
+
+#define TRUE 1
+#define FALSE 0
+#define LOGICAL int
+#define VERT int
+#define DEFINED(v)     (v >= 0)
+#define UNDEFINED      -1
+
+/* node types */
+#define STLNVX         0
+#define IFVX           1
+#define DOVX           2
+#define IOVX           3
+#define FMTVX          4
+#define COMPVX         5
+#define ASVX           6
+#define ASGOVX         7
+#define LOOPVX         8
+#define WHIVX          9
+#define UNTVX          10
+#define ITERVX         11
+#define THENVX         12
+#define STOPVX         13
+#define RETVX          14
+#define DUMVX          15
+#define GOVX           16
+#define BRKVX          17
+#define NXTVX          18
+#define SWCHVX         19
+#define ACASVX         20
+#define ICASVX         21
+
+#define TYPENUM        22
+
+
+extern int hascom[TYPENUM];            /* FALSE for types with no comments, 2 otherwise */
+extern int nonarcs[TYPENUM];           /* number of wds per node other than arcs */
+extern VERT *arc(), *lchild();
+extern int *vxpart(), *negpart(), *predic(), *expres(), *level(), *stlfmt();
+/* node parts */
+#define FIXED 4                /* number of wds needed in every node */
+#define NTYPE(v)       graph[v][0]
+#define BEGCOM(v)      graph[v][1]
+#define RSIB(v)        graph[v][2]
+#define REACH(v)       graph[v][3]
+#define LCHILD(v,i)    *lchild(v,i)
+#define CHILDNUM(v)    childper[NTYPE(v)]
+#define ARC(v,i)       *arc(v,i)
+#define ARCNUM(v)      *((arcsper[NTYPE(v)] >= 0) ? &arcsper[NTYPE(v)]: &graph[v][-arcsper[NTYPE(v)]])
+
+/* STLNVX, FMTVX parts */
+#define BEGCODE(v)     *stlfmt(v,0)            /* 1st char of line on disk or address of string */
+#define ONDISK(v)      *stlfmt(v,1)            /* FALSE if in core,# of lines on disk otherwise */
+#define CODELINES(v)           *vxpart(v,STLNVX,2)             /* # of statements stored in node */
+
+/* IOVX parts */
+#define FMTREF(v)      *vxpart(v,IOVX,0)       /* FMTVX associated with i/o statememt */
+#define PRERW(v)       *vxpart(v,IOVX,1)       /* string occurring in i/o statement before parts with labels */
+#define POSTRW(v)      *vxpart(v,IOVX,2)       /* string occurring in i/o statement after parts wih labels */
+#define ENDEQ  1               /* arc number associated with endeq */
+#define ERREQ  2               /* arc number associated wth erreq */
+
+/* ITERVX parts */
+#define NXT(v) *vxpart(v,ITERVX,0)             /* THENVX containing condition for iteration for WHILE or UNTIL */
+#define FATH(v) *vxpart(v,ITERVX,1)            /* father of v */
+#define LPRED(v) *vxpart(v,ITERVX,2)           /* loop predicate for WHILE, UNTIL */
+
+/*DOVX parts */
+#define INC(v) *vxpart(v,DOVX,0)               /* string for iteration condition of DO */
+
+/* IFVX,THENVX parts */
+#define PRED(v)                *predic(v)      /* string containing predicate */
+#define NEG(v)                 *negpart(v)             /* TRUE if predicate negated */
+#define THEN   0               /* arc number of true branch */
+#define ELSE 1         /* arc number of false branch */
+
+/* miscellaneous parts */
+#define EXP(v) *expres(v)              /* expression - ASVX, COMPVX, ASGOVX, SWCHVX, ICASVX */
+#define LABREF(v)      *vxpart(v,ASVX,1)               /* node referred to by label in ASSIGN statement */
+
+
+/* BRKVX, NXTVX parts */
+#define LEVEL(v)       *level(v)
+
+/* also COMPVX, ASGOVX, SWCHVX, and DUMVX contain wd for number of arcs */
+/* location of this wd specified by negative entry in arcsper */
+extern int arcsper[TYPENUM];
+
+/* also nodes contain wds for children as specified by childper */
+extern childper[TYPENUM];
+
+
+/* switches */
+extern int intcase, arbcase, whiloop, invelse, exitsize, maxnode,
+       maxhash, progress, labinit, labinc, inputform, debug,levbrk,levnxt,mkunt;
+
+/* arrays */
+extern int *after;
+extern char *typename[];
+
+struct list {
+       VERT elt;
+       struct list *nxtlist;
+       };
+struct list *append(), *consl();
+extern VERT retvert, stopvert; /* specifies unique return and stop vertices */
+extern VERT START;
+extern int progtype;           /* type of program - main or sub or blockdata */
+#define sub    1
+#define blockdata      2
+
+extern FILE *infd, *debfd, *outfd;
diff --git a/usr/src/cmd/struct/lextab.l b/usr/src/cmd/struct/lextab.l
new file mode 100644 (file)
index 0000000..6842baf
--- /dev/null
@@ -0,0 +1,216 @@
+%{
+#include "y.tab.h"
+#include "b.h"
+#undef input
+#define input()        ninput()
+#undef unput
+#define unput(c)       nunput(c)
+extern int yylval;
+#define xxbpmax        1700
+char xxbuf[xxbpmax + 2];
+int xxbp = -1;
+#define xxunmax        200
+char xxunbuf[xxunmax + 2];
+int xxunbp = -1;
+
+
+int blflag;
+%}
+
+D      [0-9]
+A      [0-9a-z]
+L      [a-z]
+SP     [^0-9a-z]
+
+%%
+
+%{
+char *xxtbuff;
+int xxj, xxn, xxk;
+char *xxp;
+%}
+[=/,(]{D}+[h]                  {
+                               blflag = 1;
+                               sscanf(&yytext[1],"%d",&xxn);
+                               xxtbuff = malloc(2*xxn+3);
+                               for (xxj = xxk = 1; xxj <= xxn; ++xxj)
+                                       {
+                                       xxtbuff[xxk] = ninput();
+                                       if (xxtbuff[xxk] == '"')
+                                               xxtbuff[++xxk] = '"';
+                                       ++xxk;
+                                       }
+                               xxtbuff[0] = xxtbuff[xxk++] = '"';
+                               xxtbuff[xxk] = '\0';
+                               putback(xxtbuff);
+                               free(xxtbuff);
+
+                               backup(yytext[0]);
+                               blflag = 0;
+                               xxbp = -1;
+                               }
+IF                     {fixval(); xxbp = -1; return(xxif);}
+ELSE                   {fixval(); xxbp = -1; return(xxelse);}
+REPEAT                 {fixval(); xxbp = -1; return(xxrept); }
+WHILE                  {fixval(); xxbp = -1; return(xxwhile); }
+UNTIL                  { fixval(); xxbp = -1; return(xxuntil); }
+DO                     {fixval(); xxbp = -1; return(xxdo); }
+SWITCH                 {fixval(); xxbp = -1; return(xxswitch); }
+CASE                   {fixval(); xxbp = -1; return(xxcase); }
+DEFAULT                        {fixval(); xxbp = -1; return(xxdefault); }
+END                    {fixval(); xxbp = -1; return(xxend); }
+
+".true."               |
+".false."              |
+
+{L}{A}*                {fixval(); xxbp = -1; return(xxident); }
+~{D}+                  {xxbuf[0] = ' '; fixval(); xxbp = -1; return(xxnum); }
+{D}+/"."(ge|gt|le|lt|eq|ne|not|or|and)"."      |
+{D}+\.?                        |
+{D}+\.?[de][+-]?{D}+           |
+{D}*\.{D}+[de][+-]?{D}+                |
+{D}*\.{D}+                     {fixval(); xxbp = -1; return(xxnum); }
+
+".gt."                 { putback(">"); xxbp = -1; }
+".ge."                 { putback(">=");xxbp = -1; }
+".lt."                 { putback("<"); xxbp = -1; }
+".le."                 { putback("<="); xxbp = -1; }
+".eq."                 { putback("=="); xxbp = -1; }
+".ne."                 { putback("!="); xxbp = -1; }
+".not."                        { putback("!"); xxbp = -1; }
+".or."                 { putback("||"); xxbp = -1; }
+".and."                        { putback("&&"); xxbp = -1; }
+">="           {fixval(); xxbp = -1;  return(xxge);  }
+"<="           {fixval(); xxbp = -1;  return(xxle); }
+==                     {fixval(); xxbp = -1; return(xxeq); }
+!=                     {fixval(); xxbp = -1; return(xxne); }
+"||"                   {fixval(); xxbp = -1; return('|'); }
+"&&"                   {fixval(); xxbp = -1;  return('&'); }
+"**"                   {fixval(); xxbp = -1; return('^'); }
+
+#.*                    {fixval(); xxbp = -1; return(xxcom); }
+\"([^"]|\"\")*\"               {fixval(); xxbp = -1; return(xxstring); }
+'([^']|'')*'                           {
+                                       fixval();
+                                       xxp = yylval;
+                                       xxn = slength(xxp);
+                                       xxtbuff = malloc(2*xxn+1);
+                                       xxtbuff[0] = '"';
+                                       for (xxj = xxk = 1; xxj < xxn-1; ++xxj)
+                                               {
+                                               if (xxp[xxj] == '\'' && xxp[++xxj] == '\'')
+                                                       xxtbuff[xxk++] = '\'';
+                                               else if (xxp[xxj] == '"')
+                                                       {
+                                                       xxtbuff[xxk++] = '"';
+                                                       xxtbuff[xxk++] = '"';
+                                                       }
+                                               else
+                                                       xxtbuff[xxk++] = xxp[xxj];
+                                               }
+                                       xxtbuff[xxk++] = '"';
+                                       xxtbuff[xxk] = '\0';
+                                       free(xxp);
+                                       yylval = xxtbuff;
+                                       xxbp = -1;
+                                       return(xxstring);
+                                       }
+
+^\n            xxbp = -1;
+\n             {xxbp = -1; if (newflag) {fixval(); return('\n'); }  }
+{SP}           {fixval(); xxbp = -1; return(yytext[0]); }
+
+%%
+
+rdchar()
+       {
+       int c;
+       if (xxunbp >= 0)
+               return(xxunbuf[xxunbp--]);
+       c = getchar();
+       if (c == EOF) return('\0');
+       else return((char)c);
+       }
+
+backup(c)
+char c;
+       {
+       if (++xxunbp > xxunmax)
+               {
+               xxunbuf[xxunmax + 1] = '\0';
+               error("RATFOR beautifying; input backed up too far during lex:\n",
+                       xxunbuf,"\n");
+               }
+       xxunbuf[xxunbp] = c;
+       }
+
+nunput(c)
+char c;
+       {
+       backup(c);
+       if (xxbp < 0) return;
+       if (c != xxbuf[xxbp])
+               {
+               xxbuf[xxbp + 1] = '\0';
+               error("RATFOR beautifying; lex call of nunput with wrong char:\n",
+                       xxbuf,"\n");
+               }
+       for ( --xxbp; xxbp >= 0 && (xxbuf[xxbp] == ' ' || xxbuf[xxbp] == '\t'); --xxbp)
+               backup(xxbuf[xxbp]);
+       xxbuf[xxbp+1] = '\0';
+       }
+
+ninput()
+       {
+       char c,d;
+       if (blflag) c = rdchar();
+       else
+               while ( (c = rdchar()) == ' ' || c == '\t')
+               addbuf(c);
+       if (c != '\n')
+               return(addbuf(c));
+       while ( (d = rdchar()) == ' ' || d == '\t');
+       if (d == '&')
+               return(ninput());
+       backup(d);
+       return(addbuf('\n'));
+       }
+
+addbuf(c)
+char c;
+       {
+       if (++xxbp > xxbpmax)
+               {
+               xxbuf[xxbpmax +1] = '\0';
+               error("RATFOR beautifying; buffer xxbuf too small for token beginning:\n",
+                       xxbuf,"\n");
+               }
+       xxbuf[xxbp] = c;
+       xxbuf[xxbp + 1] = '\0';
+       return(c);
+       }
+
+
+fixval()
+       {
+       int i, j, k;
+       for (j = 0; xxbuf[j] == ' ' || xxbuf[j] == '\t'; ++j);
+       for (k = j; xxbuf[k] != '\0'; ++k);
+       for (--k; k > j && xxbuf[k] == ' ' || xxbuf[k]  == '\t'; --k);
+       xxbuf[k+1] = '\0';
+       i = slength(&xxbuf[j]) + 1;
+       yylval = malloc(i);
+       str_copy(&xxbuf[j],yylval,i);
+       }
+
+
+
+putback(str)
+char *str;
+       {
+       int i;
+       for (i = 0; str[i] != '\0'; ++i);
+       for (--i; i >= 0; --i)
+               backup(str[i]);
+       }
+
diff --git a/usr/src/cmd/struct/main.c b/usr/src/cmd/struct/main.c
new file mode 100644 (file)
index 0000000..8a8b5a1
--- /dev/null
@@ -0,0 +1,69 @@
+#include <signal.h>
+#include <stdio.h>
+#include "1.defs.h"
+#include "def.h"
+
+
+char (*input)(), (*unput)();
+FILE *outfd    = stdout;
+
+
+
+main(argc,argv)
+int argc;
+char *argv[];
+       {
+       int anyoutput;
+       int dexit();
+       char *getargs();
+       char input1(), unput1(), input2(), unput2();
+       anyoutput = FALSE;
+       getargs(argc,argv);
+       if (debug == 2) debfd = stderr;
+       else if (debug)
+               debfd = fopen("debug1","w");
+
+       if (signal(SIGINT, SIG_IGN) !=SIG_IGN)
+               signal(SIGINT,dexit);
+       prog_init();
+
+       for (;;)
+               {
+               ++routnum;
+               routerr = 0;
+
+               input = input1;
+               unput = unput1;
+               if (!mkgraph()) break;
+               if (debug) prgraph();
+               if (routerr) continue;
+
+               if (progress)fprintf(stderr,"build:\n");
+               build();
+               if (debug) prtree();
+               if (routerr) continue;
+
+               if (progress)fprintf(stderr,"structure:\n");
+               structure();
+               if (debug) prtree();
+               if (routerr) continue;
+               input = input2;
+               unput = unput2;
+
+               if (progress)fprintf(stderr,"output:\n");
+               output();
+               if (routerr) continue;
+               anyoutput = TRUE;
+               freegraf();
+               }
+       if (anyoutput)
+               exit(0);
+       else
+               exit(1);
+       }
+
+
+dexit()
+       {
+       exit(1);
+       }
diff --git a/usr/src/cmd/struct/struct b/usr/src/cmd/struct/struct
new file mode 100755 (executable)
index 0000000..69d2383
--- /dev/null
@@ -0,0 +1,19 @@
+trap "rm -f /tmp/struct*$$" 0 1 2 3 13 15
+files=no
+for i
+do
+       case $i in
+       -*)     ;;
+       *)      files=yes
+       esac
+done
+
+case $files in
+yes)
+       /usr/lib/struct/structure $* >/tmp/struct$$
+       ;;
+no)
+       cat >/tmp/structin$$
+       /usr/lib/struct/structure /tmp/structin$$ $* >/tmp/struct$$
+esac &&
+       /usr/lib/struct/beautify</tmp/struct$$
diff --git a/usr/src/cmd/struct/tree.c b/usr/src/cmd/struct/tree.c
new file mode 100644 (file)
index 0000000..4f76b53
--- /dev/null
@@ -0,0 +1,238 @@
+# include "y.tab.h"
+#include "b.h"
+#include <stdio.h>
+
+
+addroot(string,type,n1,n2)
+char *string;
+int type;
+struct node *n1, *n2;
+       {
+       struct node *p;
+       p = malloc(sizeof(*p));
+       p->left = n1;
+       p->right = n2;
+       p->op = type;
+       p->lit = malloc(slength(string) + 1);
+       str_copy(string,p->lit,slength(string) + 1);
+       return(p);
+       }
+
+
+freetree(tree)
+struct node *tree;
+       {
+       if (tree)
+               {freetree(tree->left);
+               freetree(tree->right);
+               freenode(tree);
+               }
+       }
+
+freenode(treenode)
+struct node *treenode;
+       {
+       free(treenode->lit);
+       free(treenode);
+       }
+
+int compop[]   {       '&',    '|',    '<',    '>',    xxeq,   xxle,   xxne,   xxge};
+int notop[]    {       '|',    '&',    xxge,   xxle,   xxne,   '>',    xxeq,   '<'};
+char *opstring[]       { "||",  "&&",  ">=",   "<=", "!=",     ">",    "==",   "<"};
+
+checkneg(tree,neg)             /* eliminate nots if possible */
+struct node *tree;
+int neg;
+       {
+       int i;
+       struct node *t;
+       if (!tree) return(0);
+       for (i =  0; i < 8; ++i)
+               if (tree->op == compop[i]) break;
+       if (i > 1 && i <  8 && tree ->left ->op == '-' && str_eq(tree->right->lit,"0"))
+               {
+               t = tree->right;
+               tree->right = tree->left->right;
+               freenode(t);
+               t = tree->left;
+               tree->left = tree->left->left;
+               freenode(t);
+               }
+
+
+       if (neg)
+               {
+               if (tree ->op == '!')
+                       {
+                       t = tree->left;
+                       freenode(tree);
+                       return(checkneg(t,0));
+                       }
+                       if (i < 8)
+                               {
+                               tree->op = notop[i];
+                               free(tree->lit);
+                               tree->lit = malloc(slength(opstring[i])+1);
+                               str_copy(opstring[i],tree->lit, slength(opstring[i])+1);
+                               if (tree->op == '&' || tree->op == '|')
+                                       {
+                                       tree->left = checkneg(tree->left,1);
+                                       tree->right = checkneg(tree->right,1);
+                                       }
+                               return(tree);
+                               }
+               if (tree->op == xxident && str_eq(tree->lit,".false."))
+                       str_copy(".true.",tree->lit, slength(".true.")+1);
+               else if (tree->op == xxident && str_eq(tree->lit,".true."))
+                       {
+                       free(tree->lit);
+                       tree->lit = malloc(slength(".false.")+1);
+                       str_copy(".false.",tree->lit, slength(".false.")+1);
+                       }
+               else
+                       {
+                       tree = addroot("!",'!',tree,0);
+                       tree->lit = malloc(2);
+                       str_copy("!",tree->lit, slength("!")+1);
+                       }
+               return(tree);
+               }
+       else
+               if (tree->op == '!')
+                       {
+                       t = tree;
+                       tree = tree->left;
+                       freenode(t);
+                       return(checkneg(tree,1));
+                       }
+       else
+               {tree->left = checkneg(tree->left,0);
+               tree->right = checkneg(tree->right,0);
+               return(tree);
+               }
+       }
+
+yield(tree,fprec)
+struct node *tree;
+int fprec;                             /* fprec is precedence of father of this node */
+       {
+       int paren,p;
+       static int oplast;                      /* oplast = 1 iff last char printed was operator */
+       if (!tree) return;
+       p = prec(tree ->op);
+       paren = (p < fprec || (oplast && tree->op == xxuminus)) ? 1 : 0;
+
+       if (paren)
+               {
+               putout('(',"(");
+               oplast = 0;
+               }
+
+       switch(tree->op)
+               {
+               case xxuminus:
+                       tree->op = '-';
+               case '!':
+                       putout(tree->op,tree->lit);
+                       oplast = 1;
+                       yield(tree->left,p);
+                       break;
+               case '&':
+               case '|':
+               case '<':
+               case '>':
+               case xxeq:
+               case xxle:
+               case xxge:
+               case '+':
+               case '-':
+               case '*':
+               case '/':
+               case '^':
+                       yield(tree->left,p);
+                       putout(tree->op, tree->lit);
+                       oplast = 1;
+                       yield(tree->right,p);
+                       break;
+               case xxidpar:
+                       yield(tree->left,0);
+                       putout('(',"(");
+                       oplast = 0;
+                       yield(tree->right,0);
+                       putout('(',")");
+                       oplast = 0;
+                       break;
+               default:
+                       yield(tree->left,p);
+                       putout(tree->op, tree->lit);
+                       oplast = 0;
+                       yield(tree->right,p);
+                       break;
+               }
+       if (paren)
+               {
+               putout(')',")");
+               oplast = 0;
+               }
+       }
+
+puttree(tree)
+struct node *tree;
+       {
+       yield(tree,0);
+       freetree(tree);
+       }
+
+
+prec(oper)
+int oper;
+       {
+       switch(oper)
+               {
+               case ',':               return(0);
+               case '|':       return(1);
+               case '&':       return(2);
+               case '!':       return(3);
+
+               case '<':               case '>':               case xxeq:
+               case xxne:      case xxle:      case xxge:
+                               return(4);
+               case '+':
+       case '-':               return(5);
+               case '*':
+       case '/':               return(6);
+               case xxuminus:  return(7);
+               case '^':       return(8);
+               default:        return(9);
+               }
+       }
+str_copy(s,ptr,length) /* copy s at ptr, return length of s */
+char *s, *ptr;
+int length;
+       {int i;
+       for (i = 0; i < length; i++)
+               {
+               ptr[i] = s[i];
+               if (ptr[i] == '\0')
+                       return(i + 1);
+               }
+       fprintf(2,"string %s too long to be copied by str_copy at address %d\n",
+                       *s,ptr);
+       exit(1);
+       }
+str_eq(s,t)
+char s[],t[];
+       {int j;
+       for (j = 0; s[j] == t[j]; j++)
+               {if (s[j] == '\0') return(1);}
+       return(0);
+       }
+
+slength(s)                     /* return number of chars in s, not counting '\0' */
+char *s;
+       {
+       int i;
+       if (!s) return(-1);
+       for (i = 0; s[i] != '\0'; i++);
+       return(i);
+       }
diff --git a/usr/src/cmd/tbl/t..c b/usr/src/cmd/tbl/t..c
new file mode 100644 (file)
index 0000000..4334622
--- /dev/null
@@ -0,0 +1,71 @@
+/* t..c : external declarations */
+
+# include "stdio.h"
+# include "ctype.h"
+
+# define MAXLIN 200
+# define MAXHEAD 30
+# define MAXCOL 20
+# define MAXCHS 2000
+# define MAXRPT 100
+# define CLLEN 10
+# define SHORTLINE 4
+extern int nlin, ncol, iline, nclin, nslin;
+extern int style[MAXHEAD][MAXCOL];
+extern int ctop[MAXHEAD][MAXCOL];
+extern char font[MAXHEAD][MAXCOL][2];
+extern char csize[MAXHEAD][MAXCOL][4];
+extern char vsize[MAXHEAD][MAXCOL][4];
+extern char cll[MAXCOL][CLLEN];
+extern int stynum[];
+extern int F1, F2;
+extern int lefline[MAXHEAD][MAXCOL];
+extern int fullbot[];
+extern char *instead[];
+extern int expflg;
+extern int ctrflg;
+extern int evenflg;
+extern int evenup[];
+extern int boxflg;
+extern int dboxflg;
+extern int linsize;
+extern int tab;
+extern int pr1403;
+extern int linsize, delim1, delim2;
+extern int allflg;
+extern int textflg;
+extern int left1flg;
+extern int rightl;
+struct colstr {char *col, *rcol;};
+extern struct colstr *table[];
+extern char *cspace, *cstore;
+extern char *exstore, *exlim;
+extern int sep[];
+extern int used[], lused[], rused[];
+extern int linestop[];
+extern int leftover;
+extern char *last, *ifile;
+extern int texname;
+extern int texct, texmax;
+extern char texstr[];
+extern int linstart;
+
+
+extern FILE *tabin, *tabout;
+# define CRIGHT 80
+# define CLEFT 40
+# define CMID 60
+# define S1 31
+# define S2 32
+# define TMP 38
+# define SF 35
+# define SL 34
+# define LSIZE 33
+# define SIND 37
+# define SVS 36
+/* this refers to the relative position of lines */
+# define LEFT 1
+# define RIGHT 2
+# define THRU 3
+# define TOP 1
+# define BOT 2
diff --git a/usr/src/cmd/tbl/t0.c b/usr/src/cmd/tbl/t0.c
new file mode 100644 (file)
index 0000000..5ad82c6
--- /dev/null
@@ -0,0 +1,48 @@
+ /* t0.c: storage allocation */
+#
+# include "t..c"
+int expflg = 0;
+int ctrflg = 0;
+int boxflg = 0;
+int dboxflg = 0;
+int tab = '\t';
+int linsize;
+int pr1403;
+int delim1, delim2;
+int evenup[MAXCOL], evenflg;
+int F1 = 0;
+int F2 = 0;
+int allflg = 0;
+int leftover = 0;
+int textflg = 0;
+int left1flg = 0;
+int rightl = 0;
+char *cstore, *cspace;
+char *last;
+struct colstr *table[MAXLIN];
+int style[MAXHEAD][MAXCOL];
+int ctop[MAXHEAD][MAXCOL];
+char font[MAXHEAD][MAXCOL][2];
+char csize[MAXHEAD][MAXCOL][4];
+char vsize[MAXHEAD][MAXCOL][4];
+int lefline[MAXHEAD][MAXCOL];
+char cll[MAXCOL][CLLEN];
+/*char *rpt[MAXHEAD][MAXCOL];*/
+/*char rpttx[MAXRPT];*/
+int stynum[MAXLIN+1];
+int nslin, nclin;
+int sep[MAXCOL];
+int fullbot[MAXLIN];
+char *instead[MAXLIN];
+int used[MAXCOL], lused[MAXCOL], rused[MAXCOL];
+int linestop[MAXLIN];
+int nlin, ncol;
+int iline = 1;
+char *ifile = "Input";
+int texname = 'a';
+int texct = 0;
+char texstr[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYXZ0123456789";
+int linstart;
+char *exstore, *exlim;
+FILE *tabin  /*= stdin */;
+FILE *tabout  /* = stdout */;
diff --git a/usr/src/cmd/tbl/t2.c b/usr/src/cmd/tbl/t2.c
new file mode 100644 (file)
index 0000000..780dc79
--- /dev/null
@@ -0,0 +1,21 @@
+ /* t2.c:  subroutine sequencing for one table */
+# include "t..c"
+tableput()
+{
+saveline();
+savefill();
+ifdivert();
+cleanfc();
+getcomm();
+getspec();
+gettbl();
+getstop();
+checkuse();
+choochar();
+maktab();
+runout();
+release();
+rstofill();
+endoff();
+restline();
+}
diff --git a/usr/src/cmd/tbl/t3.c b/usr/src/cmd/tbl/t3.c
new file mode 100644 (file)
index 0000000..22f71ec
--- /dev/null
@@ -0,0 +1,93 @@
+ /* t3.c: interpret commands affecting whole table */
+# include "t..c"
+struct optstr {char *optnam; int *optadd;} options [] = {
+       "expand", &expflg,
+       "EXPAND", &expflg,
+       "center", &ctrflg,
+       "CENTER", &ctrflg,
+       "box", &boxflg,
+       "BOX", &boxflg,
+       "allbox", &allflg,
+       "ALLBOX", &allflg,
+       "doublebox", &dboxflg,
+       "DOUBLEBOX", &dboxflg,
+       "frame", &boxflg,
+       "FRAME", &boxflg,
+       "doubleframe", &dboxflg,
+       "DOUBLEFRAME", &dboxflg,
+       "tab", &tab,
+       "TAB", &tab,
+       "linesize", &linsize,
+       "LINESIZE", &linsize,
+       "delim", &delim1,
+       "DELIM", &delim1,
+       0,0};
+getcomm()
+{
+char line[200], *cp, nb[25], *t;
+struct optstr *lp;
+int c, ci, found;
+for(lp= options; lp->optnam; lp++)
+       *(lp->optadd) = 0;
+texname = texstr[texct=0];
+tab = '\t';
+printf(".nr %d \\n(.s\n", LSIZE);
+gets1(line);
+/* see if this is a command line */
+if (index(line,';') == NULL)
+       {
+       backrest(line);
+       return;
+       }
+for(cp=line; (c = *cp) != ';'; cp++)
+       {
+       if (!letter(c)) continue;
+       found=0;
+       for(lp= options; lp->optadd; lp++)
+               {
+               if (prefix(lp->optnam, cp))
+                       {
+                       *(lp->optadd) = 1;
+                       cp += strlen(lp->optnam);
+                       if (letter(*cp))
+                               error("Misspelled global option");
+                       while (*cp==' ')cp++;
+                       t=nb;
+                       if ( *cp == '(')
+                               while ((ci= *++cp) != ')')
+                                       *t++ = ci;
+                       else cp--;
+                       *t++ = 0; *t=0;
+                       if (lp->optadd == &tab)
+                               {
+                               if (nb[0])
+                                       *(lp->optadd) = nb[0];
+                               }
+                       if (lp->optadd == &linsize)
+                               printf(".nr %d %s\n", LSIZE, nb);
+                       if (lp->optadd == &delim1)
+                               {
+                               delim1 = nb[0];
+                               delim2 = nb[1];
+                               }
+                       found=1;
+                       break;
+                       }
+               }
+       if (!found)
+               error("Illegal option");
+       }
+cp++;
+backrest(cp);
+return;
+}
+backrest(cp)
+       char *cp;
+{
+char *s;
+for(s=cp; *s; s++);
+un1getc('\n');
+while (s>cp)
+       un1getc(*--s);
+return;
+}
diff --git a/usr/src/cmd/tbl/t4.c b/usr/src/cmd/tbl/t4.c
new file mode 100644 (file)
index 0000000..61ad357
--- /dev/null
@@ -0,0 +1,233 @@
+ /* t4.c: read table specification */
+# include "t..c"
+int oncol;
+getspec()
+{
+int icol, i;
+for(icol=0; icol<MAXCOL; icol++)
+       {
+       sep[icol]= -1;
+       evenup[icol]=0;
+       cll[icol][0]=0;
+       for(i=0; i<MAXHEAD; i++)
+               {
+               csize[i][icol][0]=0;
+               vsize[i][icol][0]=0;
+               font[i][icol][0] = lefline[i][icol] = 0;
+               ctop[i][icol]=0;
+               style[i][icol]= 'l';
+               }
+       }
+nclin=ncol=0;
+oncol =0;
+left1flg=rightl=0;
+readspec();
+fprintf(tabout, ".rm");
+for(i=0; i<ncol; i++)
+       fprintf(tabout, " %02d", 80+i);
+fprintf(tabout, "\n");
+}
+readspec()
+{
+int icol, c, sawchar, stopc, i;
+char sn[10], *snp, *temp;
+sawchar=icol=0;
+while (c=get1char())
+       {
+       switch(c)
+               {
+               default:
+                       if (c != tab)
+                       error("bad table specification character");
+               case ' ': /* note this is also case tab */
+                       continue;
+               case '\n':
+                       if(sawchar==0) continue;
+               case ',':
+               case '.': /* end of table specification */
+                       ncol = max(ncol, icol);
+                       if (lefline[nclin][ncol]>0) {ncol++; rightl++;};
+                       if(sawchar)
+                               nclin++;
+                       if (nclin>=MAXHEAD)
+                               error("too many lines in specification");
+                       icol=0;
+                       if (ncol==0 || nclin==0)
+                               error("no specification");
+                       if (c== '.')
+                               {
+                               while ((c=get1char()) && c != '\n')
+                                       if (c != ' ' && c != '\t')
+                                               error("dot not last character on format line");
+                               /* fix up sep - default is 3 except at edge */
+                               for(icol=0; icol<ncol; icol++)
+                                       if (sep[icol]<0)
+                                               sep[icol] =  icol+1<ncol ? 3 : 1;
+                               if (oncol == 0)
+                                       oncol = ncol;
+                               else if (oncol +2 <ncol)
+                                       error("tried to widen table in T&, not allowed");
+                               return;
+                               }
+                       sawchar=0;
+                       continue;
+               case 'C': case 'S': case 'R': case 'N': case 'L':  case 'A':
+                       c += ('a'-'A');
+               case '_': if (c=='_') c= '-';
+               case '=': case '-':
+               case '^':
+               case 'c': case 's': case 'n': case 'r': case 'l':  case 'a':
+                       style[nclin][icol]=c;
+                       if (c== 's' && icol<=0)
+                               error("first column can not be S-type");
+                       if (c=='s' && style[nclin][icol-1] == 'a')
+                               {
+                               fprintf(tabout, ".tm warning: can't span a-type cols, changed to l\n");
+                               style[nclin][icol-1] = 'l';
+                               }
+                       if (c=='s' && style[nclin][icol-1] == 'n')
+                               {
+                               fprintf(tabout, ".tm warning: can't span n-type cols, changed to c\n");
+                               style[nclin][icol-1] = 'c';
+                               }
+                       icol++;
+                       if (c=='^' && nclin<=0)
+                               error("first row can not contain vertical span");
+                       if (icol>=MAXCOL)
+                               error("too many columns in table");
+                       sawchar=1;
+                       continue;
+               case 'b': case 'i': 
+                       c += 'A'-'a';
+               case 'B': case 'I':
+                       if (icol==0) continue;
+                       snp=font[nclin][icol-1];
+                       snp[0]= (c=='I' ? '2' : '3');
+                       snp[1]=0;
+                       continue;
+               case 't': case 'T':
+                       if (icol>0)
+                       ctop[nclin][icol-1] = 1;
+                       continue;
+               case 'd': case 'D':
+                       if (icol>0)
+                       ctop[nclin][icol-1] = -1;
+                       continue;
+               case 'f': case 'F':
+                       if (icol==0) continue;
+                       snp=font[nclin][icol-1];
+                       snp[0]=snp[1]=stopc=0;
+                       for(i=0; i<2; i++)
+                               {
+                               c = get1char();
+                               if (i==0 && c=='(')
+                                       {
+                                       stopc=')';
+                                       c = get1char();
+                                       }
+                               if (c==0) break;
+                               if (c==stopc) {stopc=0; break;}
+                               if (stopc==0)  if (c==' ' || c== tab ) break;
+                               if (c=='\n'){un1getc(c); break;}
+                               snp[i] = c;
+                               if (c>= '0' && c<= '9') break;
+                               }
+                       if (stopc) if (get1char()!=stopc)
+                               error("Nonterminated font name");
+                       continue;
+               case 'P': case 'p':
+                       if (icol<=0) continue;
+                       temp = snp = csize[nclin][icol-1];
+                       while (c = get1char())
+                               {
+                               if (c== ' ' || c== tab || c=='\n') break;
+                               if (c=='-' || c == '+')
+                                       if (snp>temp)
+                                               break;
+                                       else
+                                               *snp++=c;
+                               else
+                               if (digit(c))
+                                       *snp++ = c;
+                               else break;
+                               if (snp-temp>4)
+                                       error("point size too large");
+                               }
+                       *snp = 0;
+                       if (atoi(temp)>36)
+                               error("point size unreasonable");
+                       un1getc (c);
+                       continue;
+               case 'V': case 'v':
+                       if (icol<=0) continue;
+                       temp = snp = vsize[nclin][icol-1];
+                       while (c = get1char())
+                               {
+                               if (c== ' ' || c== tab || c=='\n') break;
+                               if (c=='-' || c == '+')
+                                       if (snp>temp)
+                                               break;
+                                       else
+                                               *snp++=c;
+                               else
+                               if (digit(c))
+                                       *snp++ = c;
+                               else break;
+                               if (snp-temp>4)
+                                       error("vertical spacing value too large");
+                               }
+                       *snp=0;
+                       un1getc(c);
+                       continue;
+               case 'w': case 'W':
+                       snp = cll [icol-1];
+               /* Dale Smith didn't like this check - possible to have two text blocks
+                  of different widths now ....
+                       if (*snp)
+                               {
+                               fprintf(tabout, "Ignored second width specification");
+                               continue;
+                               }
+               /* end commented out code ... */
+                       stopc=0;
+                       while (c = get1char())
+                               {
+                               if (snp==cll[icol-1] && c=='(')
+                                       {
+                                       stopc = ')';
+                                       continue;
+                                       }
+                               if ( !stopc && (c>'9' || c< '0'))
+                                       break;
+                               if (stopc && c== stopc)
+                                       break;
+                               *snp++ =c;
+                               }
+                       *snp=0;
+                       if (snp-cll[icol-1]>CLLEN)
+                               error ("column width too long");
+                       if (!stopc)
+                               un1getc(c);
+                       continue;
+               case 'e': case 'E':
+                       if (icol<1) continue;
+                       evenup[icol-1]=1;
+                       evenflg=1;
+                       continue;
+               case '0': case '1': case '2': case '3': case '4':
+               case '5': case '6': case '7': case '8': case '9': 
+                       sn[0] = c;
+                       snp=sn+1;
+                       while (digit(*snp++ = c = get1char()))
+                               ;
+                       un1getc(c);
+                       sep[icol-1] = max(sep[icol-1], numb(sn));
+                       continue;
+               case '|':
+                       lefline[nclin][icol]++;
+                       if (icol==0) left1flg=1;
+                       continue;
+               }
+       }
+error("EOF reading table specification");
+}
diff --git a/usr/src/cmd/tbl/t5.c b/usr/src/cmd/tbl/t5.c
new file mode 100644 (file)
index 0000000..1cc245f
--- /dev/null
@@ -0,0 +1,166 @@
+ /* t5.c: read data for table */
+# include "t..c"
+gettbl()
+{
+int icol, ch;
+cstore=cspace= chspace();
+textflg=0;
+for (nlin=nslin=0; gets1(cstore); nlin++)
+       {
+       stynum[nlin]=nslin;
+       if (prefix(".TE", cstore))
+               {
+               leftover=0;
+               break;
+               }
+       if (prefix(".TC", cstore) || prefix(".T&", cstore))
+               {
+               readspec();
+               nslin++;
+               }
+       if (nlin>=MAXLIN)
+               {
+               leftover=cstore;
+               break;
+               }
+       fullbot[nlin]=0;
+       if (cstore[0] == '.' && !isdigit(cstore[1]))
+               {
+               instead[nlin] = cstore;
+               while (*cstore++);
+               continue;
+               }
+       else instead[nlin] = 0;
+       if (nodata(nlin))
+               {
+               if (ch = oneh(nlin))
+                       fullbot[nlin]= ch;
+               nlin++;
+               nslin++;
+               instead[nlin]=fullbot[nlin]=0;
+               }
+       table[nlin] = alocv((ncol+2)*sizeof(table[0][0]));
+       if (cstore[1]==0)
+       switch(cstore[0])
+               {
+               case '_': fullbot[nlin]= '-'; continue;
+               case '=': fullbot[nlin]= '='; continue;
+               }
+       stynum[nlin] = nslin;
+       nslin = min(nslin+1, nclin-1);
+       for (icol = 0; icol <ncol; icol++)
+               {
+               table[nlin][icol].col = cstore;
+               table[nlin][icol].rcol=0;
+               ch=1;
+               if (match(cstore, "T{")) /* text follows */
+                       table[nlin][icol].col =
+                               gettext(cstore, nlin, icol,
+                                       font[stynum[nlin]][icol],
+                                       csize[stynum[nlin]][icol]);
+               else
+                       {
+                       for(; (ch= *cstore) != '\0' && ch != tab; cstore++)
+                                       ;
+                       *cstore++ = '\0';
+                       switch(ctype(nlin,icol)) /* numerical or alpha, subcol */
+                               {
+                               case 'n':
+                                       table[nlin][icol].rcol = maknew(table[nlin][icol].col);
+                                       break;
+                               case 'a':
+                                       table[nlin][icol].rcol = table[nlin][icol].col;
+                                       table[nlin][icol].col = "";
+                                       break;
+                               }
+                       }
+               while (ctype(nlin,icol+1)== 's') /* spanning */
+                       table[nlin][++icol].col = "";
+               if (ch == '\0') break;
+               }
+       while (++icol <ncol+2)
+               {
+               table[nlin][icol].col = "";
+               table [nlin][icol].rcol=0;
+               }
+       while (*cstore != '\0')
+                cstore++;
+       if (cstore-cspace > MAXCHS)
+               cstore = cspace = chspace();
+       }
+last = cstore;
+permute();
+if (textflg) untext();
+return;
+}
+nodata(il)
+{
+int c;
+for (c=0; c<ncol;c++)
+       {
+       switch(ctype(il,c))
+               {
+               case 'c': case 'n': case 'r': case 'l': case 's': case 'a':
+                       return(0);
+               }
+       }
+return(1);
+}
+oneh(lin)
+{
+int k, icol;
+k = ctype(lin,0);
+for(icol=1; icol<ncol; icol++)
+       {
+       if (k != ctype(lin,icol))
+               return(0);
+       }
+return(k);
+}
+# define SPAN "\\^"
+permute()
+{
+int irow, jcol, is;
+char *start, *strig;
+for(jcol=0; jcol<ncol; jcol++)
+       {
+       for(irow=1; irow<nlin; irow++)
+               {
+               if (vspand(irow,jcol,0))
+                       {
+                       is = prev(irow);
+                       if (is<0)
+                               error("Vertical spanning in first row not allowed");
+                       start = table[is][jcol].col;
+                       strig = table[is][jcol].rcol;
+                       while (irow<nlin &&vspand(irow,jcol,0))
+                               irow++;
+                       table[--irow][jcol].col = start;
+                       table[irow][jcol].rcol = strig;
+                       while (is<irow)
+                               {
+                               table[is][jcol].rcol =0;
+                               table[is][jcol].col= SPAN;
+                               is = next(is);
+                               }
+                       }
+               }
+       }
+}
+vspand(ir,ij,ifform)
+{
+if (ir<0) return(0);
+if (ir>=nlin)return(0);
+if (instead[ir]) return(0);
+if (ifform==0 && ctype(ir,ij)=='^') return(1);
+if (table[ir][ij].rcol!=0) return(0);
+if (fullbot[ir]) return(0);
+return(vspen(table[ir][ij].col));
+}
+vspen(s)
+       char *s;
+{
+if (s==0) return(0);
+if (!point(s)) return(0);
+return(match(s, SPAN));
+}
diff --git a/usr/src/cmd/tbl/t6.c b/usr/src/cmd/tbl/t6.c
new file mode 100644 (file)
index 0000000..3909b98
--- /dev/null
@@ -0,0 +1,202 @@
+ /* t6.c: compute tab stops */
+# define tx(a) (a>0 && a<128)
+# include "t..c"
+maktab()
+{
+# define FN(i,c) font[stynum[i]][c]
+# define SZ(i,c) csize[stynum[i]][c]
+/* define the tab stops of the table */
+int icol, ilin, tsep, k, ik, vforml, il, text;
+int doubled[MAXCOL], acase[MAXCOL];
+char *s;
+for(icol=0; icol <ncol; icol++)
+       {
+       doubled[icol] = acase[icol] = 0;
+       fprintf(tabout, ".nr %d 0\n", icol+CRIGHT);
+   for(text=0; text<2; text++)
+       {
+       if (text)
+               fprintf(tabout, ".%02d\n.rm %02d\n", icol+80, icol+80);
+       for(ilin=0; ilin<nlin; ilin++)
+               {
+               if (instead[ilin]|| fullbot[ilin]) continue;
+               vforml=ilin;
+               for(il=prev(ilin); il>=0 && vspen(table[il][icol].col); il=prev(il))
+                       vforml=il;
+               if (fspan(vforml,icol)) continue;
+               if (filler(table[ilin][icol].col)) continue;
+               switch(ctype(vforml,icol))
+                       {
+                       case 'a':
+                               acase[icol]=1;
+                               s = table[ilin][icol].col;
+                               if (s>0 && s<128 && text)
+                                       {
+                                       if (doubled[icol]==0)
+                                               fprintf(tabout, ".nr %d 0\n.nr %d 0\n",S1,S2);
+                                       doubled[icol]=1;
+                                       fprintf(tabout, ".if \\n(%c->\\n(%d .nr %d \\n(%c-\n",s,S2,S2,s);
+                                       }
+                       case 'n':
+                               if (table[ilin][icol].rcol!=0)
+                                       {
+                                       if (doubled[icol]==0 && text==0)
+                                               fprintf(tabout, ".nr %d 0\n.nr %d 0\n", S1, S2);
+                                       doubled[icol]=1;
+                                       if (real(s=table[ilin][icol].col) && !vspen(s))
+                                               {
+                                               if (tx(s) != text) continue;
+                                               fprintf(tabout, ".nr %d ", TMP);
+                                               wide(s, FN(vforml,icol), SZ(vforml,icol)); fprintf(tabout, "\n");
+                                               fprintf(tabout, ".if \\n(%d<\\n(%d .nr %d \\n(%d\n", S1, TMP, S1, TMP);
+                                               }
+                                       if (text==0 && real(s=table[ilin][icol].rcol) && !vspen(s) && !barent(s))
+                                               {
+                                               fprintf(tabout, ".nr %d \\w%c%s%c\n",TMP, F1, s, F1);
+                                               fprintf(tabout, ".if \\n(%d<\\n(%d .nr %d \\n(%d\n",S2,TMP,S2,TMP);
+                                               }
+                                       continue;
+                                       }
+                       case 'r':
+                       case 'c':
+                       case 'l':
+                               if (real(s=table[ilin][icol].col) && !vspen(s))
+                                       {
+                                       if (tx(s) != text) continue;
+                                       fprintf(tabout, ".nr %d ", TMP);
+                                       wide(s, FN(vforml,icol), SZ(vforml,icol)); fprintf(tabout, "\n");
+                                       fprintf(tabout, ".if \\n(%d<\\n(%d .nr %d \\n(%d\n", icol+CRIGHT, TMP, icol+CRIGHT, TMP);
+                                       }
+                       }
+               }
+               }
+       if (acase[icol])
+               {
+               fprintf(tabout, ".if \\n(%d>=\\n(%d .nr %d \\n(%du+2n\n",S2,icol+CRIGHT,icol+CRIGHT,S2);
+               }
+       if (doubled[icol])
+               {
+               fprintf(tabout, ".nr %d \\n(%d\n", icol+CMID, S1);
+               fprintf(tabout, ".nr %d \\n(%d+\\n(%d\n",TMP,icol+CMID,S2);
+               fprintf(tabout, ".if \\n(%d>\\n(%d .nr %d \\n(%d\n",TMP,icol+CRIGHT,icol+CRIGHT,TMP);
+               fprintf(tabout, ".if \\n(%d<\\n(%d .nr %d +(\\n(%d-\\n(%d)/2\n",TMP,icol+CRIGHT,icol+CMID,icol+CRIGHT,TMP);
+               }
+       if (cll[icol][0])
+               {
+               fprintf(tabout, ".nr %d %sn\n", TMP, cll[icol]);
+               fprintf(tabout, ".if \\n(%d<\\n(%d .nr %d \\n(%d\n",icol+CRIGHT, TMP, icol+CRIGHT, TMP);
+               }
+       for(ilin=0; ilin<nlin; ilin++)
+       if (k=lspan(ilin, icol))
+               {
+               s=table[ilin][icol-k].col;
+               if (!real(s) || barent(s) || vspen(s) ) continue;
+               fprintf(tabout, ".nr %d ", TMP);
+               wide(table[ilin][icol-k].col, FN(ilin,icol-k), SZ(ilin,icol-k));
+               for(ik=k; ik>=0; ik--)
+                       {
+                       fprintf(tabout, "-\\n(%d",CRIGHT+icol-ik);
+                       if (!expflg && ik>0) fprintf(tabout, "-%dn", sep[icol-ik]);
+                       }
+               fprintf(tabout, "\n");
+               fprintf(tabout, ".if \\n(%d>0 .nr %d \\n(%d/%d\n", TMP, TMP, TMP, k);
+               fprintf(tabout, ".if \\n(%d<0 .nr %d 0\n", TMP, TMP);
+               for(ik=1; ik<=k; ik++)
+                       {
+                       if (doubled[icol-k+ik])
+                               fprintf(tabout, ".nr %d +\\n(%d/2\n", icol-k+ik+CMID, TMP);
+                       fprintf(tabout, ".nr %d +\\n(%d\n", icol-k+ik+CRIGHT, TMP);
+                       }
+               }
+       }
+if (textflg) untext();
+/* if even requested, make all columns widest width */
+# define TMP1 S1
+# define TMP2 S2
+if (evenflg)
+       {
+       fprintf(tabout, ".nr %d 0\n", TMP);
+       for(icol=0; icol<ncol; icol++)
+               {
+               if (evenup[icol]==0) continue;
+               fprintf(tabout, ".if \\n(%d>\\n(%d .nr %d \\n(%d\n",
+               icol+CRIGHT, TMP, TMP, icol+CRIGHT);
+               }
+       for(icol=0; icol<ncol; icol++)
+               {
+               if (evenup[icol]==0)
+                       /* if column not evened just retain old interval */
+                       continue;
+               if (doubled[icol])
+                       fprintf(tabout, ".nr %d (100*\\n(%d/\\n(%d)*\\n(%d/100\n",
+                               icol+CMID, icol+CMID, icol+CRIGHT, TMP);
+                               /* that nonsense with the 100's and parens tries
+                                  to avoid overflow while proportionally shifting
+                                  the middle of the number */
+               fprintf(tabout, ".nr %d \\n(%d\n", icol+CRIGHT, TMP);
+               }
+       }
+/* now adjust for total table width */
+for(tsep=icol=0; icol<ncol; icol++)
+       tsep+= sep[icol];
+if (expflg)
+       {
+       fprintf(tabout, ".nr %d 0", TMP);
+       for(icol=0; icol<ncol; icol++)
+               fprintf(tabout, "+\\n(%d", icol+CRIGHT);
+       fprintf(tabout, "\n");
+       fprintf(tabout, ".nr %d \\n(.l-\\n(%d\n", TMP, TMP);
+       if (boxflg || dboxflg || allflg)
+               tsep += 1;
+       else
+               tsep -= sep[ncol-1];
+       fprintf(tabout, ".nr %d \\n(%d/%d\n", TMP, TMP,  tsep);
+       fprintf(tabout, ".if \\n(%d<0 .nr %d 0\n", TMP, TMP);
+       }
+else
+       fprintf(tabout, ".nr %d 1n\n", TMP);
+fprintf(tabout, ".nr %d 0\n",CRIGHT-1);
+tsep= (boxflg || allflg || dboxflg || left1flg) ? 1 : 0;
+for(icol=0; icol<ncol; icol++)
+       {
+       fprintf(tabout, ".nr %d \\n(%d+(%d*\\n(%d)\n",icol+CLEFT, icol+CRIGHT-1, tsep, TMP);
+       fprintf(tabout, ".nr %d +\\n(%d\n",icol+CRIGHT, icol+CLEFT);
+       if (doubled[icol])
+               {
+               /* the next line is last-ditch effort to avoid zero field width */
+               /*fprintf(tabout, ".if \\n(%d=0 .nr %d 1\n",icol+CMID, icol+CMID);*/
+               fprintf(tabout, ".nr %d +\\n(%d\n", icol+CMID, icol+CLEFT);
+       /*  fprintf(tabout, ".if n .if \\n(%d%%24>0 .nr %d +12u\n",icol+CMID, icol+CMID); */
+               }
+       tsep=sep[icol];
+       }
+if (rightl)
+       fprintf(tabout, ".nr %d (\\n(%d+\\n(%d)/2\n",ncol+CRIGHT-1, ncol+CLEFT-1, ncol+CRIGHT-2);
+fprintf(tabout, ".nr TW \\n(%d\n", ncol+CRIGHT-1);
+if (boxflg || allflg || dboxflg)
+       fprintf(tabout, ".nr TW +%d*\\n(%d\n", sep[ncol-1], TMP);
+fprintf(tabout,
+ ".if t .if (\\n(TW+\\n(.o)>7.65i .tm Table at line %d file %s is too wide - \\n(TW units\n", iline-1, ifile);
+return;
+}
+wide(s, fn, size)
+       char *s, *size, *fn;
+{
+if (point(s))
+       {
+       fprintf(tabout, "\\w%c", F1);
+       if (*fn>0) putfont(fn);
+       if (*size) putsize(size);
+       fprintf(tabout, "%s", s);
+       if (*fn>0) putfont("P");
+       if (*size) putsize("0");
+       fprintf(tabout, "%c",F1);
+       }
+else
+       fprintf(tabout, "\\n(%c-", s);
+}
+filler(s)
+       char *s;
+{
+return (point(s) && s[0]=='\\' && s[1] == 'R');
+}
diff --git a/usr/src/cmd/tbl/t7.c b/usr/src/cmd/tbl/t7.c
new file mode 100644 (file)
index 0000000..40bb471
--- /dev/null
@@ -0,0 +1,131 @@
+ /* t7.c: control to write table entries */
+# include "t..c"
+# define realsplit ((ct=='a'||ct=='n') && table[ldata][c].rcol)
+runout()
+{
+int i;
+if (boxflg || allflg || dboxflg) need();
+if (ctrflg)
+       {
+       fprintf(tabout, ".nr #I \\n(.i\n");
+       fprintf(tabout, ".in +(\\n(.lu-\\n(TWu-\\n(.iu)/2u\n");
+       }
+fprintf(tabout, ".fc %c %c\n", F1, F2);
+fprintf(tabout, ".nr #T 0-1\n");
+deftail();
+for(i=0; i<nlin; i++)
+       putline(i,i);
+if (leftover)
+       yetmore();
+fprintf(tabout, ".fc\n");
+fprintf(tabout, ".nr T. 1\n");
+fprintf(tabout, ".T# 1\n");
+if (ctrflg)
+       fprintf(tabout, ".in \\n(#Iu\n");
+}
+runtabs(lform, ldata)
+{
+int c, ct, vforml, lf;
+fprintf(tabout, ".ta ");
+for(c=0; c<ncol; c++)
+       {
+       vforml=lform;
+       for(lf=prev(lform); lf>=0 && vspen(table[lf][c].col); lf=prev(lf))
+               vforml=lf;
+       if (fspan(vforml,c))
+               continue;
+       switch(ct=ctype(vforml,c))
+               {
+               case 'n':
+               case 'a':
+                       if (table[ldata][c].rcol)
+                         if (lused[c]) /*Zero field width*/
+                               fprintf(tabout, "\\n(%du ",c+CMID);
+               case 'c':
+               case 'l':
+               case 'r':
+                   if (realsplit? rused[c]: (used[c]+lused[c]))
+                       fprintf(tabout, "\\n(%du ",c+CRIGHT);
+                       continue;
+               case 's':
+                       if (lspan(lform, c))
+                               fprintf(tabout, "\\n(%du ", c+CRIGHT);
+                       continue;
+               }
+       }
+fprintf(tabout, "\n");
+}
+ifline(s)
+       char *s;
+{
+if (s[0] == '\\') s++;
+if (s[1] ) return(0);
+if (s[0] == '_') return('-');
+if (s[0] == '=') return('=');
+return(0);
+}
+need()
+{
+int texlin, horlin, i;
+for(texlin=horlin=i=0; i<nlin; i++)
+       {
+       if (fullbot[i]!=0)
+               horlin++;
+       else
+       if (instead[i]!=0)
+               continue;
+       else
+               texlin++;
+       }
+fprintf(tabout, ".ne %dv+%dp\n",texlin,2*horlin);
+}
+deftail()
+{
+int i, c, lf, lwid;
+for(i=0; i<MAXHEAD; i++)
+       if (linestop[i])
+               fprintf(tabout, ".nr #%c 0-1\n", linestop[i]+'a'-1);
+fprintf(tabout, ".nr #a 0-1\n");
+fprintf(tabout, ".eo\n");
+fprintf(tabout, ".de T#\n");
+fprintf(tabout, ".ds #d .d\n");
+fprintf(tabout, ".if \\(ts\\n(.z\\(ts\\(ts .ds #d nl\n");
+       fprintf(tabout, ".mk ##\n");
+       fprintf(tabout, ".nr ## -1v\n");
+       fprintf(tabout, ".ls 1\n");
+       for(i=0; i<MAXHEAD; i++)
+               if (linestop[i])
+                       fprintf(tabout, ".if \\n(#T>=0 .nr #%c \\n(#T\n",linestop[i]+'a'-1);
+if (boxflg || allflg || dboxflg) /* bottom of table line */
+       if (fullbot[nlin-1]==0)
+               {
+               if (!pr1403)
+                       fprintf(tabout, ".if \\n(T. .vs \\n(.vu-\\n(.sp\n");
+               fprintf(tabout, ".if \\n(T. ");
+               drawline(nlin,0,ncol, dboxflg ? '=' : '-',1,0);
+               fprintf(tabout, "\n.if \\n(T. .vs\n");
+               /* T. is really an argument to a macro but because of 
+                  eqn we don't dare pass it as an argument and reference by $1 */
+               }
+       for(c=0; c<ncol; c++)
+               {
+               if ((lf=left(nlin-1,c, &lwid))>=0)
+                       {
+                       fprintf(tabout, ".if \\n(#%c>=0 .sp -1\n",linestop[lf]+'a'-1);
+                       fprintf(tabout, ".if \\n(#%c>=0 ", linestop[lf]+'a'-1);
+                       tohcol(c);
+                       drawvert(lf, nlin-1, c, lwid);
+                       fprintf(tabout, "\\h'|\\n(TWu'\n");
+                       }
+               }
+       if (boxflg || allflg || dboxflg) /* right hand line */
+               {
+               fprintf(tabout, ".if \\n(#a>=0 .sp -1\n");
+               fprintf(tabout, ".if \\n(#a>=0 \\h'|\\n(TWu'");
+               drawvert (0, nlin-1, ncol, dboxflg? 2 : 1);
+               fprintf(tabout, "\n");
+               }
+fprintf(tabout, ".ls\n");
+fprintf(tabout, "..\n");
+fprintf(tabout, ".ec\n");
+}
diff --git a/usr/src/cmd/tbl/t8.c b/usr/src/cmd/tbl/t8.c
new file mode 100644 (file)
index 0000000..e868dd8
--- /dev/null
@@ -0,0 +1,327 @@
+ /* t8.c: write out one line of output table */
+# include "t..c"
+# define realsplit ((ct=='a'||ct=='n') && table[nl][c].rcol)
+int watchout;
+int once;
+int topat[MAXCOL];
+putline(i, nl)
+       /* i is line number for deciding format */
+       /* nl is line number for finding data   usually identical */
+{
+int c, lf, ct, form, lwid, vspf, ip, cmidx, exvspen, vforml;
+int vct, chfont;
+char *s, *size, *fn;
+watchout=vspf=exvspen=0;
+if (i==0) once=0;
+if (i==0 && ( allflg || boxflg || dboxflg))
+       fullwide(0,   dboxflg? '=' : '-');
+if (instead[nl]==0 && fullbot[nl] ==0)
+for(c=0; c<ncol; c++)
+       {
+       s = table[nl][c].col;
+       if (s==0) continue;
+       if (vspen(s))
+               {
+               for(ip=nl; ip<nlin; ip=next(ip))
+                       if (!vspen(s=table[ip][c].col)) break;
+               if (s>0 && s<128)
+               fprintf(tabout, ".ne \\n(%c|u+\\n(.Vu\n",s);
+               continue;
+               }
+       if (point(s)) continue;
+       fprintf(tabout, ".ne \\n(%c|u+\\n(.Vu\n",s);
+       watchout=1;
+       }
+if (linestop[nl])
+       fprintf(tabout, ".mk #%c\n", linestop[nl]+'a'-1);
+lf = prev(nl);
+if (instead[nl])
+       {
+       puts(instead[nl]);
+       return;
+       }
+if (fullbot[nl])
+       {
+       switch (ct=fullbot[nl])
+               {
+               case '=':
+               case '-':
+                       fullwide(nl,ct);
+               }
+       return;
+       }
+for(c=0; c<ncol; c++)
+       {
+       if (instead[nl]==0 && fullbot[nl]==0)
+       if (vspen(table[nl][c].col)) vspf=1;
+       if (lf>=0)
+               if (vspen(table[lf][c].col)) vspf=1;
+       }
+if (vspf)
+       {
+       fprintf(tabout, ".nr #^ \\n(\\*(#du\n");
+       fprintf(tabout, ".nr #- \\n(#^\n"); /* current line position relative to bottom */
+       }
+vspf=0;
+chfont=0;
+for(c=0; c<ncol; c++)
+       {
+       s = table[nl][c].col;
+       if (s==0) continue;
+       chfont |= (int)(font[stynum[nl]][c]);
+       if (point(s) ) continue;
+       lf=prev(nl);
+       if (lf>=0 && vspen(table[lf][c].col))
+               fprintf(tabout, ".if (\\n(%c|+\\n(^%c-1v)>\\n(#- .nr #- +(\\n(%c|+\\n(^%c-\\n(#--1v)\n",s,'a'+c,s,'a'+c);
+       else
+               fprintf(tabout, ".if (\\n(%c|+\\n(#^-1v)>\\n(#- .nr #- +(\\n(%c|+\\n(#^-\\n(#--1v)\n",s,s);
+       }
+if (allflg && once>0 )
+       fullwide(i,'-');
+once=1;
+runtabs(i, nl);
+if (allh(i) && !pr1403)
+       {
+       fprintf(tabout, ".nr %d \\n(.v\n", SVS);
+       fprintf(tabout, ".vs \\n(.vu-\\n(.sp\n");
+       }
+if (chfont)
+       fprintf(tabout, ".nr %2d \\n(.f\n", S1);
+fprintf(tabout, ".nr 35 1m\n");
+fprintf(tabout, "\\&");
+vct = 0;
+for(c=0; c<ncol; c++)
+       {
+       if (watchout==0 && i+1<nlin && (lf=left(i,c, &lwid))>=0)
+               {
+               tohcol(c);
+               drawvert(lf, i, c, lwid);
+               vct += 2;
+               }
+       if (rightl && c+1==ncol) continue;
+       vforml=i;
+       for(lf=prev(nl); lf>=0 && vspen(table[lf][c].col); lf=prev(lf))
+               vforml= lf;
+       form= ctype(vforml,c);
+       if (form != 's')
+               {
+               ct = c+CLEFT;
+               if (form=='a') ct = c+CMID;
+               if (form=='n' && table[nl][c].rcol && lused[c]==0) ct= c+CMID;
+               fprintf(tabout, "\\h'|\\n(%du'", ct);
+               }
+       s= table[nl][c].col;
+       fn = font[stynum[vforml]][c];
+       size = csize[stynum[vforml]][c];
+       if (*size==0)size=0;
+       switch(ct=ctype(vforml, c))
+               {
+               case 'n':
+               case 'a':
+                       if (table[nl][c].rcol)
+                               {
+                          if (lused[c]) /*Zero field width*/
+                               {
+                               ip = prev(nl);
+                               if (ip>=0)
+                               if (vspen(table[ip][c].col))
+                                       {
+                                       if (exvspen==0)
+                                               {
+                                               fprintf(tabout, "\\v'-(\\n(\\*(#du-\\n(^%cu", c+'a');
+                                               if (cmidx)
+                                                       fprintf(tabout, "-((\\n(#-u-\\n(^%cu)/2u)", c+'a');
+                                               vct++;
+                                               fprintf(tabout, "'");
+                                               exvspen=1;
+                                               }
+                                       }
+                               fprintf(tabout, "%c%c",F1,F2);
+                               puttext(s,fn,size);
+                               fprintf(tabout, "%c",F1);
+                               }
+                               s= table[nl][c].rcol;
+                               form=1;
+                               break;
+                               }
+               case 'c':
+                       form=3; break;
+               case 'r':
+                       form=2; break;
+               case 'l':
+                       form=1; break;
+               case '-':
+               case '=':
+                       if (real(table[nl][c].col))
+                               fprintf(stderr,"%s: line %d: Data ignored on table line %d\n", ifile, iline-1, i+1);
+                       makeline(i,c,ct);
+                       continue;
+               default:
+                       continue;
+               }
+       if (realsplit ? rused[c]: used[c]) /*Zero field width*/
+               {
+               /* form: 1 left, 2 right, 3 center adjust */
+               if (ifline(s))
+                       {
+                       makeline(i,c,ifline(s));
+                       continue;
+                       }
+               if (filler(s))
+                       {
+                       printf("\\l'|\\n(%du\\&%s'", c+CRIGHT, s+2);
+                       continue;
+                       }
+               ip = prev(nl);
+               cmidx = ctop[stynum[nl]][c]==0;
+               if (ip>=0)
+               if (vspen(table[ip][c].col))
+                       {
+                       if (exvspen==0)
+                               {
+                               fprintf(tabout, "\\v'-(\\n(\\*(#du-\\n(^%cu", c+'a');
+                               if (cmidx)
+                                       fprintf(tabout, "-((\\n(#-u-\\n(^%cu)/2u)", c+'a');
+                               vct++;
+                               fprintf(tabout, "'");
+                               }
+                       }
+               fprintf(tabout, "%c", F1);
+               if (form!= 1)
+                       fprintf(tabout, "%c", F2);
+               if (vspen(s))
+                       vspf=1;
+               else
+               puttext(s, fn, size);
+               if (form !=2)
+                       fprintf(tabout, "%c", F2);
+               fprintf(tabout, "%c", F1);
+               }
+       if (ip>=0)
+       if (vspen(table[ip][c].col))
+               {
+               exvspen = (c+1 < ncol) && vspen(table[ip][c+1].col) &&
+                       (topat[c] == topat[c+1]) &&
+                       (cmidx == (ctop [stynum[nl]][c+1]==0)) && (left(i,c+1,&lwid)<0);
+               if (exvspen==0)
+                       {
+                       fprintf(tabout, "\\v'(\\n(\\*(#du-\\n(^%cu", c+'a');
+                       if (cmidx)
+                               fprintf(tabout, "-((\\n(#-u-\\n(^%cu)/2u)", c+'a');
+                       vct++;
+                       fprintf(tabout, "'");
+                       }
+               }
+       else
+               exvspen=0;
+       /* if lines need to be split for gcos here is the place for a backslash */
+       if (vct > 7 && c < ncol)
+               {
+               fprintf(tabout, "\n.sp-1\n\\&");
+               vct=0;
+               }
+       }
+fprintf(tabout, "\n");
+if (allh(i) && !pr1403) fprintf(tabout, ".vs \\n(%du\n", SVS);
+if (watchout)
+       funnies(i,nl);
+if (vspf)
+       {
+       for(c=0; c<ncol; c++)
+               if (vspen(table[nl][c].col) && (nl==0 || (lf=prev(nl))<0 || !vspen(table[lf][c].col)))
+                       {
+                       fprintf(tabout, ".nr ^%c \\n(#^u\n", 'a'+c);
+                       topat[c]=nl;
+                       }
+       }
+}
+puttext(s,fn, size)
+       char *s, *size, *fn;
+{
+if (point(s))
+       {
+       putfont(fn);
+       putsize(size);
+       fprintf(tabout, "%s",s);
+       if (*fn>0) fprintf(tabout, "\\f\\n(%2d", S1);
+       if (size!=0) putsize("0");
+       }
+}
+funnies( stl, lin)
+{
+/* write out funny diverted things */
+int c, s, pl, lwid, dv, lf, ct;
+char *fn;
+fprintf(tabout, ".mk ##\n"); /* rmember current vertical position */
+fprintf(tabout, ".nr %d \\n(##\n", S1); /* bottom position */
+for(c=0; c<ncol; c++)
+       {
+       s = table[lin][c].col;
+       if (point(s)) continue;
+       if (s==0) continue;
+       fprintf(tabout, ".sp |\\n(##u-1v\n");
+       fprintf(tabout, ".nr %d ", SIND);
+       for(pl=stl; pl>=0 && !isalpha(ct=ctype(pl,c)); pl=prev(pl))
+               ;
+       switch (ct)
+               {
+               case 'n':
+               case 'c':
+                       fprintf(tabout, "(\\n(%du+\\n(%du-\\n(%c-u)/2u\n",c+CLEFT,c-1+ctspan(lin,c)+CRIGHT, s);
+                       break;
+               case 'l':
+                       fprintf(tabout, "\\n(%du\n",c+CLEFT);
+                       break;
+               case 'a':
+                       fprintf(tabout, "\\n(%du\n",c+CMID);
+                       break;
+               case 'r':
+                       fprintf(tabout, "\\n(%du-\\n(%c-u\n", c+CRIGHT, s);
+                       break;
+               }
+       fprintf(tabout, ".in +\\n(%du\n", SIND);
+       fn=font[stynum[stl]][c];
+       putfont(fn);
+       pl = prev(stl);
+       if (stl>0 && pl>=0 && vspen(table[pl][c].col))
+               {
+               fprintf(tabout, ".sp |\\n(^%cu\n", 'a'+c);
+               if (ctop[stynum[stl]][c]==0)
+                       {
+                       fprintf(tabout, ".nr %d \\n(#-u-\\n(^%c-\\n(%c|+1v\n",TMP, 'a'+c, s);
+                       fprintf(tabout, ".if \\n(%d>0 .sp \\n(%du/2u\n", TMP, TMP);
+                       }
+               }
+       fprintf(tabout, ".%c+\n",s);
+       fprintf(tabout, ".in -\\n(%du\n", SIND);
+       if (*fn>0) putfont("P");
+       fprintf(tabout, ".mk %d\n", S2);
+       fprintf(tabout, ".if \\n(%d>\\n(%d .nr %d \\n(%d\n", S2, S1, S1, S2);
+       }
+fprintf(tabout, ".sp |\\n(%du\n", S1);
+for(c=dv=0; c<ncol; c++)
+       {
+       if (stl+1< nlin && (lf=left(stl,c,&lwid))>=0)
+               {
+               if (dv++ == 0)
+                       fprintf(tabout, ".sp -1\n");
+               tohcol(c);
+               dv++;
+               drawvert(lf, stl, c, lwid);
+               }
+       }
+if (dv)
+       fprintf(tabout,"\n");
+}
+putfont(fn)
+       char *fn;
+{
+if (fn && *fn)
+       fprintf(tabout,  fn[1] ? "\\f(%.2s" : "\\f%.2s",  fn);
+}
+putsize(s)
+       char *s;
+{
+if (s && *s)
+       fprintf(tabout, "\\s%s",s);
+}
diff --git a/usr/src/cmd/tbl/t9.c b/usr/src/cmd/tbl/t9.c
new file mode 100644 (file)
index 0000000..dda72ee
--- /dev/null
@@ -0,0 +1,62 @@
+ /* t9.c: write lines for tables over 200 lines */
+# include "t..c"
+static useln;
+yetmore()
+{
+for(useln=0; useln<MAXLIN && table[useln]==0; useln++);
+if (useln>=MAXLIN)
+       error("Wierd.  No data in table.");
+table[0]=table[useln];
+for(useln=nlin-1; useln>=0 && (fullbot[useln] || instead[useln]); useln--);
+if (useln<0)
+       error("Wierd.  No real lines in table.");
+domore(leftover);
+while (gets1(cstore=cspace) && domore(cstore))
+       ;
+last =cstore;
+return;
+}
+domore(dataln)
+       char *dataln;
+{
+       int icol, ch;
+if (prefix(".TE", dataln))
+       return(0);
+if (dataln[0] == '.' && !isdigit(dataln[1]))
+       {
+       puts(dataln);
+       return(1);
+       }
+instead[0]=fullbot[0]=0;
+if (dataln[1]==0)
+switch(dataln[0])
+       {
+       case '_': fullbot[0]= '-'; putline(useln,0);  return(1);
+       case '=': fullbot[0]= '='; putline(useln, 0); return(1);
+       }
+for (icol = 0; icol <ncol; icol++)
+       {
+       table[0][icol].col = dataln;
+       table[0][icol].rcol=0;
+       for(; (ch= *dataln) != '\0' && ch != tab; dataln++)
+                       ;
+       *dataln++ = '\0';
+       switch(ctype(useln,icol))
+               {
+               case 'n':
+                       table[0][icol].rcol = maknew(table[0][icol].col);
+                       break;
+               case 'a':
+                       table[0][icol].rcol = table[0][icol].col;
+                       table[0][icol].col= "";
+                       break;
+               }
+       while (ctype(useln,icol+1)== 's') /* spanning */
+               table[0][++icol].col = "";
+       if (ch == '\0') break;
+       }
+while (++icol <ncol)
+       table[0][icol].col = "";
+putline(useln,0);
+return(1);
+}
diff --git a/usr/src/cmd/tbl/tb.c b/usr/src/cmd/tbl/tb.c
new file mode 100644 (file)
index 0000000..0a68bda
--- /dev/null
@@ -0,0 +1,82 @@
+ /* tb.c: check which entries exist, also storage allocation */
+# include "t..c"
+checkuse()
+{
+int i,c, k;
+for(c=0; c<ncol; c++)
+       {
+       used[c]=lused[c]=rused[c]=0;
+       for(i=0; i<nlin; i++)
+               {
+               if (instead[i] || fullbot[i]) continue;
+               k = ctype(i,c);
+               if (k== '-' || k == '=') continue;
+               if ((k=='n'||k=='a'))
+                       {
+                       rused[c]|= real(table[i][c].rcol);
+                       if( !real(table[i][c].rcol))
+                       used[c] |= real(table[i][c].col);
+                       if (table[i][c].rcol)
+                       lused[c] |= real(table[i][c].col);
+                       }
+               else
+                       used[c] |= real(table[i][c].col);
+               }
+       }
+}
+real(s)
+       char *s;
+{
+if (s==0) return(0);
+if (!point(s)) return(1);
+if (*s==0) return(0);
+return(1);
+}
+int spcount = 0;
+extern char * calloc();
+# define MAXVEC 20
+char *spvecs[MAXVEC];
+chspace()
+{
+char *pp;
+if (spvecs[spcount])
+       return(spvecs[spcount++]);
+if (spcount>=MAXVEC)
+       error("Too many characters in table");
+spvecs[spcount++]= pp = calloc(MAXCHS+200,1);
+if (pp== -1 || pp == 0)
+       error("no space for characters");
+return(pp);
+}
+# define MAXPC 50
+char *thisvec;
+int tpcount = -1;
+char *tpvecs[MAXPC];
+alocv(n)
+{
+int *tp, *q;
+if (tpcount<0 || thisvec+n > tpvecs[tpcount]+MAXCHS)
+       {
+       tpcount++;
+       if (tpvecs[tpcount]==0)
+               {
+               tpvecs[tpcount] = calloc(MAXCHS,1);
+               }
+       thisvec = tpvecs[tpcount];
+       if (thisvec == -1)
+               error("no space for vectors");
+       }
+tp=thisvec;
+thisvec+=n;
+for(q=tp; q<thisvec; q++)
+       *q=0;
+return(tp);
+}
+release()
+{
+extern char *exstore;
+/* give back unwanted space in some vectors */
+spcount=0;
+tpcount= -1;
+exstore=0;
+}
diff --git a/usr/src/cmd/tbl/tc.c b/usr/src/cmd/tbl/tc.c
new file mode 100644 (file)
index 0000000..3c267c6
--- /dev/null
@@ -0,0 +1,60 @@
+ /* tc.c: find character not in table to delimit fields */
+# include "t..c"
+choochar()
+{
+/* choose funny characters to delimit fields */
+int had[128], ilin,icol, k;
+char *s;
+for(icol=0; icol<128; icol++)
+       had[icol]=0;
+F1 = F2 = 0;
+for(ilin=0;ilin<nlin;ilin++)
+       {
+       if (instead[ilin]) continue;
+       if (fullbot[ilin]) continue;
+       for(icol=0; icol<ncol; icol++)
+               {
+               k = ctype(ilin, icol);
+               if (k==0 || k == '-' || k == '=')
+                       continue;
+               s = table[ilin][icol].col;
+               if (point(s))
+               while (*s)
+                       had[*s++]=1;
+               s=table[ilin][icol].rcol;
+               if (point(s))
+               while (*s)
+                       had[*s++]=1;
+               }
+       }
+/* choose first funny character */
+for(
+       s="\002\003\005\006\007!%&#/?,:;<=>@`^~_{}+-*ABCDEFGHIJKMNOPQRSTUVWXYZabcdefgjkoqrstwxyz";
+               *s; s++)
+       {
+       if (had[*s]==0)
+               {
+               F1= *s;
+               had[F1]=1;
+               break;
+               }
+       }
+/* choose second funny character */
+for(
+       s="\002\003\005\006\007:_~^`@;,<=>#%&!/?{}+-*ABCDEFGHIJKMNOPQRSTUVWXZabcdefgjkoqrstuwxyz";
+               *s; s++)
+       {
+       if (had[*s]==0)
+               {
+               F2= *s;
+               break;
+               }
+       }
+if (F1==0 || F2==0)
+       error("couldn't find characters to use for delimiters");
+return;
+}
+point(s)
+{
+return(s>= 128 || s<0);
+}
diff --git a/usr/src/cmd/tbl/tf.c b/usr/src/cmd/tbl/tf.c
new file mode 100644 (file)
index 0000000..e65a632
--- /dev/null
@@ -0,0 +1,51 @@
+ /* tf.c: save and restore fill mode around table */
+# include "t..c"
+savefill()
+{
+/* remembers various things: fill mode, vs, ps in mac 35 (SF) */
+fprintf(tabout, ".de %d\n",SF);
+fprintf(tabout, ".ps \\n(.s\n");
+fprintf(tabout, ".vs \\n(.vu\n");
+fprintf(tabout, ".in \\n(.iu\n");
+fprintf(tabout, ".if \\n(.u .fi\n");
+fprintf(tabout, ".if \\n(.j .ad\n");
+fprintf(tabout, ".if \\n(.j=0 .na\n");
+fprintf(tabout, "..\n");
+fprintf(tabout, ".nf\n");
+/* set obx offset if useful */
+fprintf(tabout, ".nr #~ 0\n");
+fprintf(tabout, ".if n .nr #~ 0.6n\n");
+}
+rstofill()
+{
+fprintf(tabout, ".%d\n",SF);
+}
+endoff()
+{
+int i;
+       for(i=0; i<MAXHEAD; i++)
+               if (linestop[i])
+                       fprintf(tabout, ".nr #%c 0\n", 'a'+i);
+       for(i=0; i<texct; i++)
+               fprintf(tabout, ".rm %c+\n",texstr[i]);
+fprintf(tabout, "%s\n", last);
+}
+ifdivert()
+{
+fprintf(tabout, ".ds #d .d\n");
+fprintf(tabout, ".if \\(ts\\n(.z\\(ts\\(ts .ds #d nl\n");
+}
+saveline()
+{
+fprintf(tabout, ".if \\n+(b.=1 .nr d. \\n(.c-\\n(c.-1\n");
+linstart=iline;
+}
+restline()
+{
+fprintf(tabout,".if \\n-(b.=0 .nr c. \\n(.c-\\n(d.-%d\n", iline-linstart);
+linstart = 0;
+}
+cleanfc()
+{
+fprintf(tabout, ".fc\n");
+}
diff --git a/usr/src/cmd/tbl/tg.c b/usr/src/cmd/tbl/tg.c
new file mode 100644 (file)
index 0000000..6673cb6
--- /dev/null
@@ -0,0 +1,69 @@
+ /* tg.c: process included text blocks */
+# include "t..c"
+gettext(sp, ilin,icol, fn, sz)
+       char *sp, *fn, *sz;
+{
+/* get a section of text */
+char line[256];
+int oname;
+char *vs;
+if (texname==0) error("Too many text block diversions");
+if (textflg==0)
+       {
+       fprintf(tabout, ".nr %d \\n(.lu\n", SL); /* remember old line length */
+       textflg=1;
+       }
+fprintf(tabout, ".eo\n");
+fprintf(tabout, ".am %02d\n", icol+80);
+fprintf(tabout, ".br\n");
+fprintf(tabout, ".di %c+\n", texname);
+rstofill();
+if (fn && *fn) fprintf(tabout, ".nr %d \\n(.f\n.ft %s\n", S1, fn);
+fprintf(tabout, ".ft \\n(.f\n"); /* protect font */
+vs = vsize[stynum[ilin]][icol];
+if ((sz && *sz) || (vs && *vs))
+       {
+       fprintf(tabout, ".nr %d \\n(.v\n", S2);
+       if (vs==0 || *vs==0) vs= "\\n(.s+2";
+       if (sz && *sz)
+               fprintf(tabout, ".ps %s\n",sz);
+       fprintf(tabout, ".vs %s\n",vs);
+       fprintf(tabout, ".if \\n(%du>\\n(.vu .sp \\n(%du-\\n(.vu\n", S2,S2);
+       }
+if (cll[icol][0])
+       fprintf(tabout, ".ll %sn\n", cll[icol]);
+else
+       fprintf(tabout, ".ll \\n(%du*%du/%du\n",SL,ctspan(ilin,icol),ncol+1);
+fprintf(tabout,".if \\n(.l<\\n(%d .ll \\n(%du\n", icol+CRIGHT, icol+CRIGHT);
+if (ctype(ilin,icol)=='a')
+       fprintf(tabout, ".ll -2n\n");
+fprintf(tabout, ".in 0\n");
+while (gets1(line))
+       {
+       if (line[0]=='T' && line[1]=='}' && line[2]== tab) break;
+       if (match("T}", line)) break;
+       fprintf(tabout, "%s\n", line);
+       }
+if (fn && *fn) fprintf(tabout, ".ft \\n(%d\n", S1);
+if (sz && *sz) fprintf(tabout, ".br\n.ps\n.vs\n");
+fprintf(tabout, ".br\n");
+fprintf(tabout, ".di\n");
+fprintf(tabout, ".nr %c| \\n(dn\n", texname);
+fprintf(tabout, ".nr %c- \\n(dl\n", texname);
+fprintf(tabout, "..\n");
+fprintf(tabout, ".ec \\\n");
+/* copy remainder of line */
+if (line[2])
+       tcopy (sp, line+3);
+else
+       *sp=0;
+oname=texname;
+texname = texstr[++texct];
+return(oname);
+}
+untext()
+{
+rstofill();
+fprintf(tabout, ".nf\n");
+fprintf(tabout, ".ll \\n(%du\n", SL);
+}
diff --git a/usr/src/cmd/tbl/ti.c b/usr/src/cmd/tbl/ti.c
new file mode 100644 (file)
index 0000000..5df0c3a
--- /dev/null
@@ -0,0 +1,56 @@
+ /* ti.c: classify line intersections */
+# include "t..c"
+/* determine local environment for intersections */
+interv(i,c)
+{
+int ku, kl;
+if (c>=ncol || c == 0)
+       {
+       if (dboxflg)
+               {
+               if (i==0) return(BOT);
+               if (i>=nlin) return(TOP);
+               return(THRU);
+               }
+       if (c>=ncol)
+               return(0);
+       }
+ku = i>0 ? lefdata(i-1,c) : 0;
+if (i+1 >= nlin)
+       kl=0;
+else
+kl = lefdata(allh(i) ? i+1 : i, c);
+if (ku==2 && kl==2) return(THRU);
+if (ku ==2) return(TOP);
+if (kl==BOT) return(2);
+return(0);
+}
+interh(i,c)
+{
+int kl, kr;
+if (fullbot[i]== '=' || (dboxflg && (i==0 || i>= nlin-1)))
+       {
+       if (c==ncol)
+               return(LEFT);
+       if (c==0)
+               return(RIGHT);
+       return(THRU);
+       }
+if (i>=nlin) return(0);
+kl = c>0 ? thish (i,c-1) : 0;
+if (kl<=1 && i>0 && allh(up1(i)))
+       kl = c>0 ? thish(up1(i),c-1) : 0;
+kr = thish(i,c);
+if (kr<=1 && i>0 && allh(up1(i)))
+       kr = c>0 ? thish(up1(i), c) : 0;
+if (kl== '=' && kr ==  '=') return(THRU);
+if (kl== '=') return(LEFT);
+if (kr== '=') return(RIGHT);
+return(0);
+}
+up1(i)
+{
+i--;
+while (instead[i] && i>0) i--;
+return(i);
+}
diff --git a/usr/src/cmd/tbl/tm.c b/usr/src/cmd/tbl/tm.c
new file mode 100644 (file)
index 0000000..e9c0328
--- /dev/null
@@ -0,0 +1,63 @@
+ /* tm.c: split numerical fields */
+# include "t..c"
+maknew(str)
+       char *str;
+{
+       /* make two numerical fields */
+       int dpoint, c;
+       char *p, *q, *ba;
+       p = str;
+       for (ba= 0; c = *str; str++)
+               if (c == '\\' && *(str+1)== '&')
+                       ba=str;
+       str=p;
+       if (ba==0)
+               {
+               for (dpoint=0; *str; str++)
+                       {
+                       if (*str=='.' && !ineqn(str,p) &&
+                               (str>p && digit(*(str-1)) ||
+                               digit(*(str+1))))
+                                       dpoint=str;
+                       }
+               if (dpoint==0)
+                       for(; str>p; str--)
+                       {
+                       if (digit( * (str-1) ) && !ineqn(str, p))
+                               break;
+                       }
+               if (!dpoint && p==str) /* not numerical, don't split */
+                       return(0);
+               if (dpoint) str=dpoint;
+               }
+       else
+               str = ba;
+       p =str;
+       if (exstore ==0 || exstore >exlim)
+               {
+               exstore = chspace();
+               exlim= exstore+MAXCHS;
+               }
+       q = exstore;
+       while (*exstore++ = *str++);
+       *p = 0;
+       return(q);
+       }
+ineqn (s, p)
+       char *s, *p;
+{
+/* true if s is in a eqn within p */
+int ineq = 0, c;
+while (c = *p)
+       {
+       if (s == p)
+               return(ineq);
+       p++;
+       if ((ineq == 0) && (c == delim1))
+               ineq = 1;
+       else
+       if ((ineq == 1) && (c == delim2))
+               ineq = 0;
+       }
+return(0);
+}
diff --git a/usr/src/cmd/tbl/ts.c b/usr/src/cmd/tbl/ts.c
new file mode 100644 (file)
index 0000000..e0f8b1c
--- /dev/null
@@ -0,0 +1,49 @@
+ /* ts.c: minor string processing subroutines */
+match (s1, s2)
+       char *s1, *s2;
+{
+       while (*s1 == *s2)
+               if (*s1++ == '\0')
+                       return(1);
+               else
+                       s2++;
+       return(0);
+}
+prefix(small, big)
+       char *small, *big;
+{
+int c;
+while ((c= *small++) == *big++)
+       if (c==0) return(1);
+return(c==0);
+}
+letter (ch)
+       {
+       if (ch >= 'a' && ch <= 'z')
+               return(1);
+       if (ch >= 'A' && ch <= 'Z')
+               return(1);
+       return(0);
+       }
+numb(str)
+       char *str;
+       {
+       /* convert to integer */
+       int k;
+       for (k=0; *str >= '0' && *str <= '9'; str++)
+               k = k*10 + *str - '0';
+       return(k);
+       }
+digit(x)
+       {
+       return(x>= '0' && x<= '9');
+       }
+max(a,b)
+{
+return( a>b ? a : b);
+}
+tcopy (s,t)
+       char *s, *t;
+{
+       while (*s++ = *t++);
+}
diff --git a/usr/src/cmd/tbl/tt.c b/usr/src/cmd/tbl/tt.c
new file mode 100644 (file)
index 0000000..ae34556
--- /dev/null
@@ -0,0 +1,85 @@
+ /* tt.c: subroutines for drawing horizontal lines */
+# include "t..c"
+ctype(il, ic)
+{
+if (instead[il])
+       return(0);
+if (fullbot[il])
+       return(0);
+il = stynum[il];
+return(style[il][ic]);
+}
+min(a,b)
+{
+return(a<b ? a : b);
+}
+fspan(i,c)
+{
+c++;
+return(c<ncol && ctype(i,c)=='s');
+}
+lspan(i,c)
+{
+int k;
+if (ctype(i,c) != 's') return(0);
+c++;
+if (c < ncol && ctype(i,c)== 's') 
+       return(0);
+for(k=0; ctype(i,--c) == 's'; k++);
+return(k);
+}
+ctspan(i,c)
+{
+int k;
+c++;
+for(k=1; c<ncol && ctype(i,c)=='s'; k++)
+       c++;
+return(k);
+}
+tohcol(ic)
+{
+                       if (ic==0)
+                               fprintf(tabout, "\\h'|0'");
+                       else
+                               fprintf(tabout, "\\h'(|\\n(%du+|\\n(%du)/2u'", ic+CLEFT, ic+CRIGHT-1);
+}
+allh(i)
+{
+/* return true if every element in line i is horizontal */
+/* also at least one must be horizontl */
+int c, one, k;
+if (fullbot[i]) return(1);
+for(one=c=0; c<ncol; c++)
+       {
+       k = thish(i,c);
+       if (k==0) return(0);
+       if (k==1) continue;
+       one=1;
+       }
+return(one);
+}
+thish(i,c)
+{
+       int t;
+       char *s;
+       struct colstr *pc;
+       if (c<0)return(0);
+       if (i<0) return(0);
+       t = ctype(i,c);
+       if (t=='_' || t == '-')
+               return('-');
+       if (t=='=')return('=');
+       if (t=='^') return(1);
+       if (fullbot[i] )
+               return(fullbot[i]);
+       if (t=='s') return(thish(i,c-1));
+       if (t==0) return(1);
+       pc = &table[i][c];
+       s = (t=='a' ? pc->rcol : pc->col);
+       if (s==0 || (point(s) && *s==0))
+               return(1);
+       if (vspen(s)) return(1);
+       if (t=barent( s))
+               return(t);
+       return(0);
+}
diff --git a/usr/src/cmd/tbl/tu.c b/usr/src/cmd/tbl/tu.c
new file mode 100644 (file)
index 0000000..4a08347
--- /dev/null
@@ -0,0 +1,202 @@
+ /* tu.c: draws horizontal lines */
+# include "t..c"
+makeline(i,c,lintype)
+{
+int cr, type, shortl;
+type = thish(i,c);
+if (type==0) return;
+cr=c;
+shortl = (table[i][c].col[0]=='\\');
+if (c>0 && !shortl && thish(i,c-1) == type)return;
+if (shortl==0)
+       for(cr=c; cr < ncol && (ctype(i,cr)=='s'||type==thish(i,cr)); cr++);
+else
+       for(cr=c+1; cr<ncol && ctype(i,cr)=='s'; cr++);
+drawline(i, c, cr-1, lintype, 0, shortl);
+}
+fullwide(i, lintype)
+{
+int cr, cl;
+if (!pr1403)
+       fprintf(tabout, ".nr %d \\n(.v\n.vs \\n(.vu-\\n(.sp\n", SVS);
+cr= 0;
+while (cr<ncol)
+       {
+       cl=cr;
+       while (i>0 && vspand(prev(i),cl,1))
+               cl++;
+       for(cr=cl; cr<ncol; cr++)
+               if (i>0 && vspand(prev(i),cr,1))
+                       break;
+       if (cl<ncol)
+       drawline(i,cl,(cr<ncol?cr-1:cr),lintype,1,0);
+       }
+fprintf(tabout, "\n");
+if (!pr1403)
+       fprintf(tabout, ".vs \\n(%du\n", SVS);
+}
+
+drawline(i, cl, cr, lintype, noheight, shortl)
+{
+       char *exhr, *exhl;
+       int lcount, ln, linpos, oldpos, nodata, lnch;
+lcount=0;
+exhr=exhl= "";
+switch(lintype)
+       {
+       case '-': lcount=1;break;
+       case '=': lcount = pr1403? 1 : 2; break;
+       case SHORTLINE: lcount=1; break;
+       }
+if (lcount<=0) return;
+nodata = cr-cl>=ncol || noheight || allh(i);
+       if (!nodata)
+               fprintf(tabout, "\\v'-.5m'");
+for(ln=oldpos=0; ln<lcount; ln++)
+       {
+       linpos = 2*ln - lcount +1;
+       if (linpos != oldpos)
+               fprintf(tabout, "\\v'%dp'", linpos-oldpos);
+       oldpos=linpos;
+       if (shortl==0)
+       {
+       tohcol(cl);
+       if (lcount>1)
+               {
+               switch(interv(i,cl))
+                       {
+                       case TOP: exhl = ln==0 ? "1p" : "-1p"; break;
+                       case BOT: exhl = ln==1 ? "1p" : "-1p"; break;
+                       case THRU: exhl = "1p"; break;
+                       }
+               if (exhl[0])
+               fprintf(tabout, "\\h'%s'", exhl);
+               }
+       else if (lcount==1)
+               {
+               switch(interv(i,cl))
+                       {
+                       case TOP: case BOT: exhl = "-1p"; break;
+                       case THRU: exhl = "1p"; break;
+                       }
+               if (exhl[0])
+               fprintf(tabout, "\\h'%s'", exhl);
+               }
+       if (lcount>1)
+               {
+               switch(interv(i,cr+1))
+                       {
+                       case TOP: exhr = ln==0 ? "-1p" : "+1p"; break;
+                       case BOT: exhr = ln==1 ? "-1p" : "+1p"; break;
+                       case THRU: exhr = "-1p"; break;
+                       }
+               }
+       else if (lcount==1)
+               {
+               switch(interv(i,cr+1))
+                       {
+                       case TOP: case BOT: exhr = "+1p"; break;
+                       case THRU: exhr = "-1p"; break;
+                       }
+               }
+       }
+       else
+               fprintf(tabout, "\\h'|\\n(%du'", cl+CLEFT);
+       fprintf(tabout, "\\s\\n(%d",LSIZE);
+       if (linsize)
+               fprintf(tabout, "\\v'-\\n(%dp/6u'", LSIZE);
+       if (shortl)
+               fprintf(tabout, "\\l'|\\n(%du'", cr+CRIGHT);
+       else
+       {
+       lnch = "\\(ul";
+       if (pr1403)
+               lnch = lintype==2 ? "=" : "\\(ru";
+       if (cr+1>=ncol)
+               fprintf(tabout, "\\l'|\\n(TWu%s%s'", exhr,lnch);
+       else
+               fprintf(tabout, "\\l'(|\\n(%du+|\\n(%du)/2u%s%s'", cr+CRIGHT,
+                       cr+1+CLEFT, exhr, lnch);
+       }
+       if (linsize)
+               fprintf(tabout, "\\v'\\n(%dp/6u'", LSIZE);
+       fprintf(tabout, "\\s0");
+       }
+if (oldpos!=0)
+       fprintf(tabout, "\\v'%dp'", -oldpos);
+if (!nodata)
+       fprintf(tabout, "\\v'+.5m'");
+}
+getstop()
+{
+int i,c,k,junk, stopp;
+stopp=1;
+for(i=0; i<MAXLIN; i++)
+       linestop[i]=0;
+for(i=0; i<nlin; i++)
+       for(c=0; c<ncol; c++)
+               {
+               k = left(i,c,&junk);
+               if (k>=0 && linestop[k]==0)
+                       linestop[k]= ++stopp;
+               }
+if (boxflg || allflg || dboxflg)
+       linestop[0]=1;
+}
+left(i,c, lwidp)
+       int *lwidp;
+{
+int kind, li, lj;
+       /* returns -1 if no line to left */
+       /* returns number of line where it starts */
+       /* stores into lwid the kind of line */
+*lwidp=0;
+kind = lefdata(i,c);
+if (kind==0) return(-1);
+if (i+1<nlin)
+if (lefdata(next(i),c)== kind) return(-1);
+while (i>=0 && lefdata(i,c)==kind)
+       i=prev(li=i);
+if (prev(li)== -1) li=0;
+*lwidp=kind;
+for(lj= i+1; lj<li; lj++)
+       if (instead[lj] && strcmp(instead[lj], ".TH")==0)
+               return(li);
+for(i= i+1; i<li; i++)
+       if (fullbot[i])
+               li=i;
+return(li);
+}
+lefdata(i,c)
+{
+int ck;
+if (i>=nlin) i=nlin-1;
+if (ctype(i,c) == 's')
+       {
+       for(ck=c; ctype(i,ck)=='s'; ck--);
+       if (thish(i,ck)==0)
+               return(0);
+       }
+i =stynum[i];
+i = lefline[i][c];
+if (i>0) return(i);
+if (dboxflg && c==0) return(2);
+if (allflg)return(1);
+if (boxflg && c==0) return(1);
+return(0);
+}
+next(i)
+{
+while (i+1 <nlin)
+       {
+       i++;
+       if (!fullbot[i] && !instead[i]) break;
+       }
+return(i);
+}
+prev(i)
+{
+while (--i >=0  && (fullbot[i] || instead[i]))
+       ;
+return(i);
+}
diff --git a/usr/src/cmd/tbl/tv.c b/usr/src/cmd/tbl/tv.c
new file mode 100644 (file)
index 0000000..eaf0c8b
--- /dev/null
@@ -0,0 +1,147 @@
+ /* tv.c: draw vertical lines */
+# include "t..c"
+drawvert(start,end, c, lwid)
+{
+char *exb=0, *ext=0;
+int tp=0, sl, ln, pos, epb, ept, vm;
+end++;
+vm='v';
+/* note: nr 35 has value of 1m outside of linesize */
+while (instead[end]) end++;
+for(ln=0; ln<lwid; ln++)
+       {
+       epb=ept=0;
+       pos = 2*ln-lwid+1;
+       if (pos!=tp) fprintf(tabout, "\\h'%dp'", pos-tp);
+       tp = pos;
+       if (end<nlin)
+               {
+               if (fullbot[end]|| (!instead[end] && allh(end)))
+                       epb=2;
+               else
+               switch (midbar(end,c))
+                       {
+                       case '-':
+                       exb = "1v-.5m"; break;
+                       case '=':
+                       exb = "1v-.5m";
+                       epb = 1; break;
+                       }
+               }
+       if (lwid>1)
+       switch(interh(end, c))
+               {
+               case THRU: epb -= 1; break;
+               case RIGHT: epb += (ln==0 ? 1 : -1); break;
+               case LEFT: epb += (ln==1 ? 1 : -1); break;
+               }
+       if (lwid==1)
+       switch(interh(end,c))
+               {
+               case THRU: epb -= 1; break;
+               case RIGHT: case LEFT: epb += 1; break;
+               }
+       if (start>0)
+               {
+               sl = start-1;
+               while (sl>=0 && instead[sl]) sl--;
+               if (sl>=0 && (fullbot[sl] || allh(sl)))
+                       ept=0;
+               else
+               if (sl>=0)
+               switch(midbar(sl,c))
+                       {
+                       case '-':
+                       ext = ".5m"; break;
+                       case '=':
+                       ext= ".5m"; ept = -1; break;
+                       default:
+                               vm = 'm'; break;
+                       }
+               else
+                       ept = -4;
+               }
+       else if (start==0 && allh(0))
+               {
+               ept=0;
+               vm = 'm';
+               }
+       if (lwid>1)
+               switch(interh(start,c))
+                       {
+                       case THRU: ept += 1; break;
+                       case LEFT: ept += (ln==0 ? 1 : -1); break;
+                       case RIGHT: ept += (ln==1 ? 1 : -1); break;
+                       }
+       else if (lwid==1)
+               switch(interh(start,c))
+                       {
+                       case THRU: ept += 1; break;
+                       case LEFT: case RIGHT: ept -= 1; break;
+                       }
+       if (exb)
+               fprintf(tabout, "\\v'%s'", exb);
+       if (epb)
+               fprintf(tabout, "\\v'%dp'", epb);
+       fprintf(tabout, "\\s\\n(%d",LSIZE);
+       if (linsize)
+               fprintf(tabout, "\\v'-\\n(%dp/6u'", LSIZE);
+       fprintf(tabout, "\\h'-\\n(#~u'"); /* adjustment for T450 nroff boxes */
+       fprintf(tabout, "\\L'|\\n(#%cu-%s", linestop[start]+'a'-1, vm=='v'? "1v" : "\\n(35u");
+       if (ext)
+               fprintf(tabout, "-(%s)",ext);
+       if (exb)
+               fprintf(tabout, "-(%s)", exb);
+       pos = ept-epb;
+       if (pos)
+               fprintf(tabout, "%s%dp", pos>=0? "+" : "", pos);
+       /* the string #d is either "nl" or ".d" depending
+          on diversions; on GCOS not the same */
+       fprintf(tabout, "'\\s0\\v'\\n(\\*(#du-\\n(#%cu+%s", linestop[start]+'a'-1,vm=='v' ? "1v" : "\\n(35u");
+       if (ext)
+               fprintf(tabout, "+%s",ext);
+       if (ept)
+               fprintf(tabout, "%s%dp", (-ept)>0 ? "+" : "", (-ept));
+       fprintf(tabout, "'");
+       if (linsize)
+               fprintf(tabout, "\\v'\\n(%dp/6u'", LSIZE);
+       }
+}
+
+
+midbar(i,c)
+{
+int k;
+k = midbcol(i,c);
+if (k==0 && c>0)
+       k = midbcol(i, c-1);
+return(k);
+}
+midbcol(i,c)
+{
+int ct;
+while ( (ct=ctype(i,c)) == 's')
+       c--;
+if (ct=='-' || ct == '=')
+       return(ct);
+if (ct=barent(table[i][c].col))
+       return(ct);
+return(0);
+}
+
+barent(s)
+       char *s;
+{
+if (s==0) return (1);
+if (s[0]== '\\') s++;
+if (s[1]!= 0)
+       return(0);
+switch(s[0])
+       {
+       case '_':
+               return('-');
+       case '=':
+               return('=');
+       }
+return(0);
+}
diff --git a/usr/src/cmd/tp/tp.h b/usr/src/cmd/tp/tp.h
new file mode 100644 (file)
index 0000000..a3a29d5
--- /dev/null
@@ -0,0 +1,85 @@
+/*     c-version of tp?.s
+ *
+ *     M. Ferentz
+ *     August 1976
+ *
+ *     revised July 1977 BTL
+ */
+
+#define        MDIRENT 496             /* must be zero mod 8 */
+#define DIRSZ  sizeof(struct dent)
+#define MAPSIZE 4096
+#define MAPMASK 07777
+#define NAMELEN 32
+#define BSIZE   512
+#define        TCSIZ   578
+#define TCDIRS 192
+#define        MTSIZ   32767
+#define TPB    (BSIZE/sizeof(struct tent))
+#define        OK      0100000
+#define        BRKINCR 512
+
+#define        tapeblk &tpentry[0]
+#define tapeb  &tpentry[0]
+
+struct         tent    {       /* Structure of a tape directory block */
+       char    pathnam[NAMELEN];
+       short   mode;
+       char    uid;
+       char    gid;
+       char    spare;
+       char    size0;
+       unsigned short  size1;
+       long    time;
+       unsigned short  tapea;  /* tape address */
+       short   unused[8];
+       short   cksum;
+}      tpentry[TPB];
+
+struct dent {  /* in core version of tent with "unused" removed
+                * and pathname replaced by pointer to same in a
+                * packed area (nameblock).
+                */
+       char    *d_namep;
+       int     d_mode;
+       int     d_uid;
+       int     d_gid;
+       long    d_size;
+       long    d_time;
+       int     d_tapea;
+}  dir[MDIRENT];
+
+char   map[MAPSIZE];
+char   name[NAMELEN];
+char   name1[NAMELEN];
+extern char mt[];
+extern char tc[];
+char   *tname;
+extern char mheader[];
+extern char theader[];
+
+int    narg, rnarg;
+char   **parg;
+int    wseeka,rseeka;
+int    tapsiz;
+int    fio;
+short  ndirent, ndentb;
+struct dent    *edir;
+struct dent *lastd;            /* for improvement */
+char   *sbrk();
+char   *strcpy();
+long   lseek();
+int    (*command)();
+
+char   *nameblk;
+char   *top;
+char   *nptr;
+
+extern int     flags;
+#define        flc     0001
+#define        fli     0004
+#define        flm     0010
+#define        flu     0020
+#define        flv     0040
+#define        flw     0100
+#define fls    0200
diff --git a/usr/src/cmd/tp/tp0.c b/usr/src/cmd/tp/tp0.c
new file mode 100644 (file)
index 0000000..04a5c21
--- /dev/null
@@ -0,0 +1,2 @@
+#include "tp.h"
+#include <tp_defs.h>
diff --git a/usr/src/cmd/tp/tp2.c b/usr/src/cmd/tp/tp2.c
new file mode 100644 (file)
index 0000000..09197a4
--- /dev/null
@@ -0,0 +1,348 @@
+#include "tp.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+
+struct direct  direct;
+struct stat    statb;
+
+clrdir()
+{
+       register j, *p;
+
+       j = ndirent * (DIRSZ/sizeof(int));
+       p = (int *)dir;
+       do (*p++ = 0);  while (--j);
+       lastd = 0;
+}
+
+clrent(ptr)
+struct dent *ptr;
+{
+       register *p, j;
+
+       p  = (int *)ptr;
+       j = DIRSZ/sizeof(int);
+       do *p++ = 0;
+          while (--j);
+       if (++ptr == lastd) do {
+               if (--lastd < dir) {
+                       lastd = 0;
+                       return;
+               }
+       } while (lastd->d_namep == 0);
+}
+
+
+rddir()
+{
+       register struct tent *tp;
+       register struct dent *p1;
+       struct dent  *dptr;
+       struct tent  *tptr;
+       int     count, i, sum;
+       short   reg, *sp;
+
+       sum = 0;
+       clrdir();
+       rseek(0);
+       tread();        /* Read the bootstrap block */
+       if ((tpentry[TPB-1].cksum != 0) && (flags & flm)) {
+               ndirent = tpentry[TPB-1].cksum;
+               if(flags & fls) swab((char *)&ndirent, (char *)&ndirent, sizeof(ndirent));
+               if(ndirent < 0 || ndirent > MDIRENT) ndirent = MDIRENT;
+               ndentb = ndirent/TPB;
+       }
+       dptr = &dir[0];
+       count = ndirent;
+       do {
+               if ((count % TPB) == 0) {       /* next block */
+                       tread();
+                       tptr = &tpentry[0];
+               }
+               if(flags & fls)
+                       swab((char *)tptr, (char *)tptr, sizeof(*tptr));
+               sp = (short *)tptr;
+               reg = 0;
+               for(i=0;i<sizeof(struct tent)/sizeof(short);i++)
+                       reg += *sp++;
+               if(flags & fls) {
+                       swab((char *)tptr, (char *)tptr, sizeof(*tptr));
+                       swabdir(tptr);
+               }
+               sum |= reg;
+               p1 = dptr;
+               if (reg == 0) {
+                       tp = tptr;
+                       if(tp->pathnam[0] != '\0') {
+                               lastd = p1;
+                               encode(tp->pathnam,p1);
+                               p1->d_mode = tp->mode;
+                               p1->d_uid = tp->uid;
+                               p1->d_gid = tp->gid;
+                               p1->d_size = (((long)tp->size0&0377L)<<16)+(tp->size1&0177777L);
+                               p1->d_time = tp->time;
+                               p1->d_tapea = tp->tapea;
+                       }
+               }
+               ++tptr;         /* bump to next tent */
+               (dptr++)->d_mode &= ~OK;
+       } while (--count);
+       if(sum != 0)
+               if(flags & (fls|fli)) {
+                       printf("Directory checksum\n");
+                       if ((flags & fli) == 0)         done();
+               } else {
+                       flags |= fls;
+                       rddir();
+                       printf("Warning: swabbing required\n");
+                       return;
+               }
+       bitmap();
+}
+
+
+wrdir()
+{
+       register struct tent *tp;
+       register struct dent *dp;
+       struct dent *dptr;
+       int     count, i;
+       short   reg, *sp;
+
+       wseek(0);
+       if (flags & flm)
+               reg = open(mheader,0);
+       else    reg = open(theader,0);
+       if (reg >= 0) {
+               read(reg,(char *)tapeb,BSIZE);
+               close(reg);
+               if(flags & fls)
+                       swab((char *)&ndirent, (char *)&tpentry[TPB-1].cksum, sizeof(ndirent));
+               else
+                       tpentry[TPB-1].cksum = ndirent;
+       } else
+               printf("\7\7\7Warning: cannot read prototype boot block.\n");
+       dptr = &dir[0];
+       count = ndirent;
+       for (;;) {
+               twrite();
+               if (count == 0)  return;
+               tp = &tpentry[0];
+               do {
+                       dp = dptr++;    /* dptr set to next entry */
+                       if (dp->d_namep)  {
+                               decode(tp->pathnam,dp);
+                               tp->mode = dp->d_mode;
+                               tp->uid = dp->d_uid;
+                               tp->gid = dp->d_gid;
+                               tp->time = dp->d_time;
+                               tp->size0 = dp->d_size >> 16;
+                               tp->size1 = dp->d_size;
+                               tp->tapea = dp->d_tapea;
+                               if(flags & fls) {
+                                       swabdir(tp);
+                                       swab((char *)tp, (char *)tp, sizeof(*tp));
+                               }
+                               reg = 0;
+                               sp = (short *)tp;
+                               for(i=0;i<sizeof(struct tent)/sizeof(short)-1;i++)
+                                       reg -= *sp++;
+                               *sp = reg;
+                               if(flags & fls)
+                                       swab((char *)tp, (char *)tp, sizeof(*tp));
+                       } else {
+                               sp = (short *)tp;
+                               for(i=0;i<sizeof(struct tent)/sizeof(short);i++)
+                                       *sp++ = 0;
+                       }
+               tp++;
+               } while (--count % TPB);
+       }
+}
+
+tread()
+{
+       register j, *ptr;
+
+       if (read(fio,(char *)tapeb,BSIZE) != BSIZE) {
+               printf("Tape read error\n");
+               if ((flags & fli) == 0)         done();
+               ptr = (int *)tapeb;
+               j = BSIZE/sizeof(int);
+               while(j--) *ptr++ = 0;
+       }
+       rseeka++;
+}
+
+twrite()
+{
+       if (write(fio, (char *)tapeb,BSIZE) != BSIZE) {
+               printf("Tape write error\n");
+               done();
+       }
+       ++wseeka;
+}
+
+rseek(blk)
+{
+       rseeka = blk;
+       if (lseek(fio,(long)blk*BSIZE,0) < 0)   seekerr();
+}
+
+wseek(blk)
+{
+       register amt, b;
+
+       amt = b = blk;
+       if ((amt -= wseeka) < 0)        amt = -amt;
+       if (amt > 25 && b) {
+               lseek(fio, (long)(b-1)*BSIZE, 0);       /* seek previous block */
+               read(fio, (char *)&wseeka, 1);  /* read next block */
+       }
+       wseeka = b;
+       if (lseek(fio, (long)b*BSIZE, 0) < 0)   seekerr();
+}
+
+seekerr()
+{
+       printf("Tape seek error\n");
+       done();
+}
+
+verify(key)
+{
+       register c;
+
+       if ((flags & (flw | flv)) == 0)
+               return(0);
+repeat:        printf("%c %s ", key, name);
+       if ((flags & flw) == 0) {
+               printf("\n");
+               return(0);
+       }
+       c = getchar();
+       if (c == 'n' && getchar() == '\n')
+               done();
+       if (c == '\n')
+               return(-1);
+       if (c == 'y' && getchar() == '\n')
+               return(0);
+       while (getchar() != '\n');
+       goto repeat;
+}
+
+getfiles()
+{
+
+       if ((narg -= 2) == 0) {
+               strcpy(name, ".");
+               callout();
+       } else while (--narg >= 0) {
+               strcpy(name, *parg++);
+               callout();
+       }
+}
+
+
+expand()
+{
+       register  char *p0, *save0;
+       int n, fid;
+
+       if ((fid = open(name,0)) < 0)           fserr();
+       for (;;) {
+               if ((n = read(fid, (char *)&direct, sizeof(direct))) != sizeof(direct)) {
+                       if (n == 0) {
+                               close(fid);
+                               return;
+                       }
+                       fserr();
+               }
+               if (direct.d_ino == 0)  /* null entry */
+                       continue;
+               p0 = name;
+               if (direct.d_name[0] == '.')            /* don't save .xxxx */
+                       continue;
+               while (*p0++);
+               save0 = --p0;           /* save loc of \0 */
+               if (p0[-1] != '/')
+                       *p0++ = '/';
+               strcpy(p0, direct.d_name);
+                       callout();
+               *save0 = 0;             /* restore */
+       }
+}
+
+fserr()
+{
+       printf("%s -- Cannot open file\n", name);
+       done();
+}
+
+callout()
+{
+       register struct dent *d;
+       register char *ptr1, *ptr0;
+       struct dent *empty;
+       int mode;
+
+       if (stat(name,&statb) < 0)      fserr();
+       mode = statb.st_mode;
+       if ((mode &= S_IFMT) != 0) {
+               if (mode == S_IFDIR)  /* directory */
+                       expand();
+               if(mode != S_IFREG) return;
+       }
+       /* when we reach here we have recursed until we found 
+        * an ordinary file.  Now we look for it in "dir".
+        */
+       empty = 0;
+       d = &dir[0];
+       do  {
+               if (d->d_namep == 0) {  /* empty directory slot */
+                       if (empty == 0) /* remember the first one */
+                               empty = d;
+                       continue;
+               }
+               decode(name1,d);
+               ptr0 = name;
+               ptr1 = name1;
+               do      if (*ptr0++ != *ptr1)   goto cont;
+                   while (*ptr1++);
+               /* veritably the same name */
+               if (flags & flu) {  /* check the times */
+                       if (d->d_time >= statb.st_mtime)
+                               return;
+               }
+               if (verify('r') < 0)    return;
+               goto copydir;
+cont:          continue;
+       }  while (++d <= lastd);
+       /* name not found in directory */
+       if ((d = empty) == 0) {
+               d = lastd +1;
+               if (d >= edir) {
+                       printf("Directory overflow\n");
+                       done();
+               }
+       }
+       if (verify('a') < 0)            return;
+       if (d > lastd)          lastd = d;
+       encode(name,d);
+copydir:
+       d->d_mode = statb.st_mode | OK;
+       d->d_uid = statb.st_uid;
+       d->d_gid = statb.st_gid;
+       d->d_size = statb.st_size;
+       d->d_time = statb.st_mtime;
+}
+
+swabdir(tp)
+register struct tent *tp;
+{
+       swab((char *)tp, (char *)tp, sizeof(*tp));
+       swab(tp->pathnam, tp->pathnam, NAMELEN);
+       swab((char *)&tp->uid, (char *)&tp->uid, 4); /* uid,gid,spare,size0 */
+}
diff --git a/usr/src/cmd/tp/tp3.c b/usr/src/cmd/tp/tp3.c
new file mode 100644 (file)
index 0000000..c754ae6
--- /dev/null
@@ -0,0 +1,248 @@
+#include "tp.h"
+
+gettape(how)
+int (*how)();
+{
+       register char *ptr0, *ptr1;
+       register struct dent *d;
+       int count;
+
+       do {
+               d = &dir[0];
+               count = 0;
+               do {
+                       if (d->d_namep == 0)  continue;
+                       decode(name,d);
+                       if (rnarg > 2) {
+                               ptr0 = name;
+                               ptr1 = *parg;
+                               while (*ptr1)
+                                       if (*ptr0++ != *ptr1++)  goto cont;
+                               if (*ptr0 && *ptr0 != '/')       goto cont;
+                       }
+                       (*how)(d);  /* delete, extract, or taboc */
+                       ++count;
+cont:                  continue;
+               }  while (++d <= lastd);
+               if (count == 0 && rnarg > 2)
+                       printf("%s  not found\n", *parg);
+               ++parg;
+       } while (--narg > 2);
+}
+
+delete(dd)
+struct dent *dd;
+{
+       if (verify('d') >= 0)
+               clrent(dd);
+}
+
+
+update()
+{
+       register struct dent *d;
+       register b, last;
+       int first, size;
+
+
+       bitmap();
+       d = &dir[0];
+       do {
+               if(d->d_namep == 0 || (d->d_mode&OK) == 0) continue;
+               if (d->d_size == 0)       continue;
+/* find a place on the tape for this file */
+               size = (d->d_size+BSIZE-1)/BSIZE;
+               first = ndentb;
+toosmall:      ++first;
+               if ((last = first + size) >= tapsiz)    maperr();
+               for (b = first; b < last; ++b)
+                       if (map[(b>>3) & MAPMASK] & (1<<(b&7))) {
+                               first = b;
+                               goto toosmall;
+                       };
+               d->d_tapea = first;
+               setmap(d);
+       }  while (++d <= lastd);
+       wrdir();
+       update1();
+}
+
+
+update1()
+{
+       register struct dent *d, *id;
+       register index;
+       int f;
+
+       for (;;) {
+               d = &dir[0];
+               index = MTSIZ;
+               id = 0;
+               do {    /* find new dent with lowest tape address */
+                       if(d->d_namep == 0 || (d->d_mode&OK) == 0) continue;
+                       if (d->d_tapea < index) {
+                               index = d->d_tapea;
+                               id = d;
+                       }
+               } while (++d <= lastd);
+               if ((d = id) == 0)      return;
+               d->d_mode &= ~OK;  /* change from new to old */
+               if (d->d_size == 0)  continue;
+               decode(name,d);
+               wseek(index);
+               if ((f = open(name,0)) < 0) {
+                       printf("Can't open %s\n", name);
+                       continue;
+               }
+               for (index = d->d_size/BSIZE; index != 0; --index)  {
+                       if (read(f,(char *)tapeb,BSIZE) != BSIZE)           phserr();
+                       twrite();
+               }
+               if (index = d->d_size % BSIZE) {
+                       if (read(f,(char *)tapeb,index) != index)  phserr();
+                       twrite();
+               }
+               if (read(f,(char *)tapeb,1) != 0)                   phserr();
+               close(f);
+       }
+}
+
+phserr()
+{      printf("%s -- Phase error \n", name);  }
+
+
+bitmap()       /* place old files in the map */
+{
+       register char *m;
+       register count;
+       register struct dent *d;
+
+       for(m=map;m<&map[MAPSIZE];) *m++ = 0;
+       count = ndirent;
+       d = dir;
+       do {
+               if(d->d_namep != 0 && (d->d_mode&OK) == 0
+                  && d->d_size != 0) setmap(d);
+               d++;
+       }  while (--count);
+}
+
+setmap(d)
+register struct dent *d;
+{
+       unsigned c, block;
+       char bit;
+       int i;
+
+       c = d->d_size/BSIZE;
+       if (d->d_size % BSIZE)  c++;
+       block = d->d_tapea;
+       if ((c += block) >= tapsiz)             maperr();
+       do {
+               bit = 1 << (block & 7);
+               i = (block>>3) & MAPMASK;
+               if (bit & map[i])               maperr();
+               map[i] |= bit;
+       } while (++block < c);
+}
+
+maperr()
+{
+       printf("Tape overflow\n");
+       done();
+}
+
+
+usage()
+{
+       register reg,count;
+       int     nused, nentr, nfree;
+       static lused;
+
+       bitmap();
+       for(count=0,nentr=0;count<ndirent;count++)
+               if(dir[count].d_namep != 0) nentr++;
+       nused = nfree = 0;
+       reg = ndentb;
+       ++reg;          /* address of first non-directory tape block */
+       count = tapsiz - reg;
+       do {
+               if (reg >= tapsiz) {
+                       printf("Tape overflow\n");
+                       done();
+               }
+               if (map[(reg>>3) & MAPMASK] & (1 << (reg&7))) {
+                       nused++;
+                       lused = reg;
+               } else {
+                       if (flags & flm)   break;
+                       nfree++;
+               }
+               reg++;
+       } while (--count);
+       printf("%4d entries\n%4d used\n", nentr, nused);
+       if ((flags & flm)==0)
+               printf("%4d free\n", nfree);
+       printf("%4d last\n", lused);
+}
+
+
+taboc(dd)
+struct dent *dd;
+{
+       register  mode;
+       register *m;
+       register char *s;
+       int count, *localtime();
+       char work[20];
+
+       if (flags & flv)  {
+               mode = dd->d_mode;
+               s = &work[19];
+               *s = 0;
+               for (count = 3; count; --count) {
+                       if (mode&1)     *--s = 'x';
+                         else          *--s = '-';
+                       if (mode&2)     *--s = 'w';
+                         else          *--s = '-';
+                       if (mode&4)     *--s = 'r';
+                         else          *--s = '-';
+                       mode >>= 3;
+               }
+               if (mode&4)             s[2] = 's';
+               if (mode&2)             s[5] = 's';
+               printf("%s%4d%4d%5d%9D ",s,dd->d_uid, dd->d_gid,dd->d_tapea,dd->d_size);
+               m = localtime(&dd->d_time);
+               printf("%2d/%2d/%2d %2d:%2d ",m[5],m[4]+1,m[3],m[2],m[1]);
+       }
+       printf("%s\n", name);
+}
+
+
+extract(d)
+register struct dent *d;
+{
+       register count, id;
+
+       if (d->d_size==0)       return;
+       if (verify('x') < 0)                    return;
+       rseek(d->d_tapea);
+       unlink(name);
+       if ((id = creat(name,d->d_mode)) < 0)
+               printf("%s -- create error\n", name);
+       count = d->d_size/BSIZE;
+       while (count--) {
+               tread();
+               if (write(id, (char *)tapeb, BSIZE) != BSIZE)   goto ng;
+       }
+       if (count = d->d_size % BSIZE) {
+               tread();
+               if (write(id, (char *)tapeb, count) != count) {
+ng:                    printf("%s -- write error\n", name);
+                       close(id);
+                       return;
+               }
+       }
+       close(id);
+       chown(name,d->d_uid & 0377, d->d_gid&0377);
+}
diff --git a/usr/src/cmd/troff/term/code.300 b/usr/src/cmd/troff/term/code.300
new file mode 100644 (file)
index 0000000..eaf6514
--- /dev/null
@@ -0,0 +1,211 @@
+"\001 ",       /*space*/
+"\001!",       /*!*/
+"\001\"",      /*"*/
+"\001#",       /*#*/
+"\001$",       /*$*/
+"\001%",       /*%*/
+"\001&",       /*&*/
+"\001'",       /*' close*/
+"\001(",       /*(*/
+"\001)",       /*)*/
+"\001*",       /***/
+"\001+",       /*+*/
+"\001,",       /*,*/
+"\001-",       /*- hyphen*/
+"\001.",       /*.*/
+"\001/",       /*/*/
+"\2010",       /*0*/
+"\2011",       /*1*/
+"\2012",       /*2*/
+"\2013",       /*3*/
+"\2014",       /*4*/
+"\2015",       /*5*/
+"\2016",       /*6*/
+"\2017",       /*7*/
+"\2018",       /*8*/
+"\2019",       /*9*/
+"\001:",       /*:*/
+"\001;",       /*;*/
+"\001<",       /*<*/
+"\001=",       /*=*/
+"\001>",       /*>*/
+"\001?",       /*?*/
+"\001@",       /*@*/
+"\201A",       /*A*/
+"\201B",       /*B*/
+"\201C",       /*C*/
+"\201D",       /*D*/
+"\201E",       /*E*/
+"\201F",       /*F*/
+"\201G",       /*G*/
+"\201H",       /*H*/
+"\201I",       /*I*/
+"\201J",       /*J*/
+"\201K",       /*K*/
+"\201L",       /*L*/
+"\201M",       /*M*/
+"\201N",       /*N*/
+"\201O",       /*O*/
+"\201P",       /*P*/
+"\201Q",       /*Q*/
+"\201R",       /*R*/
+"\201S",       /*S*/
+"\201T",       /*T*/
+"\201U",       /*U*/
+"\201V",       /*V*/
+"\201W",       /*W*/
+"\201X",       /*X*/
+"\201Y",       /*Y*/
+"\201Z",       /*Z*/
+"\001[",       /*[*/
+"\001\\",      /*\*/
+"\001]",       /*]*/
+"\001^",       /*^*/
+"\001_",       /*_ dash*/
+"\001`",       /*` open*/
+"\201a",       /*a*/
+"\201b",       /*b*/
+"\201c",       /*c*/
+"\201d",       /*d*/
+"\201e",       /*e*/
+"\201f",       /*f*/
+"\201g",       /*g*/
+"\201h",       /*h*/
+"\201i",       /*i*/
+"\201j",       /*j*/
+"\201k",       /*k*/
+"\201l",       /*l*/
+"\201m",       /*m*/
+"\201n",       /*n*/
+"\201o",       /*o*/
+"\201p",       /*p*/
+"\201q",       /*q*/
+"\201r",       /*r*/
+"\201s",       /*s*/
+"\201t",       /*t*/
+"\201u",       /*u*/
+"\201v",       /*v*/
+"\201w",       /*w*/
+"\201x",       /*x*/
+"\201y",       /*y*/
+"\201z",       /*z*/
+"\001{",       /*{*/
+"\001|",       /*|*/
+"\001}",       /*}*/
+"\001~",       /*~*/
+"\000\0",      /*narrow sp*/
+"\001-",        /*hyphen*/
+"\001o\b+",     /*bullet*/
+"\002[]",       /*square*/
+"\001-",        /*3/4 em*/
+"\001_",        /*rule*/
+"\000\0",       /*1/4*/
+"\000\0",       /*1/2*/
+"\000\0",       /*3/4*/
+"\001-",        /*minus*/
+"\202fi",       /*fi*/
+"\202fl",       /*fl*/
+"\202ff",       /*ff*/
+"\203ffi",      /*ffi*/
+"\203ffl",      /*ffl*/
+"\000\0",       /*degree*/
+"\000\0",       /*dagger*/
+"\000\0",       /*section*/
+"\001'",        /*foot mark*/
+"\001'",        /*acute accent*/
+"\001`",        /*grave accent*/
+"\001_",        /*underrule*/
+"\001/",        /*slash (longer)*/
+"\000\0",      /*half narrow space*/
+"\001 ",       /*unpaddable space*/
+"\001\241c\202(\241", /*alpha*/
+"\001\200B\242\302|\202\342", /*beta*/
+"\001\200)\201/\241", /*gamma*/
+"\001\200o\342<\302", /*delta*/
+"\001<\b-", /*epsilon*/
+"\001\200c\201\301,\241\343<\302", /*zeta*/
+"\001\200n\202\302|\242\342", /*eta*/
+"\001O\b-", /*theta*/
+"\001i",        /*iota*/
+"\001k",        /*kappa*/
+"\001\200\\\304\241'\301\241'\345\202", /*lambda*/
+"\001\200u\242,\202", /*mu*/
+"\001\241(\203/\242", /*nu*/
+"\001\200c\201\301,\241\343c\241\301`\201\301", /*xi*/
+"\001o",        /*omicron*/
+"\001\341-\303\"\301\"\343", /*pi*/
+"\001\200o\242\302|\342\202", /*rho*/
+"\001\200o\301\202~\341\242", /*sigma*/
+"\001\200t\301\202~\243~\201\341", /*tau*/
+"\001v",        /*upsilon*/
+"\001o\b/", /*phi*/
+"\001x",        /*chi*/
+"\001\200/-\302\202'\244'\202\342", /*psi*/
+"\001\241u\203u\242", /*omega*/
+"\001\242|\202\343-\303\202`\242", /*Gamma*/
+"\001\242/\303-\204-\343\\\242", /*Delta*/
+"\001O\b=", /*Theta*/
+"\001\242/\204\\\242", /*Lambda*/
+"\000\0",       /*Xi*/
+"\001\242[]\204[]\242\343-\303", /*Pi*/
+"\001\200>\302-\345-\303", /*Sigma*/
+"\000\0",       /**/
+"\001Y",        /*Upsilon*/
+"\001o\b[\b]", /*Phi*/
+"\001\200[]-\302\202'\244`\202\342", /*Psi*/
+"\001\200O\302\241-\202-\241\342", /*Omega*/
+"\000\0",       /*square root*/
+"\000\0",       /*terminal sigma*/
+"\000\0",       /*root en*/
+"\001>\b_",     /*>=*/
+"\001<\b_",     /*<=*/
+"\001=\b_",     /*identically equal*/
+"\001-",        /*equation minus*/
+"\001=\b~",     /*approx =*/
+"\000\0",       /*approximates*/
+"\001=\b/",     /*not equal*/
+"\002->",       /*right arrow*/
+"\002<-",       /*left arrow*/
+"\001|\b^",     /*up arrow*/
+"\000\0",       /*down arrow*/
+"\001=",        /*equation equal*/
+"\001x",        /*multiply*/
+"\001/",        /*divide*/
+"\001+\b_",     /*plus-minus*/
+"\001U",        /*cup (union)*/
+"\000\0",       /*cap (intersection)*/
+"\000\0",       /*subset of*/
+"\000\0",       /*superset of*/
+"\000\0",       /*improper subset*/
+"\000\0",       /* improper superset*/
+"\002oo",       /*infinity*/
+"\001\200o\201\301`\241\341`\241\341`\201\301", /*partial derivative*/
+"\001\242\\\343-\204-\303/\242", /*gradient*/
+"\001\200-\202\341,\301\242", /*not*/
+"\001\200|'\202`\243\306'\241`\202\346",       /*integral sign*/
+"\000\0",       /*proportional to*/
+"\000\0",       /*empty set*/
+"\000\0",       /*member of*/
+"\001+",        /*equation plus*/
+"\001r\bO",     /*registered*/
+"\001c\bO",     /*copyright*/
+"\001|",        /*box rule */
+"\001c\b/",     /*cent sign*/
+"\000\0",       /*dbl dagger*/
+"\000\0",       /*right hand*/
+"\001*",        /*left hand*/
+"\001*",        /*math * */
+"\000\0",       /*bell system sign*/
+"\001|",        /*or (was star)*/
+"\001O",        /*circle*/
+"\001|",        /*left top (of big curly)*/
+"\001|",        /*left bottom*/
+"\001|",        /*right top*/
+"\001|",        /*right bot*/
+"\001|",        /*left center of big curly bracket*/
+"\001|",        /*right center of big curly bracket*/
+"\001|",       /*bold vertical*/
+"\001|",       /*left floor (left bot of big sq bract)*/
+"\001|",       /*right floor (rb of ")*/
+"\001|",       /*left ceiling (lt of ")*/
+"\001|"};      /*right ceiling (rt of ")*/
diff --git a/usr/src/cmd/troff/term/tab300.c b/usr/src/cmd/troff/term/tab300.c
new file mode 100644 (file)
index 0000000..f4af9ee
--- /dev/null
@@ -0,0 +1,59 @@
+#define INCH 240
+/*
+DASI300
+nroff driving tables
+width and code tables
+*/
+
+struct {
+       int bset;
+       int breset;
+       int Hor;
+       int Vert;
+       int Newline;
+       int Char;
+       int Em;
+       int Halfline;
+       int Adj;
+       char *twinit;
+       char *twrest;
+       char *twnl;
+       char *hlr;
+       char *hlf;
+       char *flr;
+       char *bdon;
+       char *bdoff;
+       char *ploton;
+       char *plotoff;
+       char *up;
+       char *down;
+       char *right;
+       char *left;
+       char *codetab[256-32];
+       int zzz;
+       } t = {
+/*bset*/       0,
+/*breset*/     0177420,
+/*Hor*/                INCH/60,
+/*Vert*/       INCH/48,
+/*Newline*/    INCH/6,
+/*Char*/       INCH/10,
+/*Em*/         INCH/10,
+/*Halfline*/   INCH/12,
+/*Adj*/                INCH/10,
+/*twinit*/     "\007",
+/*twrest*/     "\007",
+/*twnl*/       "\015\n",
+/*hlr*/                "",
+/*hlf*/                "",
+/*flr*/                "\013",
+/*bdon*/       "",
+/*bdoff*/      "",
+/*ploton*/     "\006",
+/*plotoff*/    "\033\006",
+/*up*/         "\013",
+/*down*/       "\n",
+/*right*/      " ",
+/*left*/       "\b",
+/*codetab*/
+#include "code.300"
diff --git a/usr/src/cmd/troff/term/tab300S.c b/usr/src/cmd/troff/term/tab300S.c
new file mode 100644 (file)
index 0000000..8d2b858
--- /dev/null
@@ -0,0 +1,59 @@
+#define INCH 240
+/*
+DASI300S
+nroff driving tables
+width and code tables
+*/
+
+struct {
+       int bset;
+       int breset;
+       int Hor;
+       int Vert;
+       int Newline;
+       int Char;
+       int Em;
+       int Halfline;
+       int Adj;
+       char *twinit;
+       char *twrest;
+       char *twnl;
+       char *hlr;
+       char *hlf;
+       char *flr;
+       char *bdon;
+       char *bdoff;
+       char *ploton;
+       char *plotoff;
+       char *up;
+       char *down;
+       char *right;
+       char *left;
+       char *codetab[256-32];
+       int zzz;
+       } t = {
+/*bset*/       0,
+/*breset*/     0177420,
+/*Hor*/                INCH/60,
+/*Vert*/       INCH/48,
+/*Newline*/    INCH/6,
+/*Char*/       INCH/10,
+/*Em*/         INCH/10,
+/*Halfline*/   INCH/12,
+/*Adj*/                INCH/10,
+/*twinit*/     "\033\006",
+/*twrest*/     "\033\006",
+/*twnl*/       "\015\n",
+/*hlr*/                "\033H",
+/*hlf*/                "\033h",
+/*flr*/                "\032",
+/*bdon*/       "",
+/*bdoff*/      "",
+/*ploton*/     "\006",
+/*plotoff*/    "\033\006",
+/*up*/         "\032",
+/*down*/       "\n",
+/*right*/      " ",
+/*left*/       "\b",
+/*codetab*/
+#include "code.300"
diff --git a/usr/src/cmd/troff/term/tab300X.c b/usr/src/cmd/troff/term/tab300X.c
new file mode 100644 (file)
index 0000000..f4af9ee
--- /dev/null
@@ -0,0 +1,59 @@
+#define INCH 240
+/*
+DASI300
+nroff driving tables
+width and code tables
+*/
+
+struct {
+       int bset;
+       int breset;
+       int Hor;
+       int Vert;
+       int Newline;
+       int Char;
+       int Em;
+       int Halfline;
+       int Adj;
+       char *twinit;
+       char *twrest;
+       char *twnl;
+       char *hlr;
+       char *hlf;
+       char *flr;
+       char *bdon;
+       char *bdoff;
+       char *ploton;
+       char *plotoff;
+       char *up;
+       char *down;
+       char *right;
+       char *left;
+       char *codetab[256-32];
+       int zzz;
+       } t = {
+/*bset*/       0,
+/*breset*/     0177420,
+/*Hor*/                INCH/60,
+/*Vert*/       INCH/48,
+/*Newline*/    INCH/6,
+/*Char*/       INCH/10,
+/*Em*/         INCH/10,
+/*Halfline*/   INCH/12,
+/*Adj*/                INCH/10,
+/*twinit*/     "\007",
+/*twrest*/     "\007",
+/*twnl*/       "\015\n",
+/*hlr*/                "",
+/*hlf*/                "",
+/*flr*/                "\013",
+/*bdon*/       "",
+/*bdoff*/      "",
+/*ploton*/     "\006",
+/*plotoff*/    "\033\006",
+/*up*/         "\013",
+/*down*/       "\n",
+/*right*/      " ",
+/*left*/       "\b",
+/*codetab*/
+#include "code.300"
diff --git a/usr/src/cmd/troff/term/tab300s.c b/usr/src/cmd/troff/term/tab300s.c
new file mode 100644 (file)
index 0000000..8d2b858
--- /dev/null
@@ -0,0 +1,59 @@
+#define INCH 240
+/*
+DASI300S
+nroff driving tables
+width and code tables
+*/
+
+struct {
+       int bset;
+       int breset;
+       int Hor;
+       int Vert;
+       int Newline;
+       int Char;
+       int Em;
+       int Halfline;
+       int Adj;
+       char *twinit;
+       char *twrest;
+       char *twnl;
+       char *hlr;
+       char *hlf;
+       char *flr;
+       char *bdon;
+       char *bdoff;
+       char *ploton;
+       char *plotoff;
+       char *up;
+       char *down;
+       char *right;
+       char *left;
+       char *codetab[256-32];
+       int zzz;
+       } t = {
+/*bset*/       0,
+/*breset*/     0177420,
+/*Hor*/                INCH/60,
+/*Vert*/       INCH/48,
+/*Newline*/    INCH/6,
+/*Char*/       INCH/10,
+/*Em*/         INCH/10,
+/*Halfline*/   INCH/12,
+/*Adj*/                INCH/10,
+/*twinit*/     "\033\006",
+/*twrest*/     "\033\006",
+/*twnl*/       "\015\n",
+/*hlr*/                "\033H",
+/*hlf*/                "\033h",
+/*flr*/                "\032",
+/*bdon*/       "",
+/*bdoff*/      "",
+/*ploton*/     "\006",
+/*plotoff*/    "\033\006",
+/*up*/         "\032",
+/*down*/       "\n",
+/*right*/      " ",
+/*left*/       "\b",
+/*codetab*/
+#include "code.300"
diff --git a/usr/src/cmd/troff/term/tab37.c b/usr/src/cmd/troff/term/tab37.c
new file mode 100644 (file)
index 0000000..e391923
--- /dev/null
@@ -0,0 +1,269 @@
+#define INCH 240
+/*
+TTY M37
+nroff driving tables
+width and code tables
+*/
+
+struct {
+       int bset;
+       int breset;
+       int Hor;
+       int Vert;
+       int Newline;
+       int Char;
+       int Em;
+       int Halfline;
+       int Adj;
+       char *twinit;
+       char *twrest;
+       char *twnl;
+       char *hlr;
+       char *hlf;
+       char *flr;
+       char *bdon;
+       char *bdoff;
+       char *ploton;
+       char *plotoff;
+       char *up;
+       char *down;
+       char *right;
+       char *left;
+       char *codetab[256-32];
+       int zzz;
+       } t = {
+/*bset*/       0,
+/*breset*/     0,
+/*Hor*/                INCH/10,
+/*Vert*/       INCH/12,
+/*Newline*/    INCH/6,
+/*Char*/       INCH/10,
+/*Em*/         INCH/10,
+/*Halfline*/   INCH/12,
+/*Adj*/                INCH/10,
+/*twinit*/     "",
+/*twrest*/     "",
+/*twnl*/       "\n",
+/*hlr*/                "\0338",
+/*hlf*/                "\0339",
+/*flr*/                "\0337",
+/*bdon*/       "",
+/*bdoff*/      "",
+/*ploton*/     "",
+/*plotoff*/    "",
+/*up*/         "",
+/*down*/       "",
+/*right*/      "",
+/*left*/       "",
+/*codetab*/
+"\001 ",       /*space*/
+"\001!",       /*!*/
+"\001\"",      /*"*/
+"\001#",       /*#*/
+"\001$",       /*$*/
+"\001%",       /*%*/
+"\001&",       /*&*/
+"\001'",       /*' close*/
+"\001(",       /*(*/
+"\001)",       /*)*/
+"\001*",       /***/
+"\001+",       /*+*/
+"\001,",       /*,*/
+"\001-",       /*- hyphen*/
+"\001.",       /*.*/
+"\001/",       /*/*/
+"\2010",       /*0*/
+"\2011",       /*1*/
+"\2012",       /*2*/
+"\2013",       /*3*/
+"\2014",       /*4*/
+"\2015",       /*5*/
+"\2016",       /*6*/
+"\2017",       /*7*/
+"\2018",       /*8*/
+"\2019",       /*9*/
+"\001:",       /*:*/
+"\001;",       /*;*/
+"\001<",       /*<*/
+"\001=",       /*=*/
+"\001>",       /*>*/
+"\001?",       /*?*/
+"\001@",       /*@*/
+"\201A",       /*A*/
+"\201B",       /*B*/
+"\201C",       /*C*/
+"\201D",       /*D*/
+"\201E",       /*E*/
+"\201F",       /*F*/
+"\201G",       /*G*/
+"\201H",       /*H*/
+"\201I",       /*I*/
+"\201J",       /*J*/
+"\201K",       /*K*/
+"\201L",       /*L*/
+"\201M",       /*M*/
+"\201N",       /*N*/
+"\201O",       /*O*/
+"\201P",       /*P*/
+"\201Q",       /*Q*/
+"\201R",       /*R*/
+"\201S",       /*S*/
+"\201T",       /*T*/
+"\201U",       /*U*/
+"\201V",       /*V*/
+"\201W",       /*W*/
+"\201X",       /*X*/
+"\201Y",       /*Y*/
+"\201Z",       /*Z*/
+"\001[",       /*[*/
+"\001\\",      /*\*/
+"\001]",       /*]*/
+"\001^",       /*^*/
+"\001_",       /*_ dash*/
+"\001`",       /*` open*/
+"\201a",       /*a*/
+"\201b",       /*b*/
+"\201c",       /*c*/
+"\201d",       /*d*/
+"\201e",       /*e*/
+"\201f",       /*f*/
+"\201g",       /*g*/
+"\201h",       /*h*/
+"\201i",       /*i*/
+"\201j",       /*j*/
+"\201k",       /*k*/
+"\201l",       /*l*/
+"\201m",       /*m*/
+"\201n",       /*n*/
+"\201o",       /*o*/
+"\201p",       /*p*/
+"\201q",       /*q*/
+"\201r",       /*r*/
+"\201s",       /*s*/
+"\201t",       /*t*/
+"\201u",       /*u*/
+"\201v",       /*v*/
+"\201w",       /*w*/
+"\201x",       /*x*/
+"\201y",       /*y*/
+"\201z",       /*z*/
+"\001{",       /*{*/
+"\001|",       /*|*/
+"\001}",       /*}*/
+"\001~",       /*~*/
+"\000\0",      /*narrow sp*/
+"\001-",        /*hyphen*/
+"\001o\b+",     /*bullet*/
+"\002[]",       /*square*/
+"\001-",        /*3/4 em*/
+"\001_",        /*rule*/
+"\0031/4",     /*1/4*/
+"\0031/2",     /*1/2*/
+"\0033/4",     /*3/4*/
+"\001-",        /*minus*/
+"\202fi",       /*fi*/
+"\202fl",       /*fl*/
+"\202ff",       /*ff*/
+"\203ffi",      /*ffi*/
+"\203ffl",      /*ffl*/
+"\000\0",       /*degree*/
+"\000\0",       /*dagger*/
+"\000\0",       /*section*/
+"\001'",        /*foot mark*/
+"\001'",        /*acute accent*/
+"\001`",        /*grave accent*/
+"\001_",        /*underrule*/
+"\001/",        /*slash (longer)*/
+"\000\0",      /*half narrow space*/
+"\001 ",       /*unpaddable space*/
+"\201\016A\017", /*alpha*/
+"\201\016B\017", /*beta*/
+"\201\016\\\017", /*gamma*/
+"\201\016D\017", /*delta*/
+"\201\016S\017", /*epsilon*/
+"\201\016Q\017", /*zeta*/
+"\201\016N\017", /*eta*/
+"\201\016O\017", /*theta*/
+"\201i",        /*iota*/
+"\201k",        /*kappa*/
+"\201\016L\017", /*lambda*/
+"\201\016M\017", /*mu*/
+"\201\016@\017", /*nu*/
+"\201\016X\017", /*xi*/
+"\201o",        /*omicron*/
+"\201\016J\017", /*pi*/
+"\201\016K\017", /*rho*/
+"\201\016Y\017", /*sigma*/
+"\201\016I\017", /*tau*/
+"\201v",        /*upsilon*/
+"\201\016U\017", /*phi*/
+"\201x",        /*chi*/
+"\201\016V\017", /*psi*/
+"\201\016C\017", /*omega*/
+"\201\016G\017", /*Gamma*/
+"\201\016W\017", /*Delta*/
+"\201\016T\017", /*Theta*/
+"\201\016E\017", /*Lambda*/
+"\000\0",       /*Xi*/
+"\201\016P\017", /*Pi*/
+"\201\016R\017", /*Sigma*/
+"\000\0",       /**/
+"\201Y",        /*Upsilon*/
+"\201\016F\017", /*Phi*/
+"\201\016H\017", /*Psi*/
+"\201\016Z\017", /*Omega*/
+"\000\0",       /*square root*/
+"\000\0",       /*terminal sigma*/
+"\000\0",       /*root en*/
+"\001>\b_",     /*>=*/
+"\001<\b_",     /*<=*/
+"\001=\b_",     /*identically equal*/
+"\001-",        /*equation minus*/
+"\001=\b~",     /*approx =*/
+"\001\0339~\0338",      /*approximates*/
+"\001=\b/",     /*not equal*/
+"\002->",       /*right arrow*/
+"\002<-",       /*left arrow*/
+"\001|\b^",     /*up arrow*/
+"\000\0",       /*down arrow*/
+"\001=",        /*equation equal*/
+"\001x",        /*multiply*/
+"\001/",        /*divide*/
+"\001+\b_",     /*plus-minus*/
+"\001U",        /*cup (union)*/
+"\000\0",       /*cap (intersection)*/
+"\000\0",       /*subset of*/
+"\000\0",       /*superset of*/
+"\000\0",       /*improper subset*/
+"\000\0",       /* improper superset*/
+"\002oo",       /*infinity*/
+"\001\016]\017", /*partial derivative*/
+"\001\016[\017", /*gradient*/
+"\001\016_\017", /*not*/
+"\001\016^\017", /*integral sign*/
+"\000\0",       /*proportional to*/
+"\000\0",       /*empty set*/
+"\000\0",       /*member of*/
+"\001+",        /*equation plus*/
+"\001\0338r\0339",      /*registered*/
+"\001\0338c\0339",      /*copyright*/
+"\001|",        /*box rule */
+"\001c\b/",     /*cent sign*/
+"\000\0",       /*dbl dagger*/
+"\000\0",       /*right hand*/
+"\001*",        /*left hand*/
+"\001*",        /*math * */
+"\000\0",       /*bell system sign*/
+"\001|",        /*or (was star)*/
+"\001O",        /*circle*/
+"\001|",        /*left top (of big curly)*/
+"\001|",        /*left bottom*/
+"\001|",        /*right top*/
+"\001|",        /*right bot*/
+"\001|",        /*left center of big curly bracket*/
+"\001|",        /*right center of big curly bracket*/
+"\001|",       /*bold vertical*/
+"\001|",       /*left floor (left bot of big sq bract)*/
+"\001|",       /*right floor (rb of ")*/
+"\001|",       /*left ceiling (lt of ")*/
+"\001|"};      /*right ceiling (rt of ")*/
diff --git a/usr/src/cmd/troff/term/tab450-12.c b/usr/src/cmd/troff/term/tab450-12.c
new file mode 100644 (file)
index 0000000..f38e7ad
--- /dev/null
@@ -0,0 +1,59 @@
+#define INCH 240
+/*
+DASI450
+nroff driving tables
+width and code tables
+*/
+
+struct {
+       int bset;
+       int breset;
+       int Hor;
+       int Vert;
+       int Newline;
+       int Char;
+       int Em;
+       int Halfline;
+       int Adj;
+       char *twinit;
+       char *twrest;
+       char *twnl;
+       char *hlr;
+       char *hlf;
+       char *flr;
+       char *bdon;
+       char *bdoff;
+       char *ploton;
+       char *plotoff;
+       char *up;
+       char *down;
+       char *right;
+       char *left;
+       char *codetab[256-32];
+       int zzz;
+       } t = {
+/*bset*/       0,
+/*breset*/     0177420,
+/*Hor*/                INCH/60,
+/*Vert*/       INCH/48,
+/*Newline*/    INCH/6,
+/*Char*/       INCH/12,
+/*Em*/         INCH/12,
+/*Halfline*/   INCH/12,
+/*Adj*/                INCH/12,
+/*twinit*/     "\0334\033\037\013",
+/*twrest*/     "\0334\033\037\015",
+/*twnl*/       "\015\n",
+/*hlr*/                "\033D",
+/*hlf*/                "\033U",
+/*flr*/                "\033\n",
+/*bdon*/       "",
+/*bdoff*/      "",
+/*ploton*/     "\0333",
+/*plotoff*/    "\0334",
+/*up*/         "\033\n",
+/*down*/       "\n",
+/*right*/      " ",
+/*left*/       "\b",
+/*codetab*/
+#include "code.300"
diff --git a/usr/src/cmd/troff/term/tab450.c b/usr/src/cmd/troff/term/tab450.c
new file mode 100644 (file)
index 0000000..1ebcd34
--- /dev/null
@@ -0,0 +1,59 @@
+#define INCH 240
+/*
+DASI450
+nroff driving tables
+width and code tables
+*/
+
+struct {
+       int bset;
+       int breset;
+       int Hor;
+       int Vert;
+       int Newline;
+       int Char;
+       int Em;
+       int Halfline;
+       int Adj;
+       char *twinit;
+       char *twrest;
+       char *twnl;
+       char *hlr;
+       char *hlf;
+       char *flr;
+       char *bdon;
+       char *bdoff;
+       char *ploton;
+       char *plotoff;
+       char *up;
+       char *down;
+       char *right;
+       char *left;
+       char *codetab[256-32];
+       int zzz;
+       } t = {
+/*bset*/       0,
+/*breset*/     0177420,
+/*Hor*/                INCH/60,
+/*Vert*/       INCH/48,
+/*Newline*/    INCH/6,
+/*Char*/       INCH/10,
+/*Em*/         INCH/10,
+/*Halfline*/   INCH/12,
+/*Adj*/                INCH/10,
+/*twinit*/     "\0334",
+/*twrest*/     "\0334",
+/*twnl*/       "\015\n",
+/*hlr*/                "\033D",
+/*hlf*/                "\033U",
+/*flr*/                "\033\n",
+/*bdon*/       "",
+/*bdoff*/      "",
+/*ploton*/     "\0333",
+/*plotoff*/    "\0334",
+/*up*/         "\033\n",
+/*down*/       "\n",
+/*right*/      " ",
+/*left*/       "\b",
+/*codetab*/
+#include "code.300"
diff --git a/usr/src/cmd/troff/term/tab450X.c b/usr/src/cmd/troff/term/tab450X.c
new file mode 100644 (file)
index 0000000..687afb2
--- /dev/null
@@ -0,0 +1,59 @@
+#define INCH 240
+/*
+DASI300S
+nroff driving tables
+width and code tables
+*/
+
+struct {
+       int bset;
+       int breset;
+       int Hor;
+       int Vert;
+       int Newline;
+       int Char;
+       int Em;
+       int Halfline;
+       int Adj;
+       char *twinit;
+       char *twrest;
+       char *twnl;
+       char *hlr;
+       char *hlf;
+       char *flr;
+       char *bdon;
+       char *bdoff;
+       char *ploton;
+       char *plotoff;
+       char *up;
+       char *down;
+       char *right;
+       char *left;
+       char *codetab[256-32];
+       int zzz;
+       } t = {
+/*bset*/       0,
+/*breset*/     0177420,
+/*Hor*/                INCH/60,
+/*Vert*/       INCH/48,
+/*Newline*/    INCH/6,
+/*Char*/       INCH/10,
+/*Em*/         INCH/10,
+/*Halfline*/   INCH/12,
+/*Adj*/                INCH/10,
+/*twinit*/     "\0334",
+/*twrest*/     "\0334",
+/*twnl*/       "\015\n",
+/*hlr*/                "\033D",
+/*hlf*/                "\033U",
+/*flr*/                "\033\n",
+/*bdon*/       "",
+/*bdoff*/      "",
+/*ploton*/     "\0333",
+/*plotoff*/    "\0334",
+/*up*/         "\033\n",
+/*down*/       "\n",
+/*right*/      " ",
+/*left*/       "\b",
+/*codetab*/
+#include "code.300"
diff --git a/usr/src/cmd/troff/term/tabtn300.c b/usr/src/cmd/troff/term/tabtn300.c
new file mode 100644 (file)
index 0000000..fa1934e
--- /dev/null
@@ -0,0 +1,269 @@
+#define INCH 240
+/*
+TTY M37
+nroff driving tables
+width and code tables
+*/
+
+struct {
+       int bset;
+       int breset;
+       int Hor;
+       int Vert;
+       int Newline;
+       int Char;
+       int Em;
+       int Halfline;
+       int Adj;
+       char *twinit;
+       char *twrest;
+       char *twnl;
+       char *hlr;
+       char *hlf;
+       char *flr;
+       char *bdon;
+       char *bdoff;
+       char *ploton;
+       char *plotoff;
+       char *up;
+       char *down;
+       char *right;
+       char *left;
+       char *codetab[256-32];
+       int zzz;
+       } t = {
+/*bset*/       0,
+/*breset*/     0,
+/*Hor*/                INCH/10,
+/*Vert*/       INCH/6,
+/*Newline*/    INCH/6,
+/*Char*/       INCH/10,
+/*Em*/         INCH/10,
+/*Halfline*/   INCH/12,
+/*Adj*/                INCH/10,
+/*twinit*/     "",
+/*twrest*/     "",
+/*twnl*/       "\n",
+/*hlr*/                "",
+/*hlf*/                "",
+/*flr*/                "",
+/*bdon*/       "",
+/*bdoff*/      "",
+/*ploton*/     "",
+/*plotoff*/    "",
+/*up*/         "",
+/*down*/       "",
+/*right*/      "",
+/*left*/       "",
+/*codetab*/
+"\001 ",       /*space*/
+"\001!",       /*!*/
+"\001\"",      /*"*/
+"\001#",       /*#*/
+"\001$",       /*$*/
+"\001%",       /*%*/
+"\001&",       /*&*/
+"\001'",       /*' close*/
+"\001(",       /*(*/
+"\001)",       /*)*/
+"\001*",       /***/
+"\001+",       /*+*/
+"\001,",       /*,*/
+"\001-",       /*- hyphen*/
+"\001.",       /*.*/
+"\001/",       /*/*/
+"\2010",       /*0*/
+"\2011",       /*1*/
+"\2012",       /*2*/
+"\2013",       /*3*/
+"\2014",       /*4*/
+"\2015",       /*5*/
+"\2016",       /*6*/
+"\2017",       /*7*/
+"\2018",       /*8*/
+"\2019",       /*9*/
+"\001:",       /*:*/
+"\001;",       /*;*/
+"\001<",       /*<*/
+"\001=",       /*=*/
+"\001>",       /*>*/
+"\001?",       /*?*/
+"\001@",       /*@*/
+"\201A",       /*A*/
+"\201B",       /*B*/
+"\201C",       /*C*/
+"\201D",       /*D*/
+"\201E",       /*E*/
+"\201F",       /*F*/
+"\201G",       /*G*/
+"\201H",       /*H*/
+"\201I",       /*I*/
+"\201J",       /*J*/
+"\201K",       /*K*/
+"\201L",       /*L*/
+"\201M",       /*M*/
+"\201N",       /*N*/
+"\201O",       /*O*/
+"\201P",       /*P*/
+"\201Q",       /*Q*/
+"\201R",       /*R*/
+"\201S",       /*S*/
+"\201T",       /*T*/
+"\201U",       /*U*/
+"\201V",       /*V*/
+"\201W",       /*W*/
+"\201X",       /*X*/
+"\201Y",       /*Y*/
+"\201Z",       /*Z*/
+"\001[",       /*[*/
+"\001\\",      /*\*/
+"\001]",       /*]*/
+"\001^",       /*^*/
+"\001_",       /*_ dash*/
+"\001`",       /*` open*/
+"\201a",       /*a*/
+"\201b",       /*b*/
+"\201c",       /*c*/
+"\201d",       /*d*/
+"\201e",       /*e*/
+"\201f",       /*f*/
+"\201g",       /*g*/
+"\201h",       /*h*/
+"\201i",       /*i*/
+"\201j",       /*j*/
+"\201k",       /*k*/
+"\201l",       /*l*/
+"\201m",       /*m*/
+"\201n",       /*n*/
+"\201o",       /*o*/
+"\201p",       /*p*/
+"\201q",       /*q*/
+"\201r",       /*r*/
+"\201s",       /*s*/
+"\201t",       /*t*/
+"\201u",       /*u*/
+"\201v",       /*v*/
+"\201w",       /*w*/
+"\201x",       /*x*/
+"\201y",       /*y*/
+"\201z",       /*z*/
+"\001{",       /*{*/
+"\001|",       /*|*/
+"\001}",       /*}*/
+"\001~",       /*~*/
+"\000\0",      /*nar sp*/
+"\001-",        /*hyphen*/
+"\001o\b+",     /*bullet*/
+"\002[]",       /*square*/
+"\001-",        /*3/4 em*/
+"\001_",        /*rule*/
+"\000\0",       /*1/4*/
+"\000\0",       /*1/2*/
+"\000\0",       /*3/4*/
+"\001-",        /*minus*/
+"\202fi",       /*fi*/
+"\202fl",       /*fl*/
+"\202ff",       /*ff*/
+"\203ffi",      /*ffi*/
+"\203ffl",      /*ffl*/
+"\000\0",       /*degree*/
+"\000\0",       /*dagger*/
+"\000\0",       /*section*/
+"\001'",        /*foot mark*/
+"\001'",        /*acute accent*/
+"\001`",        /*grave accent*/
+"\001_",        /*underrule*/
+"\001/",        /*slash (longer)*/
+"\000\0",      /*half narrow space*/
+"\001 ",       /*unpaddable space*/
+"\000", /*alpha*/
+"\000", /*beta*/
+"\000", /*gamma*/
+"\000", /*delta*/
+"\000", /*epsilon*/
+"\000", /*zeta*/
+"\000", /*eta*/
+"\000", /*theta*/
+"\201i",        /*iota*/
+"\201k",        /*kappa*/
+"\000", /*lambda*/
+"\000", /*mu*/
+"\000", /*nu*/
+"\000", /*xi*/
+"\201o",        /*omicron*/
+"\000", /*pi*/
+"\000", /*rho*/
+"\000", /*sigma*/
+"\000", /*tau*/
+"\201v",        /*upsilon*/
+"\000", /*phi*/
+"\201x",        /*chi*/
+"\000", /*psi*/
+"\000", /*omega*/
+"\000", /*Gamma*/
+"\000", /*Delta*/
+"\000", /*Theta*/
+"\000", /*Lambda*/
+"\000\0",       /*Xi*/
+"\000", /*Pi*/
+"\000", /*Sigma*/
+"\000\0",       /**/
+"\201Y",        /*Upsilon*/
+"\000", /*Phi*/
+"\000", /*Psi*/
+"\000", /*Omega*/
+"\000\0",       /*square root*/
+"\000\0",       /*terminal sigma*/
+"\000\0",       /*root en*/
+"\001>\b_",     /*>=*/
+"\001<\b_",     /*<=*/
+"\001=\b_",     /*identically equal*/
+"\001-",        /*equation minus*/
+"\001=\b~",     /*approx =*/
+"\000\0",       /*approximates*/
+"\001=\b/",     /*not equal*/
+"\002->",       /*right arrow*/
+"\002<-",       /*left arrow*/
+"\001|\b^",     /*up arrow*/
+"\000\0",       /*down arrow*/
+"\001=",        /*equation equal*/
+"\001x",        /*multiply*/
+"\001/",        /*divide*/
+"\001+\b_",     /*plus-minus*/
+"\001U",        /*cup (union)*/
+"\000\0",       /*cap (intersection)*/
+"\000\0",       /*subset of*/
+"\000\0",       /*superset of*/
+"\000\0",       /*improper subset*/
+"\000\0",       /* improper superset*/
+"\002oo",       /*infinity*/
+"\000", /*partial derivative*/
+"\000", /*gradient*/
+"\000", /*not*/
+"\000", /*integral sign*/
+"\000\0",       /*proportional to*/
+"\000\0",       /*empty set*/
+"\000\0",       /*member of*/
+"\001+",        /*equation plus*/
+"\001r\bO",     /*registered*/
+"\001c\bO",     /*copyright*/
+"\001|",        /*box rule */
+"\001c\b/",     /*cent sign*/
+"\000\0",       /*dbl dagger*/
+"\000\0",       /*right hand*/
+"\001*",        /*left hand*/
+"\001*",        /*math * */
+"\000\0",       /*bell system sign*/
+"\001|",        /*or (was star)*/
+"\001O",        /*circle*/
+"\001|",        /*left top (of big curly)*/
+"\001|",        /*left bottom*/
+"\001|",        /*right top*/
+"\001|",        /*right bot*/
+"\001|",        /*left center of big curly bracket*/
+"\001|",        /*right center of big curly bracket*/
+"\001|",       /*bold vertical*/
+"\001|",       /*left floor (left bot of big sq bract)*/
+"\001|",       /*right floor (rb of ")*/
+"\001|",       /*left ceiling (lt of ")*/
+"\001|"};      /*right ceiling (rt of ")*/
diff --git a/usr/src/cmd/uudiff/lenrem.c b/usr/src/cmd/uudiff/lenrem.c
new file mode 100644 (file)
index 0000000..1ee56e9
--- /dev/null
@@ -0,0 +1,9 @@
+main(argc,argv)
+       char *argv[];
+{
+/* args: 1 is name to fix, 2 is this directory */
+if (argv[1][0] == '/')
+       printf("%s\n",argv[1]);
+else
+       printf("%s/%s\n", argv[2], argv[1]);
+}
diff --git a/usr/src/cmd/uudiff/locpart.c b/usr/src/cmd/uudiff/locpart.c
new file mode 100644 (file)
index 0000000..e0a7176
--- /dev/null
@@ -0,0 +1,8 @@
+main(argc,argv)
+       char *argv[];
+{
+char *p;
+for (p=argv[1]; *p; p++);
+while (*p != '/') p--;
+printf("%s\n", p+1);
+}
diff --git a/usr/src/cmd/uudiff/printable.c b/usr/src/cmd/uudiff/printable.c
new file mode 100644 (file)
index 0000000..2c94072
--- /dev/null
@@ -0,0 +1,12 @@
+main(argc,argv)
+       char *argv[];
+{
+char b[512], *p;
+int f, c;
+f = open(argv[1], 0);
+if (f<0) return(1);
+p = b + read(f, b, 512);
+while (p>b)
+       if ( (c= *--p) ==0 || (c&0200) ) return(1);
+return(0);
+}
diff --git a/usr/src/cmd/uudiff/remdiff b/usr/src/cmd/uudiff/remdiff
new file mode 100755 (executable)
index 0000000..e2aa342
--- /dev/null
@@ -0,0 +1,113 @@
+: 'usage: uudiff directory-local sys![directory-remote]'
+
+set UUDIR=/usr/src/cmd/uudiff
+set UUCP=/usr/src/cmd/uucp
+set SPOOL=/usr/tmp/uucp
+set UNIXNAME=vax1
+set DIFF=YES
+case $1 in
+       -d) set DIFF=NO; shift;;
+esac
+
+set HERE=`pwd`
+set ME=`getuid`
+
+set LOCAL=$1
+set SYS=`echo $2 | sed "s/!.*//"`
+if [ $SYS = $2 ]
+       then set SYS=$UNIXNAME
+fi
+
+set REMOTE=`echo $2 | sed "s/.*!//"`
+if [ x$REMOTE = x ]
+       then set $REMOTE = $LOCAL
+fi
+
+set LOCAL=`$UUDIR/lenrem $LOCAL $HERE`
+set REMOTE=`$UUDIR/lenrem $REMOTE $HERE`
+set LOCDIR=$LOCAL
+set DIR=YES
+set REMDIR=$REMOTE
+if [ -f $LOCDIR ]
+       then
+       set LOCDIR=`$UUDIR/trim $LOCDIR`
+       set REMDIR=`$UUDIR/trim $REMDIR`
+       set DIR=NO
+       fi
+
+cat >zza$pid <<!
+$UUCP/filsum $REMOTE >zzb$pid
+!
+uucp -f zza$pid $SYS!ef$pid
+$UUCP/tdemon >>/$UUCP/tmess &
+if [ $SYS = research ]
+       then
+       cat >$SPOOL/cq$pid <<%
+zzb$pid
+
+cp zzb$pid $HERE/zzc$pid
+%
+else
+uucp -f -w $SYS!zzb$pid $HERE/zzc$pid
+fi
+$UUCP/tdemon >>/$UUCP/tmess &
+$UUCP/filsum $LOCAL >zzd$pid
+cat >$SPOOL/cz$pid <<!
+$HERE/zzc$pid
+
+chdir $HERE
+cat >zzy$pid <<%
+rm zzb$pid
+%
+uucp -f zzy$pid $SYS!ey$pid
+rm zzy$pid
+cat >uudiff$pid <<%
+uudiff comparison of
+  $LOCAL here
+with
+  $REMOTE on system $SYS
+
+
+
+%
+$UUDIR/run1 zzd$pid zzc$pid  zzl$pid  | sort >>uudiff$pid
+
+cat >zzm$pid <<%
+cg$pid
+%
+cat >zzn$pid <<%
+
+chdir $HERE
+%
+
+if [ $DIFF = YES ]
+       then
+       if [ $DIR = NO ]
+               then $UUDIR/locpart $LOCAL >zzl$pid
+               fi
+       for f in \`cat zzl${pid}\`
+       do
+               if $UUDIR/printable $LOCDIR/\$f
+               then
+               if [ $DIR = YES ]
+                       then uucp $SYS!$REMDIR/\$f \$f.$pid
+                       else uucp $SYS!$REMOTE \$f.$pid
+                       fi
+               echo $HERE/\$f.$pid >>zzm$pid
+               cat >>zzn$pid <<%
+
+echo >>uudiff$pid
+echo DIFF of \$f: '(< here, > remote)' >>uudiff$pid
+diff $LOCDIR/\$f \$f.$pid >>uudiff$pid
+%
+               fi
+       done
+fi
+
+cat >>zzn$pid <<%
+echo uudiff$pid arrived in $HERE "|" mail $ME
+rm zz?$pid
+%
+cat zzm$pid zzn$pid >>$SPOOL/cg$pid
+!
+$UUCP/tdemon >>/$UUCP/tmess 
diff --git a/usr/src/cmd/uudiff/run1.c b/usr/src/cmd/uudiff/run1.c
new file mode 100644 (file)
index 0000000..60e6553
--- /dev/null
@@ -0,0 +1,76 @@
+# include "stdio.h"
+# define LAST "\177\177"
+main (argc,argv)
+       char *argv[];
+{
+       FILE *rem, *loc, *cfil;
+       char namel[100], namer[100];
+       char cname[20], zname[20];
+       int mr, ml;
+       long suml, sumr;
+ml=mr=1;
+loc = fopen(argv[1], "r");
+rem = fopen (argv[2], "r");
+cfil = fopen (argv[3], "w");
+ml = fetch (loc, namel, &suml, ml);
+mr = fetch (rem, namer, &sumr, mr);
+while ( ml || mr)
+       {
+       int x;
+       x = strcmp(namel, namer);
+       if (x>0) x=1;
+       if (x<0) x= -1;
+       switch(x)
+               {
+               case -1: /* name l lower */
+                       /* check that file is not our zz* tempfile */
+                       if (notmp(namel, argv[2]))
+                       printf("Missing on remote system: %s\n",namel);
+                       ml = fetch (loc, namel, &suml, ml);
+                       continue;
+               case 0: /* match names */
+                       if (strcmp(namel, LAST)==0)
+                               exit(0);
+                       if (suml == sumr)
+                               printf("Presumed identical: %s\n",namel);
+                       else
+                               {
+                               printf("Differ: %s\n", namel);
+                               fprintf(cfil, "%s\n", namel);
+                               }
+                       ml=fetch(loc, namel, &suml, ml);
+                       mr=fetch(rem, namer, &sumr, mr);
+                       continue;
+               case 1: /* name 2 lower */
+                       printf("Extraneous file on remote system: %s\n",namer);
+                       mr=fetch(rem, namer, &sumr, mr);
+                       continue;
+               default:
+                       printf("illegal case %d\n", strcmp(namel,namer));
+                       exit(0);
+               }
+       }
+}
+fetch (f, s, lp, m)
+       FILE *f;
+       char *s;
+       long *lp;
+{
+char b[200];
+if (m==0 ||fgets(b, 200, f)==0)
+       {
+       strcpy (s, LAST);
+       return (0);
+       }
+sscanf(b, "%s %lo", s, lp);
+return (1);
+}
+notmp(s1, s2)
+       char *s1, *s2;
+{
+char bf1[20], bf2[20];
+strcpy (bf1, s1);
+strcpy (bf2, s2);
+bf1[2]= bf2[2] = '0';
+return (strcmp(bf1, bf2));
+}
diff --git a/usr/src/cmd/uudiff/trim.c b/usr/src/cmd/uudiff/trim.c
new file mode 100644 (file)
index 0000000..c989966
--- /dev/null
@@ -0,0 +1,15 @@
+# if interdata
+# include "stdio.h"
+# endif
+main(argc,argv)
+       char *argv[];
+{
+char *nm, *p;
+p = nm = argv[1];
+while (*p) p++;
+while (*p != '/') p--;
+if (p==nm) p++;
+*p = 0;
+printf("%s\n", nm);
+exit(0);
+}
diff --git a/usr/src/cmd/xsend/enroll.c b/usr/src/cmd/xsend/enroll.c
new file mode 100644 (file)
index 0000000..f2e8e14
--- /dev/null
@@ -0,0 +1,36 @@
+#include "xmail.h"
+#include "pwd.h"
+#include "sys/types.h"
+MINT *a[42], *x, *b, *one, *c64, *t45, *z, *q, *r, *two, *t15;
+char buf[256];
+char maildir[] = { "/usr/spool/secretmail"};
+main()
+{
+       int uid, i;
+       FILE *fd;
+       char *myname, fname[128];
+       uid = getuid();
+       myname = getlogin();
+       if(myname == NULL)
+               myname = getpwuid(uid)->pw_name;
+       sprintf(fname, "%s/%s.key", maildir, myname);
+       comminit();
+       setup(getpass("Gimme key: "));
+       mkb();
+       mkx();
+#ifdef debug
+       omout(b);
+       omout(x);
+#endif
+       mka();
+       i = creat(fname, 0644);
+       if(i<0)
+       {       perror("fname");
+               exit(1);
+       }
+       close(i);
+       fd = fopen(fname, "w");
+       for(i=0; i<42; i++)
+               nout(a[i], fd);
+       exit(0);
+}
diff --git a/usr/src/cmd/xsend/lib.c b/usr/src/cmd/xsend/lib.c
new file mode 100644 (file)
index 0000000..22508a7
--- /dev/null
@@ -0,0 +1,109 @@
+#include "xmail.h"
+MINT *x, *b, *one, *c64, *t45, *z, *q, *r, *two, *t15;
+MINT *a[42];
+setup(s) char *s;
+{      int pf[2];
+       strncpy(buf, s, 10);
+       while(*s) *s++ = 0;
+       pipe(pf);
+       if(fork()==0)
+       {
+               close(0);
+               close(1);
+               dup(pf[0]);
+               dup(pf[1]);
+               execl("/usr/lib/makekey", "-", 0);
+               execl("/lib/makekey", "-", 0);
+               exit(1);
+       }
+       write(pf[1], buf, 10);
+       wait((int *)NULL);
+       if(read(pf[0], buf, 13) != 13)
+       {       fprintf(stderr, "enroll: cannot generate key\n");
+               exit(1);
+       }
+}
+mkx()
+{      int i, j;
+       for(i=0; i<4; i++)
+       {       mult(x, t15, x);
+               *z->val = (short)(rand() ^ buf[i]);
+               madd(x, z, x);
+       }
+       mdiv(x, b, q, x);
+       for(;;)
+       {       gcd(b, x, q);
+               if(q->len == 1 && q->val[0] == 1)
+                       return;
+               madd(x, one, x);
+       }
+}
+mka()
+{      int i, j;
+       for(i=0; i<42; i++)
+               a[i] = itom(1);
+       for(i=j=0; i<42; i++, j++)
+       {       *z->val = (short)rand()&00;
+               mult(a[i], z, a[i]);
+               mult(a[i], t45, a[i]);
+               rpow(two, j, q);
+               if( i%14 == 6) j++;
+               madd(a[i], q, a[i]);
+               mult(a[i], t15, a[i]);
+               *z->val = (short)rand()&0777;
+               madd(a[i], z, a[i]);
+               mdiv(a[i], b, q, a[i]);
+       }
+       for(i=0; i<42; i++)
+               mult(a[i], x, a[i]);
+       for(i=0; i<42; i++)
+       {       mdiv(a[i], b, q, a[i]);
+       }
+}
+mkb()
+{      int i, c;
+       unsigned seed;
+       seed = 123;
+       for(i=0; i<13; i++)
+               seed = seed*buf[i] + i;
+       srand(seed);
+       *b->val = 04 + (rand()&03);
+       for(i=0; i<11; i++)
+       {       *z->val = (buf[i+2] + rand()) & 077;
+               mult(b, c64, b);
+               madd(b, z, b);
+       }
+}
+comminit()
+{      int i;
+       x = itom(0);
+       b = itom(1);
+       one = itom(1);
+       two = itom(2);
+       c64 = itom(64);
+       t45 = itom(1);
+       t15 = itom(1);
+       rpow(two, 45, t45);
+       rpow(two, 15, t15);
+       z = itom(1);
+       q = itom(1);
+}
+#ifndef debug
+nout(a, fd) MINT *a; FILE *fd;
+{
+       fwrite(&a->len, sizeof(int), 1, fd);
+       fwrite(a->val, sizeof(short), a->len, fd);
+}
+nin(a, fd) MINT *a; FILE *fd;
+{
+       xfree(a);
+       fread(&a->len, sizeof(int), 1, fd);
+       a->val = xalloc(a->len, "nin");
+       fread(a->val, sizeof(short), a->len, fd);
+}
+#endif
+xfatal(s) char *s;
+{
+       fprintf(stderr, "%s\n", s);
+       exit(1);
+}
diff --git a/usr/src/cmd/xsend/xget.c b/usr/src/cmd/xsend/xget.c
new file mode 100644 (file)
index 0000000..93b06aa
--- /dev/null
@@ -0,0 +1,139 @@
+#include "xmail.h"
+#include "sys/types.h"
+#include "sys/dir.h"
+#include "ctype.h"
+#include "pwd.h"
+#include "sys/stat.h"
+char *myname;
+int uid;
+struct direct dbuf;
+char *maildir = "/usr/spool/secretmail/";
+FILE *kf, *mf, *df;
+MINT *x, *b, *one, *t45, *z, *q, *r;
+MINT *two, *t15, *mbuf;
+char buf[256], line[128];
+#define MXF 100
+int fnum[MXF], fcnt;
+struct stat stbuf;
+main()
+{      int i;
+       char *p;
+       uid = getuid();
+       myname = getlogin();
+       if(myname == NULL)
+               myname = getpwuid(uid)->pw_name;
+       comminit();
+       mbuf = itom(0);
+       files();
+       setup(getpass("Key: "));
+       mkb();
+       mkx();
+#ifndef debug
+       invert(x, b, x);
+#else
+       invert(x, b, z);
+       mult(x, z, z);
+       mdiv(z, b, q, z);
+       omout(z);
+       invert(x, b, x);
+#endif
+       for(i=0; i<fcnt; i++)
+       {       sprintf(line, "%s%s.%d", maildir, myname, fnum[i]);
+               if(stat(line, &stbuf)<0)
+               {       perror(line);
+                       continue;
+               }
+               if(stbuf.st_size == 0)
+               {       printf("zero length mail file\n");
+                       unlink(line);
+                       continue;
+               }
+               if((mf = fopen(line, "r"))==NULL)
+               {       perror(line);
+                       continue;
+               }
+               decipher(mf, stdout);
+       cmnd:
+               printf("? ");
+               fgets(buf, sizeof(buf), stdin);
+               if(feof(stdin)) exit(0);
+               switch(buf[0])
+               {
+               case 'q':
+                       exit(0);
+               case 'n':
+               case 'd':
+               case '\n':
+                       unlink(line);
+                       fclose(mf);
+                       break;
+               case '!':
+                       system(buf+1);
+                       printf("!\n");
+                       goto cmnd;
+               case 's':
+               case 'w':
+                       rewind(mf);
+                       if(buf[1] == '\n' || buf[1] == '\0')
+                               strcpy(buf, "s mbox\n");
+                       for(p=buf; !isspace(*p); p++);
+                       for(; isspace(*p); p++);
+                       p[strlen(p)-1] = 0;
+                       kf = fopen(p, "a");
+                       if(kf == NULL)
+                       {       perror(p);
+                               break;
+                       }
+                       decipher(mf, kf);
+                       fclose(mf);
+                       fclose(kf);
+                       unlink(line);
+                       break;
+               }
+       }
+       exit(0);
+}
+icmp(a, b) int *a, *b;
+{
+       return(*a - *b);
+}
+files()
+{      int i;
+       if((df = fopen(maildir, "r")) == NULL)
+       {       perror(maildir);
+               exit(1);
+       }
+       strcpy(line, myname);
+       strcat(line, ".%d");
+       for(; !feof(df);)
+       {       fread(&dbuf, sizeof(dbuf), 1, df);
+               if(feof(df)) break;
+               if(dbuf.d_ino == 0) continue;
+               if(sscanf(dbuf.d_name, line, &i) != 1)
+                       continue;
+               if(fcnt >= MXF)
+                       break;
+               fnum[fcnt++] = i;
+       }
+       if(fcnt == 0)
+       {       printf("no secret mail\n");
+               exit(0);
+       }
+       qsort(fnum, fcnt, sizeof(int), icmp);
+}
+decipher(u, w) FILE *u, *w;
+{      int i;
+       short a;
+       for(;;)
+       {       nin(mbuf, u);
+               if(feof(u)) break;
+               mult(mbuf, x, mbuf);
+               mdiv(mbuf, b, q, mbuf);
+               for(i=1; i<=3; i++)
+               {       a = mbuf->val[i];
+                       putc(a&0177, w);
+                       a >>= 8;
+                       putc(a&0177, w);
+               }
+       }
+}
diff --git a/usr/src/cmd/xsend/xmail.h b/usr/src/cmd/xsend/xmail.h
new file mode 100644 (file)
index 0000000..1d637a3
--- /dev/null
@@ -0,0 +1,8 @@
+#include <stdio.h>
+#include <mp.h>
+extern MINT *x, *b, *one, *c64, *t45, *z, *q, *r, *two, *t15;
+extern char buf[256];
+#ifdef debug
+#define nin(x, y) m_in(x, 8, y)
+#define nout(x, y) m_out(x, 8, y)
+#endif
diff --git a/usr/src/cmd/xsend/xsend.c b/usr/src/cmd/xsend/xsend.c
new file mode 100644 (file)
index 0000000..cd53806
--- /dev/null
@@ -0,0 +1,122 @@
+#include "xmail.h"
+#include "sys/types.h"
+#include "pwd.h"
+#include "sys/stat.h"
+#include "sys/dir.h"
+extern int errno;
+struct stat stbuf;
+int uid, destuid;
+char *myname, *dest, *keyfile[128], line[128];
+struct direct dbuf;
+char *maildir = "/usr/spool/secretmail/";
+FILE *kf, *mf, *df;
+MINT *a[42], *cd[6][128];
+MINT *msg;
+char buf[256], eof;
+int dbg;
+main(argc, argv) char **argv;
+{      int i, nmax, len;
+       char *p;
+       long now;
+       if(argc != 2)
+               xfatal("mail to exactly one person");
+       uid = getuid();
+       p =getlogin();
+       if(p == NULL)
+               p = getpwuid(uid)->pw_name;
+       myname = malloc(strlen(p)+1);
+       strcpy(myname, p);
+       dest = argv[1];
+       strcpy(keyfile, maildir);
+       strcat(keyfile, dest);
+       strcat(keyfile, ".key");
+       if(stat(keyfile, &stbuf) <0)
+               xfatal("addressee not enrolled");
+       destuid = getpwnam(dest)->pw_uid;
+       if(destuid != stbuf.st_uid)
+               fprintf(stderr, "warning: addressee's key file may be subverted\n");
+       errno = 0;
+       kf = fopen(keyfile, "r");
+       if(kf == NULL)
+               xfatal("addressee's key weird");
+       df = fopen(maildir, "r");
+       if(df == NULL)
+       {       perror(maildir);
+               exit(1);
+       }
+       strcpy(line, dest);
+       strcat(line, ".%d");
+       nmax = -1;
+       for(; !feof(df);)
+       {       fread(&dbuf, sizeof(dbuf), 1, df);
+               if(dbuf.d_ino == 0) continue;
+               if(sscanf(dbuf.d_name, line, &i) != 1)
+                       continue;
+               if(i>nmax) nmax = i;
+       }
+       nmax ++;
+       for(i=0; i<10; i++)
+       {       sprintf(line, "%s%s.%d", maildir, dest, nmax+i);
+               if(creat(line, 0666) >= 0) break;
+       }
+       if(i==10) xfatal("cannot create mail file");
+       mf = fopen(line, "w");
+       init();
+       time(&now);
+       sprintf(buf, "From %s %s", myname, ctime(&now) );
+#ifdef DBG
+       dbg = 1;
+#endif
+       run();
+       sprintf(buf, "mail %s <%snotice", dest, maildir);
+       system(buf);
+       exit(0);
+}
+mkcd()
+{      int i, j, k, n;
+       for(i=0; i<42; i++)
+               nin(a[i], kf);
+       fclose(kf);
+       for(i=0; i<6; i++)
+       for(j=0; j<128; j++)
+               for(k=j, n=0; k>0 && n<7; n++, k>>=1)
+                       if(k&01) madd(cd[i][j], a[7*i+n], cd[i][j]);
+}
+encipher(s) char s[6];
+{      int i;
+       msub(msg, msg, msg);
+       for(i=0; i<6; i++)
+               madd(msg, cd[i][s[i]&0177], msg);
+}
+init()
+{      int i, j;
+       msg = itom(0);
+       for(i=0; i<42; i++)
+               a[i] = itom(0);
+       for(i=0; i<6; i++)
+       for(j=0; j<128; j++)
+               cd[i][j] = itom(0);
+       mkcd();
+}
+run()
+{      char *p;
+       int i, len, eof = 0;
+       for(;;)
+       {       len = strlen(buf);
+               for(i=0; i<len/6; i++)
+               {
+                       encipher(buf+6*i);
+                       nout(msg, mf);
+               }
+               p = buf;
+               for(i *= 6; i<len; i++)
+                       *p++ = buf[i];
+               if(eof) return;
+               fgets(p, sizeof(buf)-6, stdin);
+               if(strcmp(p, ".\n") == 0 || feof(stdin))
+               {       for(i=0; i<6; i++) *p++ = ' ';
+                       *p = 0;
+                       eof = 1;
+               }
+       }
+}
diff --git a/usr/src/cmd/yacc/dextern b/usr/src/cmd/yacc/dextern
new file mode 100644 (file)
index 0000000..dca3b2e
--- /dev/null
@@ -0,0 +1,259 @@
+# include <stdio.h>
+# include <ctype.h>
+# include "files"
+
+       /*  MANIFEST CONSTANT DEFINITIONS */
+
+       /* base of nonterminal internal numbers */
+# define NTBASE 010000
+
+       /* internal codes for error and accept actions */
+
+# define ERRCODE  8190
+# define ACCEPTCODE 8191
+
+       /* sizes and limits */
+
+# ifdef HUGE
+# define ACTSIZE 12000
+# define MEMSIZE 12000
+# define NSTATES 750
+# define NTERMS 127
+# define NPROD 600
+# define NNONTERM 300
+# define TEMPSIZE 1200
+# define CNAMSZ 5000
+# define LSETSIZE 600
+# define WSETSIZE 350
+# endif
+
+# ifdef MEDIUM
+# define ACTSIZE 4000
+# define MEMSIZE 5200
+# define NSTATES 600
+# define NTERMS 127
+# define NPROD 400
+# define NNONTERM 200
+# define TEMPSIZE 800
+# define CNAMSZ 4000
+# define LSETSIZE 450
+# define WSETSIZE 250
+# endif
+
+# define NAMESIZE 50
+# define NTYPES 63
+
+# ifdef WORD32
+# define TBITSET ((32+NTERMS)/32)
+
+       /* bit packing macros (may be machine dependent) */
+# define BIT(a,i) ((a)[(i)>>5] & (1<<((i)&037)))
+# define SETBIT(a,i) ((a)[(i)>>5] |= (1<<((i)&037)))
+
+       /* number of words needed to hold n+1 bits */
+# define NWORDS(n) (((n)+32)/32)
+
+# else
+
+# define TBITSET ((16+NTERMS)/16)
+
+       /* bit packing macros (may be machine dependent) */
+# define BIT(a,i) ((a)[(i)>>4] & (1<<((i)&017)))
+# define SETBIT(a,i) ((a)[(i)>>4] |= (1<<((i)&017)))
+
+       /* number of words needed to hold n+1 bits */
+# define NWORDS(n) (((n)+16)/16)
+# endif
+
+       /* relationships which must hold:
+       TBITSET ints must hold NTERMS+1 bits...
+       WSETSIZE >= NNONTERM
+       LSETSIZE >= NNONTERM
+       TEMPSIZE >= NTERMS + NNONTERMs + 1
+       TEMPSIZE >= NSTATES
+       */
+
+       /* associativities */
+
+# define NOASC 0  /* no assoc. */
+# define LASC 1  /* left assoc. */
+# define RASC 2  /* right assoc. */
+# define BASC 3  /* binary assoc. */
+
+       /* flags for state generation */
+
+# define DONE 0
+# define MUSTDO 1
+# define MUSTLOOKAHEAD 2
+
+       /* flags for a rule having an action, and being reduced */
+
+# define ACTFLAG 04
+# define REDFLAG 010
+
+       /* output parser flags */
+# define YYFLAG1 (-1000)
+
+       /* macros for getting associativity and precedence levels */
+
+# define ASSOC(i) ((i)&03)
+# define PLEVEL(i) (((i)>>4)&077)
+# define TYPE(i)  ((i>>10)&077)
+
+       /* macros for setting associativity and precedence levels */
+
+# define SETASC(i,j) i|=j
+# define SETPLEV(i,j) i |= (j<<4)
+# define SETTYPE(i,j) i |= (j<<10)
+
+       /* looping macros */
+
+# define TLOOP(i) for(i=1;i<=ntokens;++i)
+# define NTLOOP(i) for(i=0;i<=nnonter;++i)
+# define PLOOP(s,i) for(i=s;i<nprod;++i)
+# define SLOOP(i) for(i=0;i<nstate;++i)
+# define WSBUMP(x) ++x
+# define WSLOOP(s,j) for(j=s;j<cwp;++j)
+# define ITMLOOP(i,p,q) q=pstate[i+1];for(p=pstate[i];p<q;++p)
+# define SETLOOP(i) for(i=0;i<tbitset;++i)
+
+       /* I/O descriptors */
+
+extern FILE * finput;          /* input file */
+extern FILE * faction;         /* file for saving actions */
+extern FILE *fdefine;          /* file for # defines */
+extern FILE * ftable;          /* y.tab.c file */
+extern FILE * ftemp;           /* tempfile to pass 2 */
+extern FILE * foutput;         /* y.output file */
+
+       /* structure declarations */
+
+struct looksets {
+       int lset[TBITSET];
+       };
+
+struct item {
+       int *pitem;
+       struct looksets *look;
+       };
+
+struct toksymb {
+       char *name;
+       int value;
+       };
+
+struct ntsymb {
+       char *name;
+       int tvalue;
+       };
+
+struct wset {
+       int *pitem;
+       int flag;
+       struct looksets ws;
+       };
+
+       /* token information */
+
+extern int ntokens ;   /* number of tokens */
+extern struct toksymb tokset[];
+extern int toklev[];   /* vector with the precedence of the terminals */
+
+       /* nonterminal information */
+
+extern int nnonter ;   /* the number of nonterminals */
+extern struct ntsymb nontrst[];
+
+       /* grammar rule information */
+
+extern int nprod ;     /* number of productions */
+extern int *prdptr[];  /* pointers to descriptions of productions */
+extern int levprd[] ;  /* contains production levels to break conflicts */
+
+       /* state information */
+
+extern int nstate ;            /* number of states */
+extern struct item *pstate[];  /* pointers to the descriptions of the states */
+extern int tystate[];  /* contains type information about the states */
+extern int defact[];   /* the default action of the state */
+extern int tstates[];  /* the states deriving each token */
+extern int ntstates[]; /* the states deriving each nonterminal */
+extern int mstates[];  /* the continuation of the chains begun in tstates and ntstates */
+
+       /* lookahead set information */
+
+extern struct looksets lkst[];
+extern int nolook;  /* flag to turn off lookahead computations */
+
+       /* working set information */
+
+extern struct wset wsets[];
+extern struct wset *cwp;
+
+       /* storage for productions */
+
+extern int mem0[];
+extern int *mem;
+
+       /* storage for action table */
+
+extern int amem[];  /* action table storage */
+extern int *memp ;             /* next free action table position */
+extern int indgo[];            /* index to the stored goto table */
+
+       /* temporary vector, indexable by states, terms, or ntokens */
+
+extern int temp1[];
+extern int lineno; /* current line number */
+
+       /* statistics collection variables */
+
+extern int zzgoent ;
+extern int zzgobest ;
+extern int zzacent ;
+extern int zzexcp ;
+extern int zzclose ;
+extern int zzrrconf ;
+extern int zzsrconf ;
+       /* define functions with strange types... */
+
+extern char *cstash();
+extern struct looksets *flset();
+extern char *symnam();
+extern char *writem();
+
+       /* default settings for a number of macros */
+
+       /* name of yacc tempfiles */
+
+# ifndef TEMPNAME
+# define TEMPNAME "yacc.tmp"
+# endif
+
+# ifndef ACTNAME
+# define ACTNAME "yacc.acts"
+# endif
+
+       /* output file name */
+
+# ifndef OFILE
+# define OFILE "y.tab.c"
+# endif
+
+       /* user output file name */
+
+# ifndef FILEU
+# define FILEU "y.output"
+# endif
+
+       /* output file for # defines */
+
+# ifndef FILED
+# define FILED "y.tab.h"
+# endif
+
+       /* command to clobber tempfiles after use */
+
+# ifndef ZAPFILE
+# define ZAPFILE(x) unlink(x)
+# endif
diff --git a/usr/src/cmd/yacc/y1.c b/usr/src/cmd/yacc/y1.c
new file mode 100644 (file)
index 0000000..723f0db
--- /dev/null
@@ -0,0 +1,653 @@
+# include "dextern"
+
+       /* variables used locally */
+
+       /* lookahead computations */
+
+int tbitset;  /* size of lookahead sets */
+struct looksets lkst [ LSETSIZE ];
+int nlset = 0; /* next lookahead set index */
+int nolook = 0; /* flag to suppress lookahead computations */
+struct looksets clset;  /* temporary storage for lookahead computations */
+
+       /* working set computations */
+
+struct wset wsets[ WSETSIZE ];
+struct wset *cwp;
+
+       /* state information */
+
+int nstate = 0;                /* number of states */
+struct item *pstate[NSTATES+2];        /* pointers to the descriptions of the states */
+int tystate[NSTATES];  /* contains type information about the states */
+int indgo[NSTATES];            /* index to the stored goto table */
+int tstates[ NTERMS ]; /* states generated by terminal gotos */
+int ntstates[ NNONTERM ]; /* states generated by nonterminal gotos */
+int mstates[ NSTATES ]; /* chain of overflows of term/nonterm generation lists  */
+
+       /* storage for the actions in the parser */
+
+int amem[ACTSIZE];     /* action table storage */
+int *memp = amem;      /* next free action table position */
+
+       /* other storage areas */
+
+int temp1[TEMPSIZE]; /* temporary storage, indexed by terms + ntokens or states */
+int lineno= 1; /* current input line number */
+int fatfl = 1;         /* if on, error is fatal */
+int nerrors = 0;       /* number of errors */
+
+       /* storage for information about the nonterminals */
+
+int **pres[NNONTERM+2];  /* vector of pointers to productions yielding each nonterminal */
+struct looksets *pfirst[NNONTERM+2];  /* vector of pointers to first sets for each nonterminal */
+int pempty[NNONTERM+1];  /* vector of nonterminals nontrivially deriving e */
+
+main(argc,argv) int argc; char *argv[]; {
+
+       setup(argc,argv); /* initialize and read productions */
+       tbitset = NWORDS(ntokens);
+       cpres(); /* make table of which productions yield a given nonterminal */
+       cempty(); /* make a table of which nonterminals can match the empty string */
+       cpfir(); /* make a table of firsts of nonterminals */
+       stagen(); /* generate the states */
+       output();  /* write the states and the tables */
+       go2out();
+       hideprod();
+       summary();
+       callopt();
+       others();
+       exit(0);
+       }
+
+others(){ /* put out other arrays, copy the parsers */
+       register c, i, j;
+
+       finput = fopen( PARSER, "r" );
+       if( finput == NULL ) error( "cannot find parser %s", PARSER );
+
+       warray( "yyr1", levprd, nprod );
+
+       aryfil( temp1, nprod, 0 );
+       PLOOP(1,i)temp1[i] = prdptr[i+1]-prdptr[i]-2;
+       warray( "yyr2", temp1, nprod );
+
+       aryfil( temp1, nstate, -1000 );
+       TLOOP(i){
+               for( j=tstates[i]; j!=0; j=mstates[j] ){
+                       temp1[j] = tokset[i].value;
+                       }
+               }
+       NTLOOP(i){
+               for( j=ntstates[i]; j!=0; j=mstates[j] ){
+                       temp1[j] = -i;
+                       }
+               }
+       warray( "yychk", temp1, nstate );
+
+       warray( "yydef", defact, nstate );
+
+       /* copy parser text */
+
+       while( (c=getc(finput) ) != EOF ){
+               if( c == '$' ){
+                       if( (c=getc(finput)) != 'A' ) putc( '$', ftable );
+                       else { /* copy actions */
+                               faction = fopen( ACTNAME, "r" );
+                               if( faction == NULL ) error( "cannot reopen action tempfile" );
+                               while( (c=getc(faction) ) != EOF ) putc( c, ftable );
+                               fclose(faction);
+                               ZAPFILE(ACTNAME);
+                               c = getc(finput);
+                               }
+                       }
+               putc( c, ftable );
+               }
+
+       fclose( ftable );
+       }
+
+char *chcopy( p, q )  char *p, *q; {
+       /* copies string q into p, returning next free char ptr */
+       while( *p = *q++ ) ++p;
+       return( p );
+       }
+
+# define ISIZE 400
+char *writem(pp) int *pp; { /* creates output string for item pointed to by pp */
+       int i,*p;
+       static char sarr[ISIZE];
+       char *q;
+
+       for( p=pp; *p>0 ; ++p ) ;
+       p = prdptr[-*p];
+       q = chcopy( sarr, nontrst[*p-NTBASE].name );
+       q = chcopy( q, " : " );
+
+       for(;;){
+               *q++ = ++p==pp ? '_' : ' ';
+               *q = '\0';
+               if((i = *p) <= 0) break;
+               q = chcopy( q, symnam(i) );
+               if( q> &sarr[ISIZE-30] ) error( "item too big" );
+               }
+
+       if( (i = *pp) < 0 ){ /* an item calling for a reduction */
+               q = chcopy( q, "    (" );
+               sprintf( q, "%d)", -i );
+               }
+
+       return( sarr );
+       }
+
+char *symnam(i){ /* return a pointer to the name of symbol i */
+       char *cp;
+
+       cp = (i>=NTBASE) ? nontrst[i-NTBASE].name : tokset[i].name ;
+       if( *cp == ' ' ) ++cp;
+       return( cp );
+       }
+
+struct wset *zzcwp = wsets;
+int zzgoent = 0;
+int zzgobest = 0;
+int zzacent = 0;
+int zzexcp = 0;
+int zzclose = 0;
+int zzsrconf = 0;
+int * zzmemsz = mem0;
+int zzrrconf = 0;
+
+summary(){ /* output the summary on the tty */
+
+       if( foutput!=NULL ){
+               fprintf( foutput, "\n%d/%d terminals, %d/%d nonterminals\n", ntokens, NTERMS,
+                           nnonter, NNONTERM );
+               fprintf( foutput, "%d/%d grammar rules, %d/%d states\n", nprod, NPROD, nstate, NSTATES );
+               fprintf( foutput, "%d shift/reduce, %d reduce/reduce conflicts reported\n", zzsrconf, zzrrconf );
+               fprintf( foutput, "%d/%d working sets used\n", zzcwp-wsets,  WSETSIZE );
+               fprintf( foutput, "memory: states,etc. %d/%d, parser %d/%d\n", zzmemsz-mem0, MEMSIZE,
+                           memp-amem, ACTSIZE );
+               fprintf( foutput, "%d/%d distinct lookahead sets\n", nlset, LSETSIZE );
+               fprintf( foutput, "%d extra closures\n", zzclose - 2*nstate );
+               fprintf( foutput, "%d shift entries, %d exceptions\n", zzacent, zzexcp );
+               fprintf( foutput, "%d goto entries\n", zzgoent );
+               fprintf( foutput, "%d entries saved by goto default\n", zzgobest );
+               }
+       if( zzsrconf!=0 || zzrrconf!=0 ){
+                 fprintf( stdout,"\nconflicts: ");
+                 if( zzsrconf )fprintf( stdout, "%d shift/reduce" , zzsrconf );
+                 if( zzsrconf && zzrrconf )fprintf( stdout, ", " );
+                 if( zzrrconf )fprintf( stdout, "%d reduce/reduce" , zzrrconf );
+                 fprintf( stdout, "\n" );
+                 }
+
+       fclose( ftemp );
+       if( fdefine != NULL ) fclose( fdefine );
+       }
+
+/* VARARGS1 */
+error(s,a1) char *s; { /* write out error comment */
+       
+       ++nerrors;
+       fprintf( stderr, "\n fatal error: ");
+       fprintf( stderr, s,a1);
+       fprintf( stderr, ", line %d\n", lineno );
+       if( !fatfl ) return;
+       summary();
+       exit(1);
+       }
+
+aryfil( v, n, c ) int *v,n,c; { /* set elements 0 through n-1 to c */
+       int i;
+       for( i=0; i<n; ++i ) v[i] = c;
+       }
+
+setunion( a, b ) register *a, *b; {
+       /* set a to the union of a and b */
+       /* return 1 if b is not a subset of a, 0 otherwise */
+       register i, x, sub;
+
+       sub = 0;
+       SETLOOP(i){
+               *a = (x = *a)|*b++;
+               if( *a++ != x ) sub = 1;
+               }
+       return( sub );
+       }
+
+prlook( p ) struct looksets *p;{
+       register j, *pp;
+       pp = p->lset;
+       if( pp == 0 ) fprintf( foutput, "\tNULL");
+       else {
+               fprintf( foutput, " { " );
+               TLOOP(j) {
+                       if( BIT(pp,j) ) fprintf( foutput,  "%s ", symnam(j) );
+                       }
+               fprintf( foutput,  "}" );
+               }
+       }
+
+cpres(){ /* compute an array with the beginnings of  productions yielding given nonterminals
+       The array pres points to these lists */
+       /* the array pyield has the lists: the total size is only NPROD+1 */
+       register **pmem;
+       register c, j, i;
+       static int * pyield[NPROD];
+
+       pmem = pyield;
+
+       NTLOOP(i){
+               c = i+NTBASE;
+               pres[i] = pmem;
+               fatfl = 0;  /* make undefined  symbols  nonfatal */
+               PLOOP(0,j){
+                       if (*prdptr[j] == c) *pmem++ =  prdptr[j]+1;
+                       }
+               if(pres[i] == pmem){
+                       error("nonterminal %s not defined!", nontrst[i].name);
+                       }
+               }
+       pres[i] = pmem;
+       fatfl = 1;
+       if( nerrors ){
+               summary();
+               exit(1);
+               }
+       if( pmem != &pyield[nprod] ) error( "internal Yacc error: pyield %d", pmem-&pyield[nprod] );
+       }
+
+int indebug = 0;
+cpfir() {
+       /* compute an array with the first of nonterminals */
+       register *p, **s, i, **t, ch, changes;
+
+       zzcwp = &wsets[nnonter];
+       NTLOOP(i){
+               aryfil( wsets[i].ws.lset, tbitset, 0 );
+               t = pres[i+1];
+               for( s=pres[i]; s<t; ++s ){ /* initially fill the sets */
+                       for( p = *s; (ch = *p) > 0 ; ++p ) {
+                               if( ch < NTBASE ) {
+                                       SETBIT( wsets[i].ws.lset, ch );
+                                       break;
+                                       }
+                               else if( !pempty[ch-NTBASE] ) break;
+                               }
+                       }
+               }
+
+       /* now, reflect transitivity */
+
+       changes = 1;
+       while( changes ){
+               changes = 0;
+               NTLOOP(i){
+                       t = pres[i+1];
+                       for( s=pres[i]; s<t; ++s ){
+                               for( p = *s; ( ch = (*p-NTBASE) ) >= 0; ++p ) {
+                                       changes |= setunion( wsets[i].ws.lset, wsets[ch].ws.lset );
+                                       if( !pempty[ch] ) break;
+                                       }
+                               }
+                       }
+               }
+
+       NTLOOP(i) pfirst[i] = flset( &wsets[i].ws );
+       if( !indebug ) return;
+       if( (foutput!=NULL) ){
+               NTLOOP(i) {
+                       fprintf( foutput,  "\n%s: ", nontrst[i].name );
+                       prlook( pfirst[i] );
+                       fprintf( foutput,  " %d\n", pempty[i] );
+                       }
+               }
+       }
+
+state(c){ /* sorts last state,and sees if it equals earlier ones. returns state number */
+       int size1,size2;
+       register i;
+       struct item *p1, *p2, *k, *l, *q1, *q2;
+       p1 = pstate[nstate];
+       p2 = pstate[nstate+1];
+       if(p1==p2) return(0); /* null state */
+       /* sort the items */
+       for(k=p2-1;k>p1;k--) {  /* make k the biggest */
+               for(l=k-1;l>=p1;--l)if( l->pitem > k->pitem ){
+                       int *s;
+                       struct looksets *ss;
+                       s = k->pitem;
+                       k->pitem = l->pitem;
+                       l->pitem = s;
+                       ss = k->look;
+                       k->look = l->look;
+                       l->look = ss;
+                       }
+               }
+       size1 = p2 - p1; /* size of state */
+
+       for( i= (c>=NTBASE)?ntstates[c-NTBASE]:tstates[c]; i != 0; i = mstates[i] ) {
+               /* get ith state */
+               q1 = pstate[i];
+               q2 = pstate[i+1];
+               size2 = q2 - q1;
+               if (size1 != size2) continue;
+               k=p1;
+               for(l=q1;l<q2;l++) {
+                       if( l->pitem != k->pitem ) break;
+                       ++k;
+                       }
+               if (l != q2) continue;
+               /* found it */
+               pstate[nstate+1] = pstate[nstate]; /* delete last state */
+               /* fix up lookaheads */
+               if( nolook ) return(i);
+               for( l=q1,k=p1; l<q2; ++l,++k ){
+                       int s;
+                       SETLOOP(s) clset.lset[s] = l->look->lset[s];
+                       if( setunion( clset.lset, k->look->lset ) ) {
+                               tystate[i] = MUSTDO;
+                               /* register the new set */
+                               l->look = flset( &clset );
+                               }
+                       }
+               return (i);
+               }
+       /* state is new */
+       if( nolook ) error( "yacc state/nolook error" );
+       pstate[nstate+2] = p2;
+       if(nstate+1 >= NSTATES) error("too many states" );
+       if( c >= NTBASE ){
+               mstates[ nstate ] = ntstates[ c-NTBASE ];
+               ntstates[ c-NTBASE ] = nstate;
+               }
+       else {
+               mstates[ nstate ] = tstates[ c ];
+               tstates[ c ] = nstate;
+               }
+       tystate[nstate]=MUSTDO;
+       return(nstate++);
+       }
+
+int pidebug = 0; /* debugging flag for putitem */
+putitem( ptr, lptr )  int *ptr;  struct looksets *lptr; {
+       register struct item *j;
+
+       if( pidebug && (foutput!=NULL) ) {
+               fprintf( foutput, "putitem(%s), state %d\n", writem(ptr), nstate );
+               }
+       j = pstate[nstate+1];
+       j->pitem = ptr;
+       if( !nolook ) j->look = flset( lptr );
+       pstate[nstate+1] = ++j;
+       if( (int *)j > zzmemsz ){
+               zzmemsz = (int *)j;
+               if( zzmemsz >=  &mem0[MEMSIZE] ) error( "out of state space" );
+               }
+       }
+
+cempty(){ /* mark nonterminals which derive the empty string */
+       /* also, look for nonterminals which don't derive any token strings */
+
+# define EMPTY 1
+# define WHOKNOWS 0
+# define OK 1
+
+       register i, *p;
+
+       /* first, use the array pempty to detect productions that can never be reduced */
+       /* set pempty to WHONOWS */
+       aryfil( pempty, nnonter+1, WHOKNOWS );
+
+       /* now, look at productions, marking nonterminals which derive something */
+
+       more:
+       PLOOP(0,i){
+               if( pempty[ *prdptr[i] - NTBASE ] ) continue;
+               for( p=prdptr[i]+1; *p>=0; ++p ){
+                       if( *p>=NTBASE && pempty[ *p-NTBASE ] == WHOKNOWS ) break;
+                       }
+               if( *p < 0 ){ /* production can be derived */
+                       pempty[ *prdptr[i]-NTBASE ] = OK;
+                       goto more;
+                       }
+               }
+
+       /* now, look at the nonterminals, to see if they are all OK */
+
+       NTLOOP(i){
+               /* the added production rises or falls as the start symbol ... */
+               if( i == 0 ) continue;
+               if( pempty[ i ] != OK ) {
+                       fatfl = 0;
+                       error( "nonterminal %s never derives any token string", nontrst[i].name );
+                       }
+               }
+
+       if( nerrors ){
+               summary();
+               exit(1);
+               }
+
+       /* now, compute the pempty array, to see which nonterminals derive the empty string */
+
+       /* set pempty to WHOKNOWS */
+
+       aryfil( pempty, nnonter+1, WHOKNOWS );
+
+       /* loop as long as we keep finding empty nonterminals */
+
+again:
+       PLOOP(1,i){
+               if( pempty[ *prdptr[i]-NTBASE ]==WHOKNOWS ){ /* not known to be empty */
+                       for( p=prdptr[i]+1; *p>=NTBASE && pempty[*p-NTBASE]==EMPTY ; ++p ) ;
+                       if( *p < 0 ){ /* we have a nontrivially empty nonterminal */
+                               pempty[*prdptr[i]-NTBASE] = EMPTY;
+                               goto again; /* got one ... try for another */
+                               }
+                       }
+               }
+
+       }
+
+int gsdebug = 0;
+stagen(){ /* generate the states */
+
+       int i, j;
+       register c;
+       register struct wset *p, *q;
+
+       /* initialize */
+
+       nstate = 0;
+       /* THIS IS FUNNY from the standpoint of portability */
+       /* it represents the magic moment when the mem0 array, which has
+       /* been holding the productions, starts to hold item pointers, of a
+       /* different type... */
+       /* someday, alloc should be used to allocate all this stuff... for now, we
+       /* accept that if pointers don't fit in integers, there is a problem... */
+
+       pstate[0] = pstate[1] = (struct item *)mem;
+       aryfil( clset.lset, tbitset, 0 );
+       putitem( prdptr[0]+1, &clset );
+       tystate[0] = MUSTDO;
+       nstate = 1;
+       pstate[2] = pstate[1];
+
+       aryfil( amem, ACTSIZE, 0 );
+
+       /* now, the main state generation loop */
+
+       more:
+       SLOOP(i){
+               if( tystate[i] != MUSTDO ) continue;
+               tystate[i] = DONE;
+               aryfil( temp1, nnonter+1, 0 );
+               /* take state i, close it, and do gotos */
+               closure(i);
+               WSLOOP(wsets,p){ /* generate goto's */
+                       if( p->flag ) continue;
+                       p->flag = 1;
+                       c = *(p->pitem);
+                       if( c <= 1 ) {
+                               if( pstate[i+1]-pstate[i] <= p-wsets ) tystate[i] = MUSTLOOKAHEAD;
+                               continue;
+                               }
+                       /* do a goto on c */
+                       WSLOOP(p,q){
+                               if( c == *(q->pitem) ){ /* this item contributes to the goto */
+                                       putitem( q->pitem + 1, &q->ws );
+                                       q->flag = 1;
+                                       }
+                               }
+                       if( c < NTBASE ) {
+                               state(c);  /* register new state */
+                               }
+                       else {
+                               temp1[c-NTBASE] = state(c);
+                               }
+                       }
+               if( gsdebug && (foutput!=NULL) ){
+                       fprintf( foutput,  "%d: ", i );
+                       NTLOOP(j) {
+                               if( temp1[j] ) fprintf( foutput,  "%s %d, ", nontrst[j].name, temp1[j] );
+                               }
+                       fprintf( foutput, "\n");
+                       }
+               indgo[i] = apack( &temp1[1], nnonter-1 ) - 1;
+               goto more; /* we have done one goto; do some more */
+               }
+       /* no more to do... stop */
+       }
+
+int cldebug = 0; /* debugging flag for closure */
+closure(i){ /* generate the closure of state i */
+
+       int c, ch, work, k;
+       register struct wset *u, *v;
+       int *pi;
+       int **s, **t;
+       struct item *q;
+       register struct item *p;
+
+       ++zzclose;
+
+       /* first, copy kernel of state i to wsets */
+
+       cwp = wsets;
+       ITMLOOP(i,p,q){
+               cwp->pitem = p->pitem;
+               cwp->flag = 1;    /* this item must get closed */
+               SETLOOP(k) cwp->ws.lset[k] = p->look->lset[k];
+               WSBUMP(cwp);
+               }
+
+       /* now, go through the loop, closing each item */
+
+       work = 1;
+       while( work ){
+               work = 0;
+               WSLOOP(wsets,u){
+       
+                       if( u->flag == 0 ) continue;
+                       c = *(u->pitem);  /* dot is before c */
+       
+                       if( c < NTBASE ){
+                               u->flag = 0;
+                               continue;  /* only interesting case is where . is before nonterminal */
+                               }
+       
+                       /* compute the lookahead */
+                       aryfil( clset.lset, tbitset, 0 );
+
+                       /* find items involving c */
+
+                       WSLOOP(u,v){
+                               if( v->flag == 1 && *(pi=v->pitem) == c ){
+                                       v->flag = 0;
+                                       if( nolook ) continue;
+                                       while( (ch= *++pi)>0 ){
+                                               if( ch < NTBASE ){ /* terminal symbol */
+                                                       SETBIT( clset.lset, ch );
+                                                       break;
+                                                       }
+                                               /* nonterminal symbol */
+                                               setunion( clset.lset, pfirst[ch-NTBASE]->lset );
+                                               if( !pempty[ch-NTBASE] ) break;
+                                               }
+                                       if( ch<=0 ) setunion( clset.lset, v->ws.lset );
+                                       }
+                               }
+       
+                       /*  now loop over productions derived from c */
+       
+                       c -= NTBASE; /* c is now nonterminal number */
+       
+                       t = pres[c+1];
+                       for( s=pres[c]; s<t; ++s ){
+                               /* put these items into the closure */
+                               WSLOOP(wsets,v){ /* is the item there */
+                                       if( v->pitem == *s ){ /* yes, it is there */
+                                               if( nolook ) goto nexts;
+                                               if( setunion( v->ws.lset, clset.lset ) ) v->flag = work = 1;
+                                               goto nexts;
+                                               }
+                                       }
+       
+                               /*  not there; make a new entry */
+                               if( cwp-wsets+1 >= WSETSIZE ) error( "working set overflow" );
+                               cwp->pitem = *s;
+                               cwp->flag = 1;
+                               if( !nolook ){
+                                       work = 1;
+                                       SETLOOP(k) cwp->ws.lset[k] = clset.lset[k];
+                                       }
+                               WSBUMP(cwp);
+       
+                       nexts: ;
+                               }
+       
+                       }
+               }
+
+       /* have computed closure; flags are reset; return */
+
+       if( cwp > zzcwp ) zzcwp = cwp;
+       if( cldebug && (foutput!=NULL) ){
+               fprintf( foutput, "\nState %d, nolook = %d\n", i, nolook );
+               WSLOOP(wsets,u){
+                       if( u->flag ) fprintf( foutput, "flag set!\n");
+                       u->flag = 0;
+                       fprintf( foutput, "\t%s", writem(u->pitem));
+                       prlook( &u->ws );
+                       fprintf( foutput,  "\n" );
+                       }
+               }
+       }
+
+struct looksets *flset( p )   struct looksets *p; {
+       /* decide if the lookahead set pointed to by p is known */
+       /* return pointer to a perminent location for the set */
+
+       register struct looksets *q;
+       int j, *w;
+       register *u, *v;
+
+       for( q = &lkst[nlset]; q-- > lkst; ){
+               u = p->lset;
+               v = q->lset;
+               w = & v[tbitset];
+               while( v<w) if( *u++ != *v++ ) goto more;
+               /* we have matched */
+               return( q );
+               more: ;
+               }
+       /* add a new one */
+       q = &lkst[nlset++];
+       if( nlset >= LSETSIZE )error("too many lookahead sets" );
+       SETLOOP(j){
+               q->lset[j] = p->lset[j];
+               }
+       return( q );
+       }
diff --git a/usr/src/cmd/yacc/y2.c b/usr/src/cmd/yacc/y2.c
new file mode 100644 (file)
index 0000000..a625896
--- /dev/null
@@ -0,0 +1,859 @@
+# include "dextern"
+# define IDENTIFIER 257
+# define MARK 258
+# define TERM 259
+# define LEFT 260
+# define RIGHT 261
+# define BINARY 262
+# define PREC 263
+# define LCURLY 264
+# define C_IDENTIFIER 265  /* name followed by colon */
+# define NUMBER 266
+# define START 267
+# define TYPEDEF 268
+# define TYPENAME 269
+# define UNION 270
+# define ENDFILE 0
+
+       /* communication variables between various I/O routines */
+
+char *infile;  /* input file name */
+int numbval;   /* value of an input number */
+char tokname[NAMESIZE];        /* input token name */
+
+       /* storage of names */
+
+char cnames[CNAMSZ];   /* place where token and nonterminal names are stored */
+int cnamsz = CNAMSZ;   /* size of cnames */
+char * cnamp = cnames; /* place where next name is to be put in */
+int ndefout = 3;  /* number of defined symbols output */
+
+       /* storage of types */
+int ntypes;    /* number of types defined */
+char * typeset[NTYPES];        /* pointers to type tags */
+
+       /* symbol tables for tokens and nonterminals */
+
+int ntokens = 0;
+struct toksymb tokset[NTERMS];
+int toklev[NTERMS];
+int nnonter = -1;
+struct ntsymb nontrst[NNONTERM];
+int start;     /* start symbol */
+
+       /* assigned token type values */
+int extval = 0;
+
+       /* input and output file descriptors */
+
+FILE * finput;         /* yacc input file */
+FILE * faction;                /* file for saving actions */
+FILE * fdefine;                /* file for # defines */
+FILE * ftable;         /* y.tab.c file */
+FILE * ftemp;          /* tempfile to pass 2 */
+FILE * foutput;                /* y.output file */
+
+       /* storage for grammar rules */
+
+int mem0[MEMSIZE] ; /* production storage */
+int *mem = mem0;
+int nprod= 1;  /* number of productions */
+int *prdptr[NPROD];    /* pointers to descriptions of productions */
+int levprd[NPROD] ;    /* precedence levels for the productions */
+
+
+setup(argc,argv) int argc; char *argv[];
+{      int i,j,lev,t, ty;
+       int c;
+       int *p;
+       char actname[8];
+
+       foutput = NULL;
+       fdefine = NULL;
+       i = 1;
+       while( argc >= 2  && argv[1][0] == '-' ) {
+               while( *++(argv[1]) ){
+                       switch( *argv[1] ){
+                       case 'v':
+                       case 'V':
+                               foutput = fopen(FILEU, "w" );
+                               if( foutput == NULL ) error( "cannot open y.output" );
+                               continue;
+                       case 'D':
+                       case 'd':
+                               fdefine = fopen( FILED, "w" );
+                               continue;
+                       case 'o':
+                       case 'O':
+                               fprintf( stderr, "`o' flag now default in yacc\n" );
+                               continue;
+
+                       case 'r':
+                       case 'R':
+                               error( "Ratfor Yacc is dead: sorry...\n" );
+
+                       default:
+                               error( "illegal option: %c", *argv[1]);
+                               }
+                       }
+               argv++;
+               argc--;
+               }
+
+       ftable = fopen( OFILE, "w" );
+       if( ftable == NULL ) error( "cannot open table file" );
+
+       ftemp = fopen( TEMPNAME, "w" );
+       faction = fopen( ACTNAME, "w" );
+       if( ftemp==NULL || faction==NULL ) error( "cannot open temp file" );
+
+       if( argc < 2 || ((finput=fopen( infile=argv[1], "r" )) == NULL ) ){
+               error( "cannot open input file" );
+               }
+
+       cnamp = cnames;
+       defin(0,"$end");
+       extval = 0400;
+       defin(0,"error");
+       defin(1,"$accept");
+       mem=mem0;
+       lev = 0;
+       ty = 0;
+       i=0;
+
+       /* sorry -- no yacc parser here.....
+               we must bootstrap somehow... */
+
+       for( t=gettok();  t!=MARK && t!= ENDFILE; ){
+               switch( t ){
+
+               case ';':
+                       t = gettok();
+                       break;
+
+               case START:
+                       if( (t=gettok()) != IDENTIFIER ){
+                               error( "bad %%start construction" );
+                               }
+                       start = chfind(1,tokname);
+                       t = gettok();
+                       continue;
+
+               case TYPEDEF:
+                       if( (t=gettok()) != TYPENAME ) error( "bad syntax in %%type" );
+                       ty = numbval;
+                       for(;;){
+                               t = gettok();
+                               switch( t ){
+
+                               case IDENTIFIER:
+                                       if( (t=chfind( 1, tokname ) ) < NTBASE ) {
+                                               j = TYPE( toklev[t] );
+                                               if( j!= 0 && j != ty ){
+                                                       error( "type redeclaration of token %s",
+                                                               tokset[t].name );
+                                                       }
+                                               else SETTYPE( toklev[t],ty);
+                                               }
+                                       else {
+                                               j = nontrst[t-NTBASE].tvalue;
+                                               if( j != 0 && j != ty ){
+                                                       error( "type redeclaration of nonterminal %s",
+                                                               nontrst[t-NTBASE].name );
+                                                       }
+                                               else nontrst[t-NTBASE].tvalue = ty;
+                                               }
+                               case ',':
+                                       continue;
+
+                               case ';':
+                                       t = gettok();
+                                       break;
+                               default:
+                                       break;
+                                       }
+                               break;
+                               }
+                       continue;
+
+               case UNION:
+                       /* copy the union declaration to the output */
+                       cpyunion();
+                       t = gettok();
+                       continue;
+
+               case LEFT:
+               case BINARY:
+               case RIGHT:
+                       ++i;
+               case TERM:
+                       lev = t-TERM;  /* nonzero means new prec. and assoc. */
+                       ty = 0;
+
+                       /* get identifiers so defined */
+
+                       t = gettok();
+                       if( t == TYPENAME ){ /* there is a type defined */
+                               ty = numbval;
+                               t = gettok();
+                               }
+
+                       for(;;) {
+                               switch( t ){
+
+                               case ',':
+                                       t = gettok();
+                                       continue;
+
+                               case ';':
+                                       break;
+
+                               case IDENTIFIER:
+                                       j = chfind(0,tokname);
+                                       if( lev ){
+                                               if( ASSOC(toklev[j]) ) error( "redeclaration of precedence of %s", tokname );
+                                               SETASC(toklev[j],lev);
+                                               SETPLEV(toklev[j],i);
+                                               }
+                                       if( ty ){
+                                               if( TYPE(toklev[j]) ) error( "redeclaration of type of %s", tokname );
+                                               SETTYPE(toklev[j],ty);
+                                               }
+                                       if( (t=gettok()) == NUMBER ){
+                                               tokset[j].value = numbval;
+                                               if( j < ndefout && j>2 ){
+                                                       error( "please define type number of %s earlier",
+                                                               tokset[j].name );
+                                                       }
+                                               t=gettok();
+                                               }
+                                       continue;
+
+                                       }
+
+                               break;
+                               }
+
+                       continue;
+
+               case LCURLY:
+                       defout();
+                       cpycode();
+                       t = gettok();
+                       continue;
+
+               default:
+                       error( "syntax error" );
+
+                       }
+
+               }
+
+       if( t == ENDFILE ){
+               error( "unexpected EOF before %%" );
+               }
+
+       /* t is MARK */
+
+       defout();
+
+               fprintf( ftable,  "#define yyclearin yychar = -1\n" );
+               fprintf( ftable,  "#define yyerrok yyerrflag = 0\n" );
+               fprintf( ftable,  "extern int yychar;\nextern short yyerrflag;\n" );
+               fprintf( ftable,  "#ifndef YYMAXDEPTH\n#define YYMAXDEPTH 150\n#endif\n" );
+               if( !ntypes ) fprintf( ftable,  "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n" );
+               fprintf( ftable,  "YYSTYPE yylval, yyval;\n" );
+
+       prdptr[0]=mem;
+       /* added production */
+       *mem++ = NTBASE;
+       *mem++ = start;  /* if start is 0, we will overwrite with the lhs of the first rule */
+       *mem++ = 1;
+       *mem++ = 0;
+       prdptr[1]=mem;
+
+       while( (t=gettok()) == LCURLY ) cpycode();
+
+       if( t != C_IDENTIFIER ) error( "bad syntax on first rule" );
+
+       if( !start ) prdptr[0][1] = chfind(1,tokname);
+
+       /* read rules */
+
+       while( t!=MARK && t!=ENDFILE ){
+
+               /* process a rule */
+
+               if( t == '|' ){
+                       *mem++ = *prdptr[nprod-1];
+                       }
+               else if( t == C_IDENTIFIER ){
+                       *mem = chfind(1,tokname);
+                       if( *mem < NTBASE ) error( "token illegal on LHS of grammar rule" );
+                       ++mem;
+                       }
+               else error( "illegal rule: missing semicolon or | ?" );
+
+               /* read rule body */
+
+
+               t = gettok();
+       more_rule:
+               while( t == IDENTIFIER ) {
+                       *mem = chfind(1,tokname);
+                       if( *mem<NTBASE ) levprd[nprod] = toklev[*mem];
+                       ++mem;
+                       t = gettok();
+                       }
+
+
+               if( t == PREC ){
+                       if( gettok()!=IDENTIFIER) error( "illegal %%prec syntax" );
+                       j = chfind(2,tokname);
+                       if( j>=NTBASE)error("nonterminal %s illegal after %%prec", nontrst[j-NTBASE].name);
+                       levprd[nprod]=toklev[j];
+                       t = gettok();
+                       }
+
+               if( t == '=' ){
+                       levprd[nprod] |= ACTFLAG;
+                       fprintf( faction, "\ncase %d:", nprod );
+                       cpyact( mem-prdptr[nprod]-1 );
+                       fprintf( faction, " break;" );
+                       if( (t=gettok()) == IDENTIFIER ){
+                               /* action within rule... */
+
+                               sprintf( actname, "$$%d", nprod );
+                               j = chfind(1,actname);  /* make it a nonterminal */
+
+                               /* the current rule will become rule number nprod+1 */
+                               /* move the contents down, and make room for the null */
+
+                               for( p=mem; p>=prdptr[nprod]; --p ) p[2] = *p;
+                               mem += 2;
+
+                               /* enter null production for action */
+
+                               p = prdptr[nprod];
+
+                               *p++ = j;
+                               *p++ = -nprod;
+
+                               /* update the production information */
+
+                               levprd[nprod+1] = levprd[nprod] & ~ACTFLAG;
+                               levprd[nprod] = ACTFLAG;
+
+                               if( ++nprod >= NPROD ) error( "more than %d rules", NPROD );
+                               prdptr[nprod] = p;
+
+                               /* make the action appear in the original rule */
+                               *mem++ = j;
+
+                               /* get some more of the rule */
+
+                               goto more_rule;
+                               }
+
+                       }
+
+               while( t == ';' ) t = gettok();
+
+               *mem++ = -nprod;
+
+               /* check that default action is reasonable */
+
+               if( ntypes && !(levprd[nprod]&ACTFLAG) && nontrst[*prdptr[nprod]-NTBASE].tvalue ){
+                       /* no explicit action, LHS has value */
+                       register tempty;
+                       tempty = prdptr[nprod][1];
+                       if( tempty < 0 ) error( "must return a value, since LHS has a type" );
+                       else if( tempty >= NTBASE ) tempty = nontrst[tempty-NTBASE].tvalue;
+                       else tempty = TYPE( toklev[tempty] );
+                       if( tempty != nontrst[*prdptr[nprod]-NTBASE].tvalue ){
+                               error( "default action causes potential type clash" );
+                               }
+                       }
+
+               if( ++nprod >= NPROD ) error( "more than %d rules", NPROD );
+               prdptr[nprod] = mem;
+               levprd[nprod]=0;
+
+               }
+
+       /* end of all rules */
+
+       finact();
+       if( t == MARK ){
+               fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile );
+               while( (c=getc(finput)) != EOF ) putc( c, ftable );
+               }
+       fclose( finput );
+       }
+
+finact(){
+       /* finish action routine */
+
+       fclose(faction);
+
+       fprintf( ftable, "# define YYERRCODE %d\n", tokset[2].value );
+
+       }
+
+defin( t, s ) register char  *s; {
+/*     define s to be a terminal if t=0
+       or a nonterminal if t=1         */
+
+       register val;
+
+       if (t) {
+               if( ++nnonter >= NNONTERM ) error("too many nonterminals, limit %d",NNONTERM);
+               nontrst[nnonter].name = cstash(s);
+               return( NTBASE + nnonter );
+               }
+       /* must be a token */
+       if( ++ntokens >= NTERMS ) error("too many terminals, limit %d",NTERMS );
+       tokset[ntokens].name = cstash(s);
+
+       /* establish value for token */
+
+       if( s[0]==' ' && s[2]=='\0' ) /* single character literal */
+               val = s[1];
+       else if ( s[0]==' ' && s[1]=='\\' ) { /* escape sequence */
+               if( s[3] == '\0' ){ /* single character escape sequence */
+                       switch ( s[2] ){
+                                        /* character which is escaped */
+                       case 'n': val = '\n'; break;
+                       case 'r': val = '\r'; break;
+                       case 'b': val = '\b'; break;
+                       case 't': val = '\t'; break;
+                       case 'f': val = '\f'; break;
+                       case '\'': val = '\''; break;
+                       case '"': val = '"'; break;
+                       case '\\': val = '\\'; break;
+                       default: error( "invalid escape" );
+                               }
+                       }
+               else if( s[2] <= '7' && s[2]>='0' ){ /* \nnn sequence */
+                       if( s[3]<'0' || s[3] > '7' || s[4]<'0' ||
+                               s[4]>'7' || s[5] != '\0' ) error("illegal \\nnn construction" );
+                       val = 64*s[2] + 8*s[3] + s[4] - 73*'0';
+                       if( val == 0 ) error( "'\\000' is illegal" );
+                       }
+               }
+       else {
+               val = extval++;
+               }
+       tokset[ntokens].value = val;
+       toklev[ntokens] = 0;
+       return( ntokens );
+       }
+
+defout(){ /* write out the defines (at the end of the declaration section) */
+
+       register int i, c;
+       register char *cp;
+
+       for( i=ndefout; i<=ntokens; ++i ){
+
+               cp = tokset[i].name;
+               if( *cp == ' ' ) ++cp;  /* literals */
+
+               for( ; (c= *cp)!='\0'; ++cp ){
+
+                       if( islower(c) || isupper(c) || isdigit(c) || c=='_' );  /* VOID */
+                       else goto nodef;
+                       }
+
+               fprintf( ftable, "# define %s %d\n", tokset[i].name, tokset[i].value );
+               if( fdefine != NULL ) fprintf( fdefine, "# define %s %d\n", tokset[i].name, tokset[i].value );
+
+       nodef:  ;
+               }
+
+       ndefout = ntokens+1;
+
+       }
+
+char *
+cstash( s ) register char *s; {
+       char *temp;
+
+       temp = cnamp;
+       do {
+               if( cnamp >= &cnames[cnamsz] ) error("too many characters in id's and literals" );
+               else *cnamp++ = *s;
+               }  while ( *s++ );
+       return( temp );
+       }
+
+gettok() {
+       register i, base;
+       static int peekline; /* number of '\n' seen in lookahead */
+       register c, match, reserve;
+
+begin:
+       reserve = 0;
+       lineno += peekline;
+       peekline = 0;
+       c = getc(finput);
+       while( c==' ' || c=='\n' || c=='\t' || c=='\f' ){
+               if( c == '\n' ) ++lineno;
+               c=getc(finput);
+               }
+       if( c == '/' ){ /* skip comment */
+               lineno += skipcom();
+               goto begin;
+               }
+
+       switch(c){
+
+       case EOF:
+               return(ENDFILE);
+       case '{':
+               ungetc( c, finput );
+               return( '=' );  /* action ... */
+       case '<':  /* get, and look up, a type name (union member name) */
+               i = 0;
+               while( (c=getc(finput)) != '>' && c>=0 && c!= '\n' ){
+                       tokname[i] = c;
+                       if( ++i >= NAMESIZE ) --i;
+                       }
+               if( c != '>' ) error( "unterminated < ... > clause" );
+               tokname[i] = '\0';
+               for( i=1; i<=ntypes; ++i ){
+                       if( !strcmp( typeset[i], tokname ) ){
+                               numbval = i;
+                               return( TYPENAME );
+                               }
+                       }
+               typeset[numbval = ++ntypes] = cstash( tokname );
+               return( TYPENAME );
+
+       case '"':       
+       case '\'':
+               match = c;
+               tokname[0] = ' ';
+               i = 1;
+               for(;;){
+                       c = getc(finput);
+                       if( c == '\n' || c == EOF )
+                               error("illegal or missing ' or \"" );
+                       if( c == '\\' ){
+                               c = getc(finput);
+                               tokname[i] = '\\';
+                               if( ++i >= NAMESIZE ) --i;
+                               }
+                       else if( c == match ) break;
+                       tokname[i] = c;
+                       if( ++i >= NAMESIZE ) --i;
+                       }
+               break;
+
+       case '%':
+       case '\\':
+
+               switch(c=getc(finput)) {
+
+               case '0':       return(TERM);
+               case '<':       return(LEFT);
+               case '2':       return(BINARY);
+               case '>':       return(RIGHT);
+               case '%':
+               case '\\':      return(MARK);
+               case '=':       return(PREC);
+               case '{':       return(LCURLY);
+               default:        reserve = 1;
+                       }
+
+       default:
+
+               if( isdigit(c) ){ /* number */
+                       numbval = c-'0' ;
+                       base = (c=='0') ? 8 : 10 ;
+                       for( c=getc(finput); isdigit(c) ; c=getc(finput) ){
+                               numbval = numbval*base + c - '0';
+                               }
+                       ungetc( c, finput );
+                       return(NUMBER);
+                       }
+               else if( islower(c) || isupper(c) || c=='_' || c=='.' || c=='$' ){
+                       i = 0;
+                       while( islower(c) || isupper(c) || isdigit(c) || c=='_' || c=='.' || c=='$' ){
+                               tokname[i] = c;
+                               if( reserve && isupper(c) ) tokname[i] += 'a'-'A';
+                               if( ++i >= NAMESIZE ) --i;
+                               c = getc(finput);
+                               }
+                       }
+               else return(c);
+
+               ungetc( c, finput );
+               }
+
+       tokname[i] = '\0';
+
+       if( reserve ){ /* find a reserved word */
+               if( !strcmp(tokname,"term")) return( TERM );
+               if( !strcmp(tokname,"token")) return( TERM );
+               if( !strcmp(tokname,"left")) return( LEFT );
+               if( !strcmp(tokname,"nonassoc")) return( BINARY );
+               if( !strcmp(tokname,"binary")) return( BINARY );
+               if( !strcmp(tokname,"right")) return( RIGHT );
+               if( !strcmp(tokname,"prec")) return( PREC );
+               if( !strcmp(tokname,"start")) return( START );
+               if( !strcmp(tokname,"type")) return( TYPEDEF );
+               if( !strcmp(tokname,"union")) return( UNION );
+               error("invalid escape, or illegal reserved word: %s", tokname );
+               }
+
+       /* look ahead to distinguish IDENTIFIER from C_IDENTIFIER */
+
+       c = getc(finput);
+       while( c==' ' || c=='\t'|| c=='\n' || c=='\f' || c== '/' ) {
+               if( c == '\n' ) ++peekline;
+               else if( c == '/' ){ /* look for comments */
+                       peekline += skipcom();
+                       }
+               c = getc(finput);
+               }
+       if( c == ':' ) return( C_IDENTIFIER );
+       ungetc( c, finput );
+       return( IDENTIFIER );
+}
+
+fdtype( t ){ /* determine the type of a symbol */
+       register v;
+       if( t >= NTBASE ) v = nontrst[t-NTBASE].tvalue;
+       else v = TYPE( toklev[t] );
+       if( v <= 0 ) error( "must specify type for %s", (t>=NTBASE)?nontrst[t-NTBASE].name:
+                       tokset[t].name );
+       return( v );
+       }
+
+chfind( t, s ) register char *s; {
+       int i;
+
+       if (s[0]==' ')t=0;
+       TLOOP(i){
+               if(!strcmp(s,tokset[i].name)){
+                       return( i );
+                       }
+               }
+       NTLOOP(i){
+               if(!strcmp(s,nontrst[i].name)) {
+                       return( i+NTBASE );
+                       }
+               }
+       /* cannot find name */
+       if( t>1 )
+               error( "%s should have been defined earlier", s );
+       return( defin( t, s ) );
+       }
+
+cpyunion(){
+       /* copy the union declaration to the output, and the define file if present */
+
+       int level, c;
+       fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile );
+       fprintf( ftable, "typedef union " );
+       if( fdefine ) fprintf( fdefine, "\ntypedef union " );
+
+       level = 0;
+       for(;;){
+               if( (c=getc(finput)) < 0 ) error( "EOF encountered while processing %%union" );
+               putc( c, ftable );
+               if( fdefine ) putc( c, fdefine );
+
+               switch( c ){
+
+               case '\n':
+                       ++lineno;
+                       break;
+
+               case '{':
+                       ++level;
+                       break;
+
+               case '}':
+                       --level;
+                       if( level == 0 ) { /* we are finished copying */
+                               fprintf( ftable, " YYSTYPE;\n" );
+                               if( fdefine ) fprintf( fdefine, " YYSTYPE;\nextern YYSTYPE yylval;\n" );
+                               return;
+                               }
+                       }
+               }
+       }
+
+cpycode(){ /* copies code between \{ and \} */
+
+       int c;
+       c = getc(finput);
+       if( c == '\n' ) {
+               c = getc(finput);
+               lineno++;
+               }
+       fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile );
+       while( c>=0 ){
+               if( c=='\\' )
+                       if( (c=getc(finput)) == '}' ) return;
+                       else putc('\\', ftable );
+               if( c=='%' )
+                       if( (c=getc(finput)) == '}' ) return;
+                       else putc('%', ftable );
+               putc( c , ftable );
+               if( c == '\n' ) ++lineno;
+               c = getc(finput);
+               }
+       error("eof before %%}" );
+       }
+
+skipcom(){ /* skip over comments */
+       register c, i=0;  /* i is the number of lines skipped */
+
+       /* skipcom is called after reading a / */
+
+       if( getc(finput) != '*' ) error( "illegal comment" );
+       c = getc(finput);
+       while( c != EOF ){
+               while( c == '*' ){
+                       if( (c=getc(finput)) == '/' ) return( i );
+                       }
+               if( c == '\n' ) ++i;
+               c = getc(finput);
+               }
+       error( "EOF inside comment" );
+       /* NOTREACHED */
+       }
+
+cpyact(offset){ /* copy C action to the next ; or closing } */
+       int brac, c, match, j, s, tok;
+
+       fprintf( faction, "\n# line %d \"%s\"\n", lineno, infile );
+
+       brac = 0;
+
+loop:
+       c = getc(finput);
+swt:
+       switch( c ){
+
+case ';':
+               if( brac == 0 ){
+                       putc( c , faction );
+                       return;
+                       }
+               goto lcopy;
+
+case '{':
+               brac++;
+               goto lcopy;
+
+case '$':
+               s = 1;
+               tok = -1;
+               c = getc(finput);
+               if( c == '<' ){ /* type description */
+                       ungetc( c, finput );
+                       if( gettok() != TYPENAME ) error( "bad syntax on $<ident> clause" );
+                       tok = numbval;
+                       c = getc(finput);
+                       }
+               if( c == '$' ){
+                       fprintf( faction, "yyval");
+                       if( ntypes ){ /* put out the proper tag... */
+                               if( tok < 0 ) tok = fdtype( *prdptr[nprod] );
+                               fprintf( faction, ".%s", typeset[tok] );
+                               }
+                       goto loop;
+                       }
+               if( c == '-' ){
+                       s = -s;
+                       c = getc(finput);
+                       }
+               if( isdigit(c) ){
+                       j=0;
+                       while( isdigit(c) ){
+                               j= j*10+c-'0';
+                               c = getc(finput);
+                               }
+
+                       j = j*s - offset;
+                       if( j > 0 ){
+                               error( "Illegal use of $%d", j+offset );
+                               }
+
+                       fprintf( faction, "yypvt[-%d]", -j );
+                       if( ntypes ){ /* put out the proper tag */
+                               if( j+offset <= 0 && tok < 0 ) error( "must specify type of $%d", j+offset );
+                               if( tok < 0 ) tok = fdtype( prdptr[nprod][j+offset] );
+                               fprintf( faction, ".%s", typeset[tok] );
+                               }
+                       goto swt;
+                       }
+               putc( '$' , faction );
+               if( s<0 ) putc('-', faction );
+               goto swt;
+
+case '}':
+               if( --brac ) goto lcopy;
+               putc( c, faction );
+               return;
+
+
+case '/':      /* look for comments */
+               putc( c , faction );
+               c = getc(finput);
+               if( c != '*' ) goto swt;
+
+               /* it really is a comment */
+
+               putc( c , faction );
+               c = getc(finput);
+               while( c != EOF ){
+                       while( c=='*' ){
+                               putc( c , faction );
+                               if( (c=getc(finput)) == '/' ) goto lcopy;
+                               }
+                       putc( c , faction );
+                       if( c == '\n' )++lineno;
+                       c = getc(finput);
+                       }
+               error( "EOF inside comment" );
+
+case '\'':     /* character constant */
+               match = '\'';
+               goto string;
+
+case '"':      /* character string */
+               match = '"';
+
+       string:
+
+               putc( c , faction );
+               while( c=getc(finput) ){
+
+                       if( c=='\\' ){
+                               putc( c , faction );
+                               c=getc(finput);
+                               if( c == '\n' ) ++lineno;
+                               }
+                       else if( c==match ) goto lcopy;
+                       else if( c=='\n' ) error( "newline in string or char. const." );
+                       putc( c , faction );
+                       }
+               error( "EOF in string or character constant" );
+
+case EOF:
+               error("action does not terminate" );
+
+case '\n':     ++lineno;
+               goto lcopy;
+
+               }
+
+lcopy:
+       putc( c , faction );
+       goto loop;
+       }
diff --git a/usr/src/cmd/yacc/y3.c b/usr/src/cmd/yacc/y3.c
new file mode 100644 (file)
index 0000000..7e79373
--- /dev/null
@@ -0,0 +1,404 @@
+# include "dextern"
+
+       /* important local variables */
+int lastred;  /* the number of the last reduction of a state */
+int defact[NSTATES];  /* the default actions of states */
+
+output(){ /* print the output for the states */
+
+       int i, k, c;
+       register struct wset *u, *v;
+
+       fprintf( ftable, "short yyexca[] ={\n" );
+
+       SLOOP(i) { /* output the stuff for state i */
+               nolook = !(tystate[i]==MUSTLOOKAHEAD);
+               closure(i);
+               /* output actions */
+               nolook = 1;
+               aryfil( temp1, ntokens+nnonter+1, 0 );
+               WSLOOP(wsets,u){
+                       c = *( u->pitem );
+                       if( c>1 && c<NTBASE && temp1[c]==0 ) {
+                               WSLOOP(u,v){
+                                       if( c == *(v->pitem) ) putitem( v->pitem+1, (struct looksets *)0 );
+                                       }
+                               temp1[c] = state(c);
+                               }
+                       else if( c > NTBASE && temp1[ (c -= NTBASE) + ntokens ] == 0 ){
+                               temp1[ c+ntokens ] = amem[indgo[i]+c];
+                               }
+                       }
+
+               if( i == 1 ) temp1[1] = ACCEPTCODE;
+
+               /* now, we have the shifts; look at the reductions */
+
+               lastred = 0;
+               WSLOOP(wsets,u){
+                       c = *( u->pitem );
+                       if( c<=0 ){ /* reduction */
+                               lastred = -c;
+                               TLOOP(k){
+                                       if( BIT(u->ws.lset,k) ){
+                                                 if( temp1[k] == 0 ) temp1[k] = c;
+                                                 else if( temp1[k]<0 ){ /* reduce/reduce conflict */
+                                                   if( foutput!=NULL )
+                                                     fprintf( foutput,
+                                                       "\n%d: reduce/reduce conflict (red'ns %d and %d ) on %s",
+                                                       i, -temp1[k], lastred, symnam(k) );
+                                                   if( -temp1[k] > lastred ) temp1[k] = -lastred;
+                                                   ++zzrrconf;
+                                                   }
+                                                 else { /* potential shift/reduce conflict */
+                                                       precftn( lastred, k, i );
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               wract(i);
+               }
+
+       fprintf( ftable, "\t};\n" );
+
+       wdef( "YYNPROD", nprod );
+
+       }
+
+int pkdebug = 0;
+apack(p, n ) int *p;{ /* pack state i from temp1 into amem */
+       int off;
+       register *pp, *qq, *rr;
+       int *q, *r;
+
+       /* we don't need to worry about checking because we
+          we will only look entries known to be there... */
+
+       /* eliminate leading and trailing 0's */
+
+       q = p+n;
+       for( pp=p,off=0 ; *pp==0 && pp<=q; ++pp,--off ) /* VOID */ ;
+       if( pp > q ) return(0);  /* no actions */
+       p = pp;
+
+       /* now, find a place for the elements from p to q, inclusive */
+
+       r = &amem[ACTSIZE-1];
+       for( rr=amem; rr<=r; ++rr,++off ){  /* try rr */
+               for( qq=rr,pp=p ; pp<=q ; ++pp,++qq){
+                       if( *pp != 0 ){
+                               if( *pp != *qq && *qq != 0 ) goto nextk;
+                               }
+                       }
+
+               /* we have found an acceptable k */
+
+               if( pkdebug && foutput!=NULL ) fprintf( foutput, "off = %d, k = %d\n", off, rr-amem );
+
+               for( qq=rr,pp=p; pp<=q; ++pp,++qq ){
+                       if( *pp ){
+                               if( qq > r ) error( "action table overflow" );
+                               if( qq>memp ) memp = qq;
+                               *qq = *pp;
+                               }
+                       }
+               if( pkdebug && foutput!=NULL ){
+                       for( pp=amem; pp<= memp; pp+=10 ){
+                               fprintf( foutput, "\t");
+                               for( qq=pp; qq<=pp+9; ++qq ) fprintf( foutput, "%d ", *qq );
+                               fprintf( foutput, "\n");
+                               }
+                       }
+               return( off );
+
+               nextk: ;
+               }
+       error("no space in action table" );
+       /* NOTREACHED */
+       }
+
+go2out(){ /* output the gotos for the nontermninals */
+       int i, j, k, best, count, cbest, times;
+
+       fprintf( ftemp, "$\n" );  /* mark begining of gotos */
+
+       for( i=1; i<=nnonter; ++i ) {
+               go2gen(i);
+
+               /* find the best one to make default */
+
+               best = -1;
+               times = 0;
+
+               for( j=0; j<=nstate; ++j ){ /* is j the most frequent */
+                       if( tystate[j] == 0 ) continue;
+                       if( tystate[j] == best ) continue;
+
+                       /* is tystate[j] the most frequent */
+
+                       count = 0;
+                       cbest = tystate[j];
+
+                       for( k=j; k<=nstate; ++k ) if( tystate[k]==cbest ) ++count;
+
+                       if( count > times ){
+                               best = cbest;
+                               times = count;
+                               }
+                       }
+
+               /* best is now the default entry */
+
+               zzgobest += (times-1);
+               for( j=0; j<=nstate; ++j ){
+                       if( tystate[j] != 0 && tystate[j]!=best ){
+                               fprintf( ftemp, "%d,%d,", j, tystate[j] );
+                               zzgoent += 1;
+                               }
+                       }
+
+               /* now, the default */
+
+               zzgoent += 1;
+               fprintf( ftemp, "%d\n", best );
+
+               }
+
+
+
+       }
+
+int g2debug = 0;
+go2gen(c){ /* output the gotos for nonterminal c */
+
+       int i, work, cc;
+       struct item *p, *q;
+
+
+       /* first, find nonterminals with gotos on c */
+
+       aryfil( temp1, nnonter+1, 0 );
+       temp1[c] = 1;
+
+       work = 1;
+       while( work ){
+               work = 0;
+               PLOOP(0,i){
+                       if( (cc=prdptr[i][1]-NTBASE) >= 0 ){ /* cc is a nonterminal */
+                               if( temp1[cc] != 0 ){ /* cc has a goto on c */
+                                       cc = *prdptr[i]-NTBASE; /* thus, the left side of production i does too */
+                                       if( temp1[cc] == 0 ){
+                                                 work = 1;
+                                                 temp1[cc] = 1;
+                                                 }
+                                       }
+                               }
+                       }
+               }
+
+       /* now, we have temp1[c] = 1 if a goto on c in closure of cc */
+
+       if( g2debug && foutput!=NULL ){
+               fprintf( foutput, "%s: gotos on ", nontrst[c].name );
+               NTLOOP(i) if( temp1[i] ) fprintf( foutput, "%s ", nontrst[i].name);
+               fprintf( foutput, "\n");
+               }
+
+       /* now, go through and put gotos into tystate */
+
+       aryfil( tystate, nstate, 0 );
+       SLOOP(i){
+               ITMLOOP(i,p,q){
+                       if( (cc= *p->pitem) >= NTBASE ){
+                               if( temp1[cc -= NTBASE] ){ /* goto on c is possible */
+                                       tystate[i] = amem[indgo[i]+c];
+                                       break;
+                                       }
+                               }
+                       }
+               }
+       }
+
+precftn(r,t,s){ /* decide a shift/reduce conflict by precedence.
+       /* r is a rule number, t a token number */
+       /* the conflict is in state s */
+       /* temp1[t] is changed to reflect the action */
+
+       int lp,lt, action;
+
+       lp = levprd[r];
+       lt = toklev[t];
+       if( PLEVEL(lt) == 0 || PLEVEL(lp) == 0 ) {
+               /* conflict */
+               if( foutput != NULL ) fprintf( foutput, "\n%d: shift/reduce conflict (shift %d, red'n %d) on %s",
+                                               s, temp1[t], r, symnam(t) );
+               ++zzsrconf;
+               return;
+               }
+       if( PLEVEL(lt) == PLEVEL(lp) ) action = ASSOC(lt);
+       else if( PLEVEL(lt) > PLEVEL(lp) ) action = RASC;  /* shift */
+       else action = LASC;  /* reduce */
+
+       switch( action ){
+
+       case BASC:  /* error action */
+               temp1[t] = ERRCODE;
+               return;
+
+       case LASC:  /* reduce */
+               temp1[t] = -r;
+               return;
+
+               }
+       }
+
+wract(i){ /* output state i */
+       /* temp1 has the actions, lastred the default */
+       int p, p0, p1;
+       int ntimes, tred, count, j;
+       int flag;
+
+       /* find the best choice for lastred */
+
+       lastred = 0;
+       ntimes = 0;
+       TLOOP(j){
+               if( temp1[j] >= 0 ) continue;
+               if( temp1[j]+lastred == 0 ) continue;
+               /* count the number of appearances of temp1[j] */
+               count = 0;
+               tred = -temp1[j];
+               levprd[tred] |= REDFLAG;
+               TLOOP(p){
+                       if( temp1[p]+tred == 0 ) ++count;
+                       }
+               if( count >ntimes ){
+                       lastred = tred;
+                       ntimes = count;
+                       }
+               }
+
+       /* for error recovery, arrange that, if there is a shift on the
+       /* error recovery token, `error', that the default be the error action */
+       if( temp1[1] > 0 ) lastred = 0;
+
+       /* clear out entries in temp1 which equal lastred */
+       TLOOP(p) if( temp1[p]+lastred == 0 )temp1[p]=0;
+
+       wrstate(i);
+       defact[i] = lastred;
+
+       flag = 0;
+       TLOOP(p0){
+               if( (p1=temp1[p0])!=0 ) {
+                       if( p1 < 0 ){
+                               p1 = -p1;
+                               goto exc;
+                               }
+                       else if( p1 == ACCEPTCODE ) {
+                               p1 = -1;
+                               goto exc;
+                               }
+                       else if( p1 == ERRCODE ) {
+                               p1 = 0;
+                               goto exc;
+                       exc:
+                               if( flag++ == 0 ) fprintf( ftable, "-1, %d,\n", i );
+                               fprintf( ftable, "\t%d, %d,\n", tokset[p0].value, p1 );
+                               ++zzexcp;
+                               }
+                       else {
+                               fprintf( ftemp, "%d,%d,", tokset[p0].value, p1 );
+                               ++zzacent;
+                               }
+                       }
+               }
+       if( flag ) {
+               defact[i] = -2;
+               fprintf( ftable, "\t-2, %d,\n", lastred );
+               }
+       fprintf( ftemp, "\n" );
+       return;
+       }
+
+wrstate(i){ /* writes state i */
+       register j0,j1;
+       register struct item *pp, *qq;
+       register struct wset *u;
+
+       if( foutput == NULL ) return;
+       fprintf( foutput, "\nstate %d\n",i);
+       ITMLOOP(i,pp,qq) fprintf( foutput, "\t%s\n", writem(pp->pitem));
+       if( tystate[i] == MUSTLOOKAHEAD ){
+               /* print out empty productions in closure */
+               WSLOOP( wsets+(pstate[i+1]-pstate[i]), u ){
+                       if( *(u->pitem) < 0 ) fprintf( foutput, "\t%s\n", writem(u->pitem) );
+                       }
+               }
+
+       /* check for state equal to another */
+
+       TLOOP(j0) if( (j1=temp1[j0]) != 0 ){
+               fprintf( foutput, "\n\t%s  ", symnam(j0) );
+               if( j1>0 ){ /* shift, error, or accept */
+                       if( j1 == ACCEPTCODE ) fprintf( foutput,  "accept" );
+                       else if( j1 == ERRCODE ) fprintf( foutput, "error" );
+                       else fprintf( foutput,  "shift %d", j1 );
+                       }
+               else fprintf( foutput, "reduce %d",-j1 );
+               }
+
+       /* output the final production */
+
+       if( lastred ) fprintf( foutput, "\n\t.  reduce %d\n\n", lastred );
+       else fprintf( foutput, "\n\t.  error\n\n" );
+
+       /* now, output nonterminal actions */
+
+       j1 = ntokens;
+       for( j0 = 1; j0 <= nnonter; ++j0 ){
+               if( temp1[++j1] ) fprintf( foutput, "\t%s  goto %d\n", symnam( j0+NTBASE), temp1[j1] );
+               }
+
+       }
+
+wdef( s, n ) char *s; { /* output a definition of s to the value n */
+       fprintf( ftable, "# define %s %d\n", s, n );
+       }
+
+warray( s, v, n ) char *s; int *v, n; {
+
+       register i;
+
+       fprintf( ftable, "short %s[]={\n", s );
+       for( i=0; i<n; ){
+               if( i%10 == 0 ) fprintf( ftable, "\n" );
+               fprintf( ftable, "%4d", v[i] );
+               if( ++i == n ) fprintf( ftable, " };\n" );
+               else fprintf( ftable, "," );
+               }
+       }
+
+hideprod(){
+       /* in order to free up the mem and amem arrays for the optimizer,
+       /* and still be able to output yyr1, etc., after the sizes of
+       /* the action array is known, we hide the nonterminals
+       /* derived by productions in levprd.
+       */
+
+       register i, j;
+
+       j = 0;
+       levprd[0] = 0;
+       PLOOP(1,i){
+               if( !(levprd[i] & REDFLAG) ){
+                       ++j;
+                       if( foutput != NULL ){
+                               fprintf( foutput, "Rule not reduced:   %s\n", writem( prdptr[i] ) );
+                               }
+                       }
+               levprd[i] = *prdptr[i] - NTBASE;
+               }
+       if( j ) fprintf( stdout, "%d rules never reduced\n", j );
+       }
diff --git a/usr/src/cmd/yacc/y4.c b/usr/src/cmd/yacc/y4.c
new file mode 100644 (file)
index 0000000..d32f4b0
--- /dev/null
@@ -0,0 +1,325 @@
+# include "dextern"
+
+# define a amem
+# define mem mem0
+# define pa indgo
+# define yypact temp1
+# define greed tystate
+
+int * ggreed = lkst[0].lset;
+int * pgo = wsets[0].ws.lset;
+int *yypgo = &nontrst[0].tvalue;
+
+int maxspr = 0;  /* maximum spread of any entry */
+int maxoff = 0;  /* maximum offset into a array */
+int *pmem = mem;
+int *maxa;
+# define NOMORE -1000
+
+int nxdb = 0;
+int adb = 0;
+
+callopt(){
+
+       register i, *p, j, k, *q;
+
+       /* read the arrays from tempfile and set parameters */
+
+       if( (finput=fopen(TEMPNAME,"r")) == NULL ) error( "optimizer cannot open tempfile" );
+
+       pgo[0] = 0;
+       yypact[0] = 0;
+       nstate = 0;
+       nnonter = 0;
+       for(;;){
+               switch( gtnm() ){
+
+               case '\n':
+                       yypact[++nstate] = (--pmem) - mem;
+               case ',':
+                       continue;
+
+               case '$':
+                       break;
+
+               default:
+                       error( "bad tempfile" );
+                       }
+               break;
+               }
+
+       yypact[nstate] = yypgo[0] = (--pmem) - mem;
+
+       for(;;){
+               switch( gtnm() ){
+
+               case '\n':
+                       yypgo[++nnonter]= pmem-mem;
+               case ',':
+                       continue;
+
+               case EOF:
+                       break;
+
+               default:
+                       error( "bad tempfile" );
+                       }
+               break;
+               }
+
+       yypgo[nnonter--] = (--pmem) - mem;
+
+
+
+       for( i=0; i<nstate; ++i ){
+
+               k = 32000;
+               j = 0;
+               q = mem + yypact[i+1];
+               for( p = mem + yypact[i]; p<q ; p += 2 ){
+                       if( *p > j ) j = *p;
+                       if( *p < k ) k = *p;
+                       }
+               if( k <= j ){ /* nontrivial situation */
+                       /* temporarily, kill this for compatibility
+                       j -= k;  /* j is now the range */
+                       if( k > maxoff ) maxoff = k;
+                       }
+               greed[i] = (yypact[i+1]-yypact[i]) + 2*j;
+               if( j > maxspr ) maxspr = j;
+               }
+
+       /* initialize ggreed table */
+
+       for( i=1; i<=nnonter; ++i ){
+               ggreed[i] = 1;
+               j = 0;
+               /* minimum entry index is always 0 */
+               q = mem + yypgo[i+1] -1;
+               for( p = mem+yypgo[i]; p<q ; p += 2 ) {
+                       ggreed[i] += 2;
+                       if( *p > j ) j = *p;
+                       }
+               ggreed[i] = ggreed[i] + 2*j;
+               if( j > maxoff ) maxoff = j;
+               }
+
+
+       /* now, prepare to put the shift actions into the a array */
+
+       for( i=0; i<ACTSIZE; ++i ) a[i] = 0;
+       maxa = a;
+
+       for( i=0; i<nstate; ++i ) {
+               if( greed[i]==0 && adb>1 ) fprintf( ftable, "State %d: null\n", i );
+               pa[i] = YYFLAG1;
+               }
+
+       while( (i = nxti()) != NOMORE ) {
+               if( i >= 0 ) stin(i);
+               else gin(-i);
+
+               }
+
+       if( adb>2 ){ /* print a array */
+               for( p=a; p <= maxa; p += 10){
+                       fprintf( ftable, "%4d  ", p-a );
+                       for( i=0; i<10; ++i ) fprintf( ftable, "%4d  ", p[i] );
+                       fprintf( ftable, "\n" );
+                       }
+               }
+       /* write out the output appropriate to the language */
+
+       aoutput();
+
+       osummary();
+       ZAPFILE(TEMPNAME);
+       }
+
+gin(i){
+
+       register *p, *r, *s, *q1, *q2;
+
+       /* enter gotos on nonterminal i into array a */
+
+       ggreed[i] = 0;
+
+       q2 = mem+ yypgo[i+1] - 1;
+       q1 = mem + yypgo[i];
+
+       /* now, find a place for it */
+
+       for( p=a; p < &a[ACTSIZE]; ++p ){
+               if( *p ) continue;
+               for( r=q1; r<q2; r+=2 ){
+                       s = p + *r +1;
+                       if( *s ) goto nextgp;
+                       if( s > maxa ){
+                               if( (maxa=s) > &a[ACTSIZE] ) error( "a array overflow" );
+                               }
+                       }
+               /* we have found a spot */
+
+               *p = *q2;
+               if( p > maxa ){
+                       if( (maxa=p) > &a[ACTSIZE] ) error( "a array overflow" );
+                       }
+               for( r=q1; r<q2; r+=2 ){
+                       s = p + *r + 1;
+                       *s = r[1];
+                       }
+
+               pgo[i] = p-a;
+               if( adb>1 ) fprintf( ftable, "Nonterminal %d, entry at %d\n" , i, pgo[i] );
+               goto nextgi;
+
+               nextgp:  ;
+               }
+
+       error( "cannot place goto %d\n", i );
+
+       nextgi:  ;
+       }
+
+stin(i){
+       register *r, *s, n, flag, j, *q1, *q2;
+
+       greed[i] = 0;
+
+       /* enter state i into the a array */
+
+       q2 = mem+yypact[i+1];
+       q1 = mem+yypact[i];
+       /* find an acceptable place */
+
+       for( n= -maxoff; n<ACTSIZE; ++n ){
+
+               flag = 0;
+               for( r = q1; r < q2; r += 2 ){
+                       if( (s = *r + n + a ) < a ) goto nextn;
+                       if( *s == 0 ) ++flag;
+                       else if( *s != r[1] ) goto nextn;
+                       }
+
+               /* check that the position equals another only if the states are identical */
+
+               for( j=0; j<nstate; ++j ){
+                       if( pa[j] == n ) {
+                               if( flag ) goto nextn;  /* we have some disagreement */
+                               if( yypact[j+1] + yypact[i] == yypact[j] + yypact[i+1] ){
+                                       /* states are equal */
+                                       pa[i] = n;
+                                       if( adb>1 ) fprintf( ftable, "State %d: entry at %d equals state %d\n",
+                                               i, n, j );
+                                       return;
+                                       }
+                               goto nextn;  /* we have some disagreement */
+                               }
+                       }
+
+               for( r = q1; r < q2; r += 2 ){
+                       if( (s = *r + n + a ) >= &a[ACTSIZE] ) error( "out of space in optimizer a array" );
+                       if( s > maxa ) maxa = s;
+                       if( *s != 0 && *s != r[1] ) error( "clobber of a array, pos'n %d, by %d", s-a, r[1] );
+                       *s = r[1];
+                       }
+               pa[i] = n;
+               if( adb>1 ) fprintf( ftable, "State %d: entry at %d\n", i, pa[i] );
+               return;
+
+               nextn:  ;
+               }
+
+       error( "Error; failure to place state %d\n", i );
+
+       }
+
+nxti(){ /* finds the next i */
+       register i, max, maxi;
+
+       max = 0;
+
+       for( i=1; i<= nnonter; ++i ) if( ggreed[i] >= max ){
+               max = ggreed[i];
+               maxi = -i;
+               }
+
+       for( i=0; i<nstate; ++i ) if( greed[i] >= max ){
+               max = greed[i];
+               maxi = i;
+               }
+
+       if( nxdb ) fprintf( ftable, "nxti = %d, max = %d\n", maxi, max );
+       if( max==0 ) return( NOMORE );
+       else return( maxi );
+       }
+
+osummary(){
+       /* write summary */
+
+       register i, *p;
+
+       if( foutput == NULL ) return;
+       i=0;
+       for( p=maxa; p>=a; --p ) {
+               if( *p == 0 ) ++i;
+               }
+
+       fprintf( foutput, "Optimizer space used: input %d/%d, output %d/%d\n",
+               pmem-mem+1, MEMSIZE, maxa-a+1, ACTSIZE );
+       fprintf( foutput, "%d table entries, %d zero\n", (maxa-a)+1, i );
+       fprintf( foutput, "maximum spread: %d, maximum offset: %d\n", maxspr, maxoff );
+
+       }
+
+aoutput(){ /* this version is for C */
+
+
+       /* write out the optimized parser */
+
+       fprintf( ftable, "# define YYLAST %d\n", maxa-a+1 );
+
+       arout( "yyact", a, (maxa-a)+1 );
+       arout( "yypact", pa, nstate );
+       arout( "yypgo", pgo, nnonter+1 );
+
+       }
+
+arout( s, v, n ) char *s; int *v, n; {
+
+       register i;
+
+       fprintf( ftable, "short %s[]={\n", s );
+       for( i=0; i<n; ){
+               if( i%10 == 0 ) fprintf( ftable, "\n" );
+               fprintf( ftable, "%4d", v[i] );
+               if( ++i == n ) fprintf( ftable, " };\n" );
+               else fprintf( ftable, "," );
+               }
+       }
+
+
+gtnm(){
+
+       register s, val, c;
+
+       /* read and convert an integer from the standard input */
+       /* return the terminating character */
+       /* blanks, tabs, and newlines are ignored */
+
+       s = 1;
+       val = 0;
+
+       while( (c=getc(finput)) != EOF ){
+               if( isdigit(c) ){
+                       val = val * 10 + c - '0';
+                       }
+               else if ( c == '-' ) s = -1;
+               else break;
+               }
+
+       *pmem++ = s*val;
+       if( pmem > &mem[MEMSIZE] ) error( "out of space" );
+       return( c );
+
+       }
diff --git a/usr/src/cmd/yacc/yaccdiffs b/usr/src/cmd/yacc/yaccdiffs
new file mode 100644 (file)
index 0000000..e5f7f4f
--- /dev/null
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+
+
+
+                      Yacc Differences
+
+
+
+
+
+This document gives a short list of differences between  the
+new Yacc and earlier Yaccs.
+
+_\bB_\bu_\bg_\bs _\bF_\bi_\bx_\be_\bd
+
+1.   There was a bug which caused  Yacc  to  silently  steal
+     away in the night if an action had mismatched '' in it;
+     this is fixed.
+
+2.   A number of table size overflow conditions used  to  be
+     checked incorrectly or not at all; this is now better.
+
+3.   A bug which suppressed the printing of some rules  with
+     empty RHS's on the y.output file has been fixed.
+
+_\bS_\bp_\be_\be_\bd_\bu_\bp_\bs, _\bS_\bh_\br_\bi_\bn_\bk_\bs, _\ba_\bn_\bd _\bD_\bi_\bd_\bd_\bl_\be_\bs
+
+1.   The old optimizer (-o) flag is now the default in Yacc.
+     At the same time, the Yacc process itself has been sped
+     up; the result is that Yacc takes  about  the  same  or
+     slightly  longer on short inputs, but is much faster on
+     long inputs.
+
+2.   The optimized parsers produced by Yacc are likely to be
+     2-3  times  faster  and 1-2k bytes smaller than the old
+     ones, for medium/large grammars.  The time to parse  is
+     now  essentially  independent  of  the grammar size; it
+     used to grow as the size of the grammar did.
+
+3.   The y.output file has been considerably reformatted, to
+     make  it easier to read.  The old "goto" table is gone;
+     the goto's for nonterminal symbols are now  printed  in
+     the  states  where  they  occur.   Rules  which  can be
+     reduced in a state have their rule number printed after
+     them,  in  ().   This makes it much easier to interpret
+     the "reduce n" actions.  The message "same  as  n"  has
+     been  removed; duplicate states are in fact duplicated,
+     saving shuffling and cross-referencing.
+
+4.   Various table sizes are somewhat bigger.
+
+5.   The form feed character, and the construction '\f', are
+     now  recognized;  form feed is ignored (=whitespace) on
+     input.
+
+
+
+
+                      January 14, 1977
+
+
+
+
+
+                           - 2 -
+
+
+
+6.   The arrays "yysterm" and "yysnter" are no  longer  pro-
+     duced  on  output; they were little used, and took up a
+     surprising amount of space in the parser.
+
+7.   Rules in the input which are not reduced are  now  com-
+     plained  about; they may represent unreachable parts of
+     the grammar, botched precedence,  or  duplicate  rules.
+     As  with  conflicts,  a summary complaint, "n rules not
+     reduced", appears at the terminal; more information  is
+     on the y.output file.
+
+_\bN_\be_\bw _\bF_\be_\ba_\bt_\bu_\br_\be_\bs
+
+1.   The actions are now  copied  into  the  middle  of  the
+     parser, rather than being gathered into a separate rou-
+     tine.  It's faster.  Also, you can return a value  from
+     yyparse (and stop parsing...) by saying `return(x);' in
+     an action.  There are  macros  which  simulate  various
+     interesting parsing actions:
+
+     YYERROR  causes the parser to behave as if a syntax
+     error had been encountered (i.e., do error recovery)
+     YYACCEPT causes a return from yyparse with a value of 0
+     YYABORT  causes a return from yyparse with a value of 1
+
+
+2.   The repositioning of the actions may cause scope  prob-
+     lems  for  some people who include lexical analyzers in
+     funny places.  This can probably be  avoided  by  using
+     another  new  feature:  the `-d' option.  Invoking Yacc
+     with the -d option causes  the  #defines  generated  by
+     Yacc  to  be  written out onto a file called "y.tab.h",
+     (as well as on the "y.tab.c" file).  This can  then  be
+     included as desired in lexical analyzers, etc.
+
+3.   Actions  are  now  permitted  within  rules;  for  such
+     actions,  $$, $1, $2, etc. continue to have their usual
+     meanings.  An error  message  is  returned  if  any  $n
+     refers  to  a value lying to the right of the action in
+     the rule.  These internal actions are assumed to return
+     a  value,  which  is accessed through the $n mechanism.
+     In the y.output file, the actions are  referred  to  by
+     created  nonterminal  names  of  the  form  $$nnn.  All
+     actions within rules are assumed to  be  distinct.   If
+     some   actions   are   the   same,  Yacc  might  report
+     reduce/reduce conflicts  which  could  be  resolved  by
+     explicitly  identifying  identical actions; does anyone
+     have a good idea for a syntax to do this?  The  =  sign
+     may  now be omitted in action constructions of the form
+     ={  ...   }.
+
+
+
+
+
+
+                      January 14, 1977
+
+
+
+
+
+                           - 3 -
+
+
+
+4.   As a result of the rearrangement of rules,  people  who
+     thought they knew what $1 really turned into, and wrote
+     programs which referred to yypv[1], etc., are in  trou-
+     ble.  See Steve Johnson if you are really suffering.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                      January 14, 1977
+
+
diff --git a/usr/src/cmd/yacc/yaccnews b/usr/src/cmd/yacc/yaccnews
new file mode 100644 (file)
index 0000000..547c81e
--- /dev/null
@@ -0,0 +1,149 @@
+5/18/78
+A new version of Yacc has been installed which contains some new
+features relating to error recovery, detection of funny conditions in the
+grammar, and strong typing.  Existing grammars should continue to work,
+with the possible exception of somewhat better error recovery behavior.
+More details follow:
+
+***    Ratfor and EFL Yacc are dead.  Long live C!
+
+***    The y.tab.c file now uses the # line feature to reflect
+       most error conditions in actions, etc., back to the yacc source
+       file, rather than the y.tab.c file.  As always with such features,
+       lookahead may cause the line number to be one too large
+       occasionally.
+
+***    The error recovery algorithm has been changed to cause the
+       parser never to reduce on a state where there is a shift
+       on the special token `error'.  This has the effect of causing
+       the error recovery action to take place somewhat closer to the
+       location of the error than previously.  It does not affect the
+       behavior of the parser in the absence of errors.  The parse
+       tables may be 1-2% larger as a result of this change.
+
+***    Yacc now detects the existence of nonterminals in the grammar
+       which can never derive any strings of tokens (even the empty string).
+       The simplest example is the grammar:
+               %%
+               s       :       s 'a' ;
+       Here, one must reduce `s' in order to reduce `s': the
+       parser would always report error.  If such nonterminals are
+       present, Yacc reports all such, then terminates.
+
+***    There is a new reserved word, %start.  When used in the declarations
+       section, it may be used to declare the start symbol of the grammar.
+       If %start does not appear, the start symbol is, as at present, the
+       first nonterminal symbol encountered.
+
+***    Yacc produced parsers are notorious for producing many many
+       comments from lint.  The problem is the value stack of the
+       parser, which typically may contain integers, pointers, and
+       possibly even floating point, etc., values.  The lack
+       of tight specification of this stack leads to potential
+       nonportability, and considerable loss of the diagnostic power
+       of lint.  Thus, some new features have been added which make use
+       of the new structure and union facilities of C.  In effect,
+       the user of Yacc may `honestly' declare the value stack, as
+       well as the lexical interface variable, yylval, to be unions
+       of all the types desired.  Yacc will keep track of the types
+       declared for all terminals and nonterminals, and automatically
+       insert the appropriate union tag for all constructions such
+       as $1, $$, etc.  It is up to the user to supply the appropriate
+       union declaration, and to declare the type of all the terminal
+       and nonterminal symbols which will have values.  If the type
+       declaration feature is used at all, it must be used correctly;
+       if it is not used, the default values are integers, as at present.
+       The new type declaration features are described below:
+
+***    There is a new keyword, %union.  A construction such as
+               %union {
+                       int inttag;
+                       float floattag;
+                       struct mumble *ptrtag;
+                       }
+       can be used, in the declarations section, to declare
+       the type of the yacc stack.  The declaration is
+       effectively copied to the y.tab.c file, and, if the -d
+       option is present, to the y.tab.h file as well.  The
+       declaration is used to declare the typedef YYSTYPE, which is the
+       type of the value stack.  If the -d option is present,
+       the declaration
+               extern YYSTYPE yylval;
+       is also placed onto the y.tab.h file.  Note that the lexical
+       analyzer must be changed to use the appropriate union tag when
+       assigning values.  It is not necessary that the %union
+       mechanism be used, as long as there is a union type YYSTYPE
+       defined in the declarations section.
+
+***    The %token, %left, %right, and %nonassoc declarations now
+       accept a union tag, enclosed in angle brackets (<...>), immediately
+       after the keyword.  All tokens mentioned in that declaration are
+       taken to have the appropriate type.
+
+***    There is a new keyword, %type, also followed by a union tag
+       in angle brackets, which may be used in the declarations section to
+       declare nonterminal symbols to have a particular type.
+
+       In both cases, whenever a $$ or $n is encountered in an action,
+       the appropriate union tag is supplied by Yacc.  Once any type is
+       declared, it is an error to use a $$ or $n whose type is unknown.
+       It is also illegal to have a grammar rule whose LHS has a type,
+       but the rule has no action and the default action { $$ = $1; }
+       would be inapplicable because $1 had a different type.
+
+***    There are occasional times when the type of something is
+       not known (for example, when an action within a rule returns a
+       value).  In this case, the $$ and $n syntax is extended
+       to permit the declaration of the type: the syntax is
+               $<tag>$
+       and
+               $<tag>n
+       respectively.  This rather strange syntax is necessitated by the 
+       need to distinguish the <> surrounding the tag from the < and >
+       operators of C in the action.  It is anticipated that the usage
+       will be rare.
+
+***    As always, report gripes, bugs, suggestions to SCJ ***
+
+12/01/76
+A newer version of Yacc has been installed which copies the actions directly
+into the parser, rather than gathering them into a separate routine.
+The advantages include
+1.  It's faster
+2.  You can return a value from yyparse (and stop parsing...) by
+    saying `return(x);' in an action
+3.  There are macros which simulate various interesting parsing
+    actions:
+      YYERROR  causes the parser to behave as if a syntax
+               error had been encountered (i.e., do error recovery)
+      YYACCEPT causes a return from yyparse with a value of 0
+      YYABORT  causes a return from yyparse with a value of 1
+
+The repositioning of the actions may cause scope problems
+for some people who include lexical analyzers in funny places.
+This can probably be avoided by using another
+new feature: the `-d' option.
+Invoking Yacc with the -d option causes the #defines
+generated by Yacc to be written out onto a file
+called "y.tab.h".  This can then be included as desired
+in lexical analyzers, etc.
+
+11/28/76
+A new version of Yacc has been installed which permits actions within
+rules.  For such actions, $$ and $1, $2, etc. continue to have their
+usual meanings.  An error message is returned if any $n refers to
+a value lying to the right of the action in the rule.
+
+These internal actions are assumed to return a value, which is accessed
+through the $n mechanism.
+
+In the y.output file, the actions are referred to by created nonterminal
+names of the form $$nnn.
+
+All actions within rules are assumed to be distinct.  If some actions
+are the same, Yacc might report reduce/reduce conflicts which could
+be resolved by explicitly identifying identical actions; does anyone
+have a good idea for a syntax to do this?
+
+In the new Yacc, the = sign may now be omitted in action constructions
+of the form    ={  ...   }
diff --git a/usr/src/cmd/yacc/yaccpar b/usr/src/cmd/yacc/yaccpar
new file mode 100644 (file)
index 0000000..daa01c4
--- /dev/null
@@ -0,0 +1,149 @@
+#
+# define YYFLAG -1000
+# define YYERROR goto yyerrlab
+# define YYACCEPT return(0)
+# define YYABORT return(1)
+
+/*     parser for yacc output  */
+
+#ifdef YYDEBUG
+int yydebug = 0; /* 1 for debugging */
+#endif
+YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */
+int yychar = -1; /* current input token number */
+int yynerrs = 0;  /* number of errors */
+short yyerrflag = 0;  /* error recovery flag */
+
+yyparse() {
+
+       short yys[YYMAXDEPTH];
+       short yyj, yym;
+       register YYSTYPE *yypvt;
+       register short yystate, *yyps, yyn;
+       register YYSTYPE *yypv;
+       register short *yyxi;
+
+       yystate = 0;
+       yychar = -1;
+       yynerrs = 0;
+       yyerrflag = 0;
+       yyps= &yys[-1];
+       yypv= &yyv[-1];
+
+ yystack:    /* put a state and value onto the stack */
+
+#ifdef YYDEBUG
+       if( yydebug  ) printf( "state %d, char 0%o\n", yystate, yychar );
+#endif
+               if( ++yyps> &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); }
+               *yyps = yystate;
+               ++yypv;
+               *yypv = yyval;
+
+ yynewstate:
+
+       yyn = yypact[yystate];
+
+       if( yyn<= YYFLAG ) goto yydefault; /* simple state */
+
+       if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0;
+       if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault;
+
+       if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */
+               yychar = -1;
+               yyval = yylval;
+               yystate = yyn;
+               if( yyerrflag > 0 ) --yyerrflag;
+               goto yystack;
+               }
+
+ yydefault:
+       /* default state action */
+
+       if( (yyn=yydef[yystate]) == -2 ) {
+               if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0;
+               /* look through exception table */
+
+               for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */
+
+               while( *(yyxi+=2) >= 0 ){
+                       if( *yyxi == yychar ) break;
+                       }
+               if( (yyn = yyxi[1]) < 0 ) return(0);   /* accept */
+               }
+
+       if( yyn == 0 ){ /* error */
+               /* error ... attempt to resume parsing */
+
+               switch( yyerrflag ){
+
+               case 0:   /* brand new error */
+
+                       yyerror( "syntax error" );
+               yyerrlab:
+                       ++yynerrs;
+
+               case 1:
+               case 2: /* incompletely recovered error ... try again */
+
+                       yyerrflag = 3;
+
+                       /* find a state where "error" is a legal shift action */
+
+                       while ( yyps >= yys ) {
+                          yyn = yypact[*yyps] + YYERRCODE;
+                          if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){
+                             yystate = yyact[yyn];  /* simulate a shift of "error" */
+                             goto yystack;
+                             }
+                          yyn = yypact[*yyps];
+
+                          /* the current yyps has no shift onn "error", pop stack */
+
+#ifdef YYDEBUG
+                          if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] );
+#endif
+                          --yyps;
+                          --yypv;
+                          }
+
+                       /* there is no state on the stack with an error shift ... abort */
+
+       yyabort:
+                       return(1);
+
+
+               case 3:  /* no shift yet; clobber input char */
+
+#ifdef YYDEBUG
+                       if( yydebug ) printf( "error recovery discards char %d\n", yychar );
+#endif
+
+                       if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */
+                       yychar = -1;
+                       goto yynewstate;   /* try again in the same state */
+
+                       }
+
+               }
+
+       /* reduction by production yyn */
+
+#ifdef YYDEBUG
+               if( yydebug ) printf("reduce %d\n",yyn);
+#endif
+               yyps -= yyr2[yyn];
+               yypvt = yypv;
+               yypv -= yyr2[yyn];
+               yyval = yypv[1];
+               yym=yyn;
+                       /* consult goto table to find next state */
+               yyn = yyr1[yyn];
+               yyj = yypgo[yyn] + *yyps + 1;
+               if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]];
+               switch(yym){
+                       $A
+               }
+               goto yystack;  /* stack new state and value */
+
+       }