From 42d6e430f0b7c8bc68352aa33571d525ce59a2b0 Mon Sep 17 00:00:00 2001 From: Bill Joy Date: Mon, 12 Feb 1979 05:51:39 -0800 Subject: [PATCH] BSD 3 development 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 --- usr/src/cmd/awk/awk.def | 127 ++ usr/src/cmd/awk/awk.g.y | 269 ++++ usr/src/cmd/awk/awk.h | 76 ++ usr/src/cmd/awk/awk.lx.l | 168 +++ usr/src/cmd/awk/b.c | 536 ++++++++ usr/src/cmd/awk/dump.c | 135 ++ usr/src/cmd/awk/parse.c | 135 ++ usr/src/cmd/awk/proc.c | 82 ++ usr/src/cmd/awk/token.c | 97 ++ usr/src/cmd/awk/tokenscript | 11 + usr/src/cmd/awk/tran.c | 237 ++++ usr/src/cmd/dc/dc.c | 1940 ++++++++++++++++++++++++++++ usr/src/cmd/dc/dc.h | 117 ++ usr/src/cmd/eqn/diacrit.c | 56 + usr/src/cmd/eqn/e.h | 42 + usr/src/cmd/eqn/e.y | 166 +++ usr/src/cmd/eqn/eqnbox.c | 25 + usr/src/cmd/eqn/font.c | 59 + usr/src/cmd/eqn/fromto.c | 45 + usr/src/cmd/eqn/funny.c | 26 + usr/src/cmd/eqn/glob.c | 27 + usr/src/cmd/eqn/integral.c | 30 + usr/src/cmd/eqn/io.c | 195 +++ usr/src/cmd/eqn/lex.c | 211 +++ usr/src/cmd/eqn/lookup.c | 217 ++++ usr/src/cmd/eqn/mark.c | 17 + usr/src/cmd/eqn/matrix.c | 62 + usr/src/cmd/eqn/move.c | 18 + usr/src/cmd/eqn/over.c | 29 + usr/src/cmd/eqn/paren.c | 105 ++ usr/src/cmd/eqn/pile.c | 62 + usr/src/cmd/eqn/shift.c | 103 ++ usr/src/cmd/eqn/size.c | 46 + usr/src/cmd/eqn/sqrt.c | 17 + usr/src/cmd/eqn/text.c | 170 +++ usr/src/cmd/graph/graph.c | 693 ++++++++++ usr/src/cmd/learn/README | 43 + usr/src/cmd/learn/copy.c | 272 ++++ usr/src/cmd/learn/dounit.c | 59 + usr/src/cmd/learn/lcount.c | 12 + usr/src/cmd/learn/learn.c | 47 + usr/src/cmd/learn/list.c | 30 + usr/src/cmd/learn/lrndef | 18 + usr/src/cmd/learn/lrnref | 46 + usr/src/cmd/learn/makpipe.c | 20 + usr/src/cmd/learn/maktee.c | 46 + usr/src/cmd/learn/mem.c | 94 ++ usr/src/cmd/learn/mysys.c | 120 ++ usr/src/cmd/learn/origmakefile | 68 + usr/src/cmd/learn/selsub.c | 94 ++ usr/src/cmd/learn/selunit.c | 102 ++ usr/src/cmd/learn/temp | 5 + usr/src/cmd/learn/whatnow.c | 28 + usr/src/cmd/learn/wrapup.c | 26 + usr/src/cmd/lex/header.c | 109 ++ usr/src/cmd/lex/ldefs.c | 162 +++ usr/src/cmd/lex/lmain.c | 227 ++++ usr/src/cmd/lex/ncform | 179 +++ usr/src/cmd/lex/once.c | 130 ++ usr/src/cmd/lex/parser.y | 710 ++++++++++ usr/src/cmd/lex/sub1.c | 683 ++++++++++ usr/src/cmd/lex/sub2.c | 951 ++++++++++++++ usr/src/cmd/lint/READ_ME | 3 + usr/src/cmd/lint/SHELL | 23 + usr/src/cmd/lint/lint.c | 793 ++++++++++++ usr/src/cmd/lint/llib-lc | 105 ++ usr/src/cmd/lint/llib-port | 44 + usr/src/cmd/lint/lmanifest | 18 + usr/src/cmd/lint/lpass2.c | 367 ++++++ usr/src/cmd/lint/macdefs | 71 + usr/src/cmd/m4/m4.c | 899 +++++++++++++ usr/src/cmd/m4/m4y.y | 94 ++ usr/src/cmd/neqn/diacrit.c | 44 + usr/src/cmd/neqn/e.h | 42 + usr/src/cmd/neqn/e.y | 166 +++ usr/src/cmd/neqn/eqnbox.c | 25 + usr/src/cmd/neqn/font.c | 59 + usr/src/cmd/neqn/fromto.c | 45 + usr/src/cmd/neqn/funny.c | 26 + usr/src/cmd/neqn/glob.c | 27 + usr/src/cmd/neqn/integral.c | 31 + usr/src/cmd/neqn/io.c | 195 +++ usr/src/cmd/neqn/lex.c | 211 +++ usr/src/cmd/neqn/lookup.c | 217 ++++ usr/src/cmd/neqn/mark.c | 17 + usr/src/cmd/neqn/matrix.c | 62 + usr/src/cmd/neqn/move.c | 18 + usr/src/cmd/neqn/over.c | 28 + usr/src/cmd/neqn/paren.c | 106 ++ usr/src/cmd/neqn/pile.c | 62 + usr/src/cmd/neqn/shift.c | 70 + usr/src/cmd/neqn/size.c | 46 + usr/src/cmd/neqn/sqrt.c | 12 + usr/src/cmd/neqn/text.c | 170 +++ usr/src/cmd/plot/chrtab.c | 98 ++ usr/src/cmd/plot/driver.c | 128 ++ usr/src/cmd/plot/vplot.c | 376 ++++++ usr/src/cmd/prof/prof.c | 321 +++++ usr/src/cmd/ratfor/r.g | 66 + usr/src/cmd/ratfor/r.h | 64 + usr/src/cmd/ratfor/r0.c | 83 ++ usr/src/cmd/ratfor/r1.c | 371 ++++++ usr/src/cmd/ratfor/r2.c | 210 +++ usr/src/cmd/ratfor/rlex.c | 244 ++++ usr/src/cmd/ratfor/rlook.c | 67 + usr/src/cmd/refer/Makefile | 52 + usr/src/cmd/refer/deliv1.c | 45 + usr/src/cmd/refer/deliv2.c | 47 + usr/src/cmd/refer/flagger.c | 163 +++ usr/src/cmd/refer/glue1.c | 259 ++++ usr/src/cmd/refer/glue2.c | 11 + usr/src/cmd/refer/glue3.c | 69 + usr/src/cmd/refer/glue4.c | 96 ++ usr/src/cmd/refer/hunt1.c | 227 ++++ usr/src/cmd/refer/hunt2.c | 267 ++++ usr/src/cmd/refer/hunt3.c | 43 + usr/src/cmd/refer/hunt5.c | 50 + usr/src/cmd/refer/hunt6.c | 110 ++ usr/src/cmd/refer/hunt7.c | 104 ++ usr/src/cmd/refer/hunt9.c | 6 + usr/src/cmd/refer/inv2.c | 90 ++ usr/src/cmd/refer/inv3.c | 16 + usr/src/cmd/refer/inv5.c | 50 + usr/src/cmd/refer/inv6.c | 73 ++ usr/src/cmd/refer/kaiser.c | 274 ++++ usr/src/cmd/refer/mkey2.c | 137 ++ usr/src/cmd/refer/mkey3.c | 50 + usr/src/cmd/refer/refer0.c | 27 + usr/src/cmd/refer/refer1.c | 151 +++ usr/src/cmd/refer/refer2.c | 203 +++ usr/src/cmd/refer/refer3.c | 26 + usr/src/cmd/refer/refer4.c | 65 + usr/src/cmd/refer/refer5.c | 274 ++++ usr/src/cmd/refer/refer8.c | 32 + usr/src/cmd/refer/sample | 1737 +++++++++++++++++++++++++ usr/src/cmd/refer/shell.c | 24 + usr/src/cmd/refer/test | 60 + usr/src/cmd/refer/thash.c | 140 ++ usr/src/cmd/refer/types.c | 14 + usr/src/cmd/refer/what..c | 17 + usr/src/cmd/refer/what1.c | 133 ++ usr/src/cmd/refer/what3.c | 71 + usr/src/cmd/refer/what4.c | 163 +++ usr/src/cmd/sed/sed0.c | 966 ++++++++++++++ usr/src/cmd/sh/args.c | 135 ++ usr/src/cmd/sh/blok.c | 111 ++ usr/src/cmd/sh/brkincr.h | 2 + usr/src/cmd/sh/builtin.c | 2 + usr/src/cmd/sh/cmd.c | 406 ++++++ usr/src/cmd/sh/ctype.c | 108 ++ usr/src/cmd/sh/ctype.h | 90 ++ usr/src/cmd/sh/dup.h | 10 + usr/src/cmd/sh/error.c | 83 ++ usr/src/cmd/sh/expand.c | 190 +++ usr/src/cmd/sh/fault.c | 109 ++ usr/src/cmd/sh/mac.h | 60 + usr/src/cmd/sh/macro.c | 233 ++++ usr/src/cmd/sh/mode.h | 205 +++ usr/src/cmd/sh/name.c | 320 +++++ usr/src/cmd/sh/name.h | 25 + usr/src/cmd/sh/print.c | 97 ++ usr/src/cmd/sh/setbrk.c | 17 + usr/src/cmd/sh/stak.c | 81 ++ usr/src/cmd/sh/stak.h | 76 ++ usr/src/cmd/sh/string.c | 55 + usr/src/cmd/sh/sym.h | 46 + usr/src/cmd/sh/word.c | 124 ++ usr/src/cmd/spell/american | 319 +++++ usr/src/cmd/spell/british | 324 +++++ usr/src/cmd/spell/local | 0 usr/src/cmd/spell/spell.c | 535 ++++++++ usr/src/cmd/spell/spell.h | 72 ++ usr/src/cmd/spell/spell.sh | 28 + usr/src/cmd/spell/spellin.c | 40 + usr/src/cmd/spell/spellout.c | 43 + usr/src/cmd/spell/stop | 927 +++++++++++++ usr/src/cmd/struct/0.alloc.c | 153 +++ usr/src/cmd/struct/0.args.c | 98 ++ usr/src/cmd/struct/0.def.c | 11 + usr/src/cmd/struct/0.extr.c | 26 + usr/src/cmd/struct/0.graph.c | 59 + usr/src/cmd/struct/0.list.c | 66 + usr/src/cmd/struct/0.parts.c | 120 ++ usr/src/cmd/struct/0.string.c | 106 ++ usr/src/cmd/struct/1.defs.h | 152 +++ usr/src/cmd/struct/1.finish.c | 38 + usr/src/cmd/struct/1.form.c | 218 ++++ usr/src/cmd/struct/1.fort.c | 260 ++++ usr/src/cmd/struct/1.hash.c | 238 ++++ usr/src/cmd/struct/1.incl.h | 39 + usr/src/cmd/struct/1.init.c | 48 + usr/src/cmd/struct/1.line.c | 116 ++ usr/src/cmd/struct/1.main.c | 13 + usr/src/cmd/struct/1.node.c | 48 + usr/src/cmd/struct/1.recog.c | 374 ++++++ usr/src/cmd/struct/1.tables.c | 220 ++++ usr/src/cmd/struct/2.def.h | 4 + usr/src/cmd/struct/2.dfs.c | 173 +++ usr/src/cmd/struct/2.dom.c | 50 + usr/src/cmd/struct/2.head.c | 107 ++ usr/src/cmd/struct/2.inarc.c | 69 + usr/src/cmd/struct/2.main.c | 49 + usr/src/cmd/struct/2.test.c | 45 + usr/src/cmd/struct/2.tree.c | 131 ++ usr/src/cmd/struct/3.branch.c | 88 ++ usr/src/cmd/struct/3.def.h | 6 + usr/src/cmd/struct/3.flow.c | 89 ++ usr/src/cmd/struct/3.loop.c | 152 +++ usr/src/cmd/struct/3.main.c | 33 + usr/src/cmd/struct/3.reach.c | 143 ++ usr/src/cmd/struct/3.test.c | 11 + usr/src/cmd/struct/3.then.c | 75 ++ usr/src/cmd/struct/4.brace.c | 56 + usr/src/cmd/struct/4.def.h | 11 + usr/src/cmd/struct/4.form.c | 113 ++ usr/src/cmd/struct/4.main.c | 22 + usr/src/cmd/struct/4.out.c | 292 +++++ usr/src/cmd/struct/Makefile | 49 + usr/src/cmd/struct/b.h | 10 + usr/src/cmd/struct/bdef.c | 4 + usr/src/cmd/struct/beauty.y | 410 ++++++ usr/src/cmd/struct/def.h | 118 ++ usr/src/cmd/struct/lextab.l | 216 ++++ usr/src/cmd/struct/main.c | 69 + usr/src/cmd/struct/struct | 19 + usr/src/cmd/struct/tree.c | 238 ++++ usr/src/cmd/tbl/t..c | 71 + usr/src/cmd/tbl/t0.c | 48 + usr/src/cmd/tbl/t2.c | 21 + usr/src/cmd/tbl/t3.c | 93 ++ usr/src/cmd/tbl/t4.c | 233 ++++ usr/src/cmd/tbl/t5.c | 166 +++ usr/src/cmd/tbl/t6.c | 202 +++ usr/src/cmd/tbl/t7.c | 131 ++ usr/src/cmd/tbl/t8.c | 327 +++++ usr/src/cmd/tbl/t9.c | 62 + usr/src/cmd/tbl/tb.c | 82 ++ usr/src/cmd/tbl/tc.c | 60 + usr/src/cmd/tbl/tf.c | 51 + usr/src/cmd/tbl/tg.c | 69 + usr/src/cmd/tbl/ti.c | 56 + usr/src/cmd/tbl/tm.c | 63 + usr/src/cmd/tbl/ts.c | 49 + usr/src/cmd/tbl/tt.c | 85 ++ usr/src/cmd/tbl/tu.c | 202 +++ usr/src/cmd/tbl/tv.c | 147 +++ usr/src/cmd/tp/tp.h | 85 ++ usr/src/cmd/tp/tp0.c | 2 + usr/src/cmd/tp/tp2.c | 348 +++++ usr/src/cmd/tp/tp3.c | 248 ++++ usr/src/cmd/troff/term/code.300 | 211 +++ usr/src/cmd/troff/term/tab300.c | 59 + usr/src/cmd/troff/term/tab300S.c | 59 + usr/src/cmd/troff/term/tab300X.c | 59 + usr/src/cmd/troff/term/tab300s.c | 59 + usr/src/cmd/troff/term/tab37.c | 269 ++++ usr/src/cmd/troff/term/tab450-12.c | 59 + usr/src/cmd/troff/term/tab450.c | 59 + usr/src/cmd/troff/term/tab450X.c | 59 + usr/src/cmd/troff/term/tabtn300.c | 269 ++++ usr/src/cmd/uudiff/lenrem.c | 9 + usr/src/cmd/uudiff/locpart.c | 8 + usr/src/cmd/uudiff/printable.c | 12 + usr/src/cmd/uudiff/remdiff | 113 ++ usr/src/cmd/uudiff/run1.c | 76 ++ usr/src/cmd/uudiff/trim.c | 15 + usr/src/cmd/xsend/enroll.c | 36 + usr/src/cmd/xsend/lib.c | 109 ++ usr/src/cmd/xsend/xget.c | 139 ++ usr/src/cmd/xsend/xmail.h | 8 + usr/src/cmd/xsend/xsend.c | 122 ++ usr/src/cmd/yacc/dextern | 259 ++++ usr/src/cmd/yacc/y1.c | 653 ++++++++++ usr/src/cmd/yacc/y2.c | 859 ++++++++++++ usr/src/cmd/yacc/y3.c | 404 ++++++ usr/src/cmd/yacc/y4.c | 325 +++++ usr/src/cmd/yacc/yaccdiffs | 198 +++ usr/src/cmd/yacc/yaccnews | 149 +++ usr/src/cmd/yacc/yaccpar | 149 +++ 279 files changed, 40932 insertions(+) create mode 100644 usr/src/cmd/awk/awk.def create mode 100644 usr/src/cmd/awk/awk.g.y create mode 100644 usr/src/cmd/awk/awk.h create mode 100644 usr/src/cmd/awk/awk.lx.l create mode 100644 usr/src/cmd/awk/b.c create mode 100644 usr/src/cmd/awk/dump.c create mode 100644 usr/src/cmd/awk/parse.c create mode 100644 usr/src/cmd/awk/proc.c create mode 100644 usr/src/cmd/awk/token.c create mode 100644 usr/src/cmd/awk/tokenscript create mode 100644 usr/src/cmd/awk/tran.c create mode 100644 usr/src/cmd/dc/dc.c create mode 100644 usr/src/cmd/dc/dc.h create mode 100644 usr/src/cmd/eqn/diacrit.c create mode 100644 usr/src/cmd/eqn/e.h create mode 100644 usr/src/cmd/eqn/e.y create mode 100644 usr/src/cmd/eqn/eqnbox.c create mode 100644 usr/src/cmd/eqn/font.c create mode 100644 usr/src/cmd/eqn/fromto.c create mode 100644 usr/src/cmd/eqn/funny.c create mode 100644 usr/src/cmd/eqn/glob.c create mode 100644 usr/src/cmd/eqn/integral.c create mode 100644 usr/src/cmd/eqn/io.c create mode 100644 usr/src/cmd/eqn/lex.c create mode 100644 usr/src/cmd/eqn/lookup.c create mode 100644 usr/src/cmd/eqn/mark.c create mode 100644 usr/src/cmd/eqn/matrix.c create mode 100644 usr/src/cmd/eqn/move.c create mode 100644 usr/src/cmd/eqn/over.c create mode 100644 usr/src/cmd/eqn/paren.c create mode 100644 usr/src/cmd/eqn/pile.c create mode 100644 usr/src/cmd/eqn/shift.c create mode 100644 usr/src/cmd/eqn/size.c create mode 100644 usr/src/cmd/eqn/sqrt.c create mode 100644 usr/src/cmd/eqn/text.c create mode 100644 usr/src/cmd/graph/graph.c create mode 100644 usr/src/cmd/learn/README create mode 100644 usr/src/cmd/learn/copy.c create mode 100644 usr/src/cmd/learn/dounit.c create mode 100644 usr/src/cmd/learn/lcount.c create mode 100644 usr/src/cmd/learn/learn.c create mode 100644 usr/src/cmd/learn/list.c create mode 100644 usr/src/cmd/learn/lrndef create mode 100644 usr/src/cmd/learn/lrnref create mode 100644 usr/src/cmd/learn/makpipe.c create mode 100644 usr/src/cmd/learn/maktee.c create mode 100644 usr/src/cmd/learn/mem.c create mode 100644 usr/src/cmd/learn/mysys.c create mode 100644 usr/src/cmd/learn/origmakefile create mode 100644 usr/src/cmd/learn/selsub.c create mode 100644 usr/src/cmd/learn/selunit.c create mode 100644 usr/src/cmd/learn/temp create mode 100644 usr/src/cmd/learn/whatnow.c create mode 100644 usr/src/cmd/learn/wrapup.c create mode 100644 usr/src/cmd/lex/header.c create mode 100644 usr/src/cmd/lex/ldefs.c create mode 100644 usr/src/cmd/lex/lmain.c create mode 100644 usr/src/cmd/lex/ncform create mode 100644 usr/src/cmd/lex/once.c create mode 100644 usr/src/cmd/lex/parser.y create mode 100644 usr/src/cmd/lex/sub1.c create mode 100644 usr/src/cmd/lex/sub2.c create mode 100644 usr/src/cmd/lint/READ_ME create mode 100755 usr/src/cmd/lint/SHELL create mode 100644 usr/src/cmd/lint/lint.c create mode 100644 usr/src/cmd/lint/llib-lc create mode 100644 usr/src/cmd/lint/llib-port create mode 100644 usr/src/cmd/lint/lmanifest create mode 100644 usr/src/cmd/lint/lpass2.c create mode 100644 usr/src/cmd/lint/macdefs create mode 100644 usr/src/cmd/m4/m4.c create mode 100644 usr/src/cmd/m4/m4y.y create mode 100644 usr/src/cmd/neqn/diacrit.c create mode 100644 usr/src/cmd/neqn/e.h create mode 100644 usr/src/cmd/neqn/e.y create mode 100644 usr/src/cmd/neqn/eqnbox.c create mode 100644 usr/src/cmd/neqn/font.c create mode 100644 usr/src/cmd/neqn/fromto.c create mode 100644 usr/src/cmd/neqn/funny.c create mode 100644 usr/src/cmd/neqn/glob.c create mode 100644 usr/src/cmd/neqn/integral.c create mode 100644 usr/src/cmd/neqn/io.c create mode 100644 usr/src/cmd/neqn/lex.c create mode 100644 usr/src/cmd/neqn/lookup.c create mode 100644 usr/src/cmd/neqn/mark.c create mode 100644 usr/src/cmd/neqn/matrix.c create mode 100644 usr/src/cmd/neqn/move.c create mode 100644 usr/src/cmd/neqn/over.c create mode 100644 usr/src/cmd/neqn/paren.c create mode 100644 usr/src/cmd/neqn/pile.c create mode 100644 usr/src/cmd/neqn/shift.c create mode 100644 usr/src/cmd/neqn/size.c create mode 100644 usr/src/cmd/neqn/sqrt.c create mode 100644 usr/src/cmd/neqn/text.c create mode 100644 usr/src/cmd/plot/chrtab.c create mode 100644 usr/src/cmd/plot/driver.c create mode 100644 usr/src/cmd/plot/vplot.c create mode 100644 usr/src/cmd/prof/prof.c create mode 100644 usr/src/cmd/ratfor/r.g create mode 100644 usr/src/cmd/ratfor/r.h create mode 100644 usr/src/cmd/ratfor/r0.c create mode 100644 usr/src/cmd/ratfor/r1.c create mode 100644 usr/src/cmd/ratfor/r2.c create mode 100644 usr/src/cmd/ratfor/rlex.c create mode 100644 usr/src/cmd/ratfor/rlook.c create mode 100644 usr/src/cmd/refer/Makefile create mode 100644 usr/src/cmd/refer/deliv1.c create mode 100644 usr/src/cmd/refer/deliv2.c create mode 100644 usr/src/cmd/refer/flagger.c create mode 100644 usr/src/cmd/refer/glue1.c create mode 100644 usr/src/cmd/refer/glue2.c create mode 100644 usr/src/cmd/refer/glue3.c create mode 100644 usr/src/cmd/refer/glue4.c create mode 100644 usr/src/cmd/refer/hunt1.c create mode 100644 usr/src/cmd/refer/hunt2.c create mode 100644 usr/src/cmd/refer/hunt3.c create mode 100644 usr/src/cmd/refer/hunt5.c create mode 100644 usr/src/cmd/refer/hunt6.c create mode 100644 usr/src/cmd/refer/hunt7.c create mode 100644 usr/src/cmd/refer/hunt9.c create mode 100644 usr/src/cmd/refer/inv2.c create mode 100644 usr/src/cmd/refer/inv3.c create mode 100644 usr/src/cmd/refer/inv5.c create mode 100644 usr/src/cmd/refer/inv6.c create mode 100644 usr/src/cmd/refer/kaiser.c create mode 100644 usr/src/cmd/refer/mkey2.c create mode 100644 usr/src/cmd/refer/mkey3.c create mode 100644 usr/src/cmd/refer/refer0.c create mode 100644 usr/src/cmd/refer/refer1.c create mode 100644 usr/src/cmd/refer/refer2.c create mode 100644 usr/src/cmd/refer/refer3.c create mode 100644 usr/src/cmd/refer/refer4.c create mode 100644 usr/src/cmd/refer/refer5.c create mode 100644 usr/src/cmd/refer/refer8.c create mode 100644 usr/src/cmd/refer/sample create mode 100644 usr/src/cmd/refer/shell.c create mode 100644 usr/src/cmd/refer/test create mode 100644 usr/src/cmd/refer/thash.c create mode 100644 usr/src/cmd/refer/types.c create mode 100644 usr/src/cmd/refer/what..c create mode 100644 usr/src/cmd/refer/what1.c create mode 100644 usr/src/cmd/refer/what3.c create mode 100644 usr/src/cmd/refer/what4.c create mode 100644 usr/src/cmd/sed/sed0.c create mode 100644 usr/src/cmd/sh/args.c create mode 100644 usr/src/cmd/sh/blok.c create mode 100644 usr/src/cmd/sh/brkincr.h create mode 100644 usr/src/cmd/sh/builtin.c create mode 100644 usr/src/cmd/sh/cmd.c create mode 100644 usr/src/cmd/sh/ctype.c create mode 100644 usr/src/cmd/sh/ctype.h create mode 100644 usr/src/cmd/sh/dup.h create mode 100644 usr/src/cmd/sh/error.c create mode 100644 usr/src/cmd/sh/expand.c create mode 100644 usr/src/cmd/sh/fault.c create mode 100644 usr/src/cmd/sh/mac.h create mode 100644 usr/src/cmd/sh/macro.c create mode 100644 usr/src/cmd/sh/mode.h create mode 100644 usr/src/cmd/sh/name.c create mode 100644 usr/src/cmd/sh/name.h create mode 100644 usr/src/cmd/sh/print.c create mode 100644 usr/src/cmd/sh/setbrk.c create mode 100644 usr/src/cmd/sh/stak.c create mode 100644 usr/src/cmd/sh/stak.h create mode 100644 usr/src/cmd/sh/string.c create mode 100644 usr/src/cmd/sh/sym.h create mode 100644 usr/src/cmd/sh/word.c create mode 100644 usr/src/cmd/spell/american create mode 100644 usr/src/cmd/spell/british create mode 100644 usr/src/cmd/spell/local create mode 100644 usr/src/cmd/spell/spell.c create mode 100644 usr/src/cmd/spell/spell.h create mode 100755 usr/src/cmd/spell/spell.sh create mode 100644 usr/src/cmd/spell/spellin.c create mode 100644 usr/src/cmd/spell/spellout.c create mode 100644 usr/src/cmd/spell/stop create mode 100644 usr/src/cmd/struct/0.alloc.c create mode 100644 usr/src/cmd/struct/0.args.c create mode 100644 usr/src/cmd/struct/0.def.c create mode 100644 usr/src/cmd/struct/0.extr.c create mode 100644 usr/src/cmd/struct/0.graph.c create mode 100644 usr/src/cmd/struct/0.list.c create mode 100644 usr/src/cmd/struct/0.parts.c create mode 100644 usr/src/cmd/struct/0.string.c create mode 100644 usr/src/cmd/struct/1.defs.h create mode 100644 usr/src/cmd/struct/1.finish.c create mode 100644 usr/src/cmd/struct/1.form.c create mode 100644 usr/src/cmd/struct/1.fort.c create mode 100644 usr/src/cmd/struct/1.hash.c create mode 100644 usr/src/cmd/struct/1.incl.h create mode 100644 usr/src/cmd/struct/1.init.c create mode 100644 usr/src/cmd/struct/1.line.c create mode 100644 usr/src/cmd/struct/1.main.c create mode 100644 usr/src/cmd/struct/1.node.c create mode 100644 usr/src/cmd/struct/1.recog.c create mode 100644 usr/src/cmd/struct/1.tables.c create mode 100644 usr/src/cmd/struct/2.def.h create mode 100644 usr/src/cmd/struct/2.dfs.c create mode 100644 usr/src/cmd/struct/2.dom.c create mode 100644 usr/src/cmd/struct/2.head.c create mode 100644 usr/src/cmd/struct/2.inarc.c create mode 100644 usr/src/cmd/struct/2.main.c create mode 100644 usr/src/cmd/struct/2.test.c create mode 100644 usr/src/cmd/struct/2.tree.c create mode 100644 usr/src/cmd/struct/3.branch.c create mode 100644 usr/src/cmd/struct/3.def.h create mode 100644 usr/src/cmd/struct/3.flow.c create mode 100644 usr/src/cmd/struct/3.loop.c create mode 100644 usr/src/cmd/struct/3.main.c create mode 100644 usr/src/cmd/struct/3.reach.c create mode 100644 usr/src/cmd/struct/3.test.c create mode 100644 usr/src/cmd/struct/3.then.c create mode 100644 usr/src/cmd/struct/4.brace.c create mode 100644 usr/src/cmd/struct/4.def.h create mode 100644 usr/src/cmd/struct/4.form.c create mode 100644 usr/src/cmd/struct/4.main.c create mode 100644 usr/src/cmd/struct/4.out.c create mode 100644 usr/src/cmd/struct/Makefile create mode 100644 usr/src/cmd/struct/b.h create mode 100644 usr/src/cmd/struct/bdef.c create mode 100644 usr/src/cmd/struct/beauty.y create mode 100644 usr/src/cmd/struct/def.h create mode 100644 usr/src/cmd/struct/lextab.l create mode 100644 usr/src/cmd/struct/main.c create mode 100755 usr/src/cmd/struct/struct create mode 100644 usr/src/cmd/struct/tree.c create mode 100644 usr/src/cmd/tbl/t..c create mode 100644 usr/src/cmd/tbl/t0.c create mode 100644 usr/src/cmd/tbl/t2.c create mode 100644 usr/src/cmd/tbl/t3.c create mode 100644 usr/src/cmd/tbl/t4.c create mode 100644 usr/src/cmd/tbl/t5.c create mode 100644 usr/src/cmd/tbl/t6.c create mode 100644 usr/src/cmd/tbl/t7.c create mode 100644 usr/src/cmd/tbl/t8.c create mode 100644 usr/src/cmd/tbl/t9.c create mode 100644 usr/src/cmd/tbl/tb.c create mode 100644 usr/src/cmd/tbl/tc.c create mode 100644 usr/src/cmd/tbl/tf.c create mode 100644 usr/src/cmd/tbl/tg.c create mode 100644 usr/src/cmd/tbl/ti.c create mode 100644 usr/src/cmd/tbl/tm.c create mode 100644 usr/src/cmd/tbl/ts.c create mode 100644 usr/src/cmd/tbl/tt.c create mode 100644 usr/src/cmd/tbl/tu.c create mode 100644 usr/src/cmd/tbl/tv.c create mode 100644 usr/src/cmd/tp/tp.h create mode 100644 usr/src/cmd/tp/tp0.c create mode 100644 usr/src/cmd/tp/tp2.c create mode 100644 usr/src/cmd/tp/tp3.c create mode 100644 usr/src/cmd/troff/term/code.300 create mode 100644 usr/src/cmd/troff/term/tab300.c create mode 100644 usr/src/cmd/troff/term/tab300S.c create mode 100644 usr/src/cmd/troff/term/tab300X.c create mode 100644 usr/src/cmd/troff/term/tab300s.c create mode 100644 usr/src/cmd/troff/term/tab37.c create mode 100644 usr/src/cmd/troff/term/tab450-12.c create mode 100644 usr/src/cmd/troff/term/tab450.c create mode 100644 usr/src/cmd/troff/term/tab450X.c create mode 100644 usr/src/cmd/troff/term/tabtn300.c create mode 100644 usr/src/cmd/uudiff/lenrem.c create mode 100644 usr/src/cmd/uudiff/locpart.c create mode 100644 usr/src/cmd/uudiff/printable.c create mode 100755 usr/src/cmd/uudiff/remdiff create mode 100644 usr/src/cmd/uudiff/run1.c create mode 100644 usr/src/cmd/uudiff/trim.c create mode 100644 usr/src/cmd/xsend/enroll.c create mode 100644 usr/src/cmd/xsend/lib.c create mode 100644 usr/src/cmd/xsend/xget.c create mode 100644 usr/src/cmd/xsend/xmail.h create mode 100644 usr/src/cmd/xsend/xsend.c create mode 100644 usr/src/cmd/yacc/dextern create mode 100644 usr/src/cmd/yacc/y1.c create mode 100644 usr/src/cmd/yacc/y2.c create mode 100644 usr/src/cmd/yacc/y3.c create mode 100644 usr/src/cmd/yacc/y4.c create mode 100644 usr/src/cmd/yacc/yaccdiffs create mode 100644 usr/src/cmd/yacc/yaccnews create mode 100644 usr/src/cmd/yacc/yaccpar diff --git a/usr/src/cmd/awk/awk.def b/usr/src/cmd/awk/awk.def new file mode 100644 index 0000000000..7de49fc642 --- /dev/null +++ b/usr/src/cmd/awk/awk.def @@ -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 index 0000000000..3a51f76273 --- /dev/null +++ b/usr/src/cmd/awk/awk.g.y @@ -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 index 0000000000..5f2df5f0f0 --- /dev/null +++ b/usr/src/cmd/awk/awk.h @@ -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 index 0000000000..7e0799b67f --- /dev/null +++ b/usr/src/cmd/awk/awk.lx.l @@ -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('}'); + } + +^\n lineno++; +^{WS}*#.*\n lineno++; /* strip comment lines */ +{WS} ; +"\\"\n lineno++; +"||" RETURN(BOR); +BEGIN RETURN(XBEGIN); +END RETURN(XEND); +PROGEND RETURN(EOF); +"&&" RETURN(AND); +"!" RETURN(NOT); +"!=" { yylval = NE; RETURN(RELOP); } +"~" { yylval = MATCH; RETURN(MATCHOP); } +"!~" { yylval = NOTMATCH; RETURN(MATCHOP); } +"<" { yylval = LT; RETURN(RELOP); } +"<=" { yylval = LE; RETURN(RELOP); } +"==" { yylval = EQ; RETURN(RELOP); } +">=" { yylval = GE; RETURN(RELOP); } +">" { yylval = GT; RETURN(RELOP); } +">>" { yylval = APPEND; RETURN(RELOP); } +"++" { yylval = INCR; RETURN(INCR); } +"--" { yylval = DECR; RETURN(DECR); } +"+=" { yylval = ADDEQ; RETURN(ASGNOP); } +"-=" { yylval = SUBEQ; RETURN(ASGNOP); } +"*=" { yylval = MULTEQ; RETURN(ASGNOP); } +"/=" { yylval = DIVEQ; RETURN(ASGNOP); } +"%=" { yylval = MODEQ; RETURN(ASGNOP); } +"=" { yylval = ASSIGN; RETURN(ASGNOP); } + +"$"{D}+ { if (atoi(yytext+1)==0) { + yylval = lookup("$record", symtab); + RETURN(STRING); + } else { + yylval = fieldadr(atoi(yytext+1)); + RETURN(FIELD); + } + } +"$"{WS}* { RETURN(INDIRECT); } +NF { mustfld=1; yylval = setsymtab(yytext, NULL, 0.0, NUM, symtab); RETURN(VAR); } +({D}+("."?){D}*|"."{D}+)((e|E)("+"|-)?{D}+)? { + yylval = setsymtab(yytext, NULL, atof(yytext), CON|NUM, symtab); RETURN(NUMBER); } +"}"{WS}*\n { BEGIN sc; lineno++; RETURN(';'); } +"}" { BEGIN sc; RETURN(';'); } +;\n { lineno++; RETURN(';'); } +\n { lineno++; RETURN(NL); } +while RETURN(WHILE); +for RETURN(FOR); +if RETURN(IF); +else RETURN(ELSE); +next RETURN(NEXT); +exit RETURN(EXIT); +break RETURN(BREAK); +continue RETURN(CONTINUE); +print { yylval = PRINT; RETURN(PRINT); } +printf { yylval = PRINTF; RETURN(PRINTF); } +sprintf { yylval = SPRINTF; RETURN(SPRINTF); } +split { yylval = SPLIT; RETURN(SPLIT); } +substr RETURN(SUBSTR); +index RETURN(INDEX); +in RETURN(IN); +length { yylval = FLENGTH; RETURN(FNCN); } +log { yylval = FLOG; RETURN(FNCN); } +int { yylval = FINT; RETURN(FNCN); } +exp { yylval = FEXP; RETURN(FNCN); } +sqrt { yylval = FSQRT; RETURN(FNCN); } +{A}{B}* { yylval = setsymtab(yytext, tostring(""), 0.0, STR, symtab); RETURN(VAR); } +\" { BEGIN str; clen=0; } + +# { BEGIN comment; } +\n { BEGIN A; lineno++; RETURN(NL); } +. ; + +. { yylval = yytext[0]; RETURN(yytext[0]); } + +"[" { BEGIN chc; clen=0; cflag=0; } +"[^" { BEGIN chc; clen=0; cflag=1; } + +"?" RETURN(QUEST); +"+" RETURN(PLUS); +"*" RETURN(STAR); +"|" RETURN(OR); +"." RETURN(DOT); +"(" RETURN('('); +")" RETURN(')'); +"^" RETURN('^'); +"$" RETURN('$'); +\\. { if (yytext[1]=='n') yylval = '\n'; + else if (yytext[1] == 't') yylval = '\t'; + else yylval = yytext[1]; + RETURN(CHAR); + } +"/" { BEGIN A; unput('/'); } +\n { yyerror("newline in regular expression"); lineno++; BEGIN A; } +. { yylval = yytext[0]; RETURN(CHAR); } + +\" { BEGIN A; cbuf[clen]=0; yylval = setsymtab("", tostring(cbuf), 0.0, CON|STR, symtab); RETURN(STRING); } +\n { yyerror("newline in string"); lineno++; BEGIN A; } +"\\\"" { cbuf[clen++]='"'; } +"\\"n { cbuf[clen++]='\n'; } +"\\"t { cbuf[clen++]='\t'; } +"\\\\" { cbuf[clen++]='\\'; } +. CADD; + +"\\""]" { cbuf[clen++]=']'; } +"]" { BEGIN reg; cbuf[clen]=0; yylval = tostring(cbuf); + if (cflag==0) { RETURN(CCL); } + else { RETURN(NCCL); } } +\n { yyerror("newline in character class"); lineno++; BEGIN A; } +. 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 index 0000000000..a3c6040998 --- /dev/null +++ b/usr/src/cmd/awk/b.c @@ -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= 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 index 0000000000..5319cee573 --- /dev/null +++ b/usr/src/cmd/awk/dump.c @@ -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 index 0000000000..24ef508814 --- /dev/null +++ b/usr/src/cmd/awk/parse.c @@ -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 index 0000000000..a64aee9580 --- /dev/null +++ b/usr/src/cmd/awk/proc.c @@ -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;itoken!=0; p++) + names[p->token-FIRSTTOKEN] = p->pname; + for(i=0; i= 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 index 0000000000..809784c301 --- /dev/null +++ b/usr/src/cmd/awk/tokenscript @@ -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 index 0000000000..769e8dfad0 --- /dev/null +++ b/usr/src/cmd/awk/tran.c @@ -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 index 0000000000..e1c8a41816 --- /dev/null +++ b/usr/src/cmd/dc/dc.c @@ -0,0 +1,1940 @@ +#include +#include +#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=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= 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(hrd = (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(ptrlast)*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;ival; + 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 index 0000000000..eaea5af13d --- /dev/null +++ b/usr/src/cmd/dc/dc.h @@ -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 index 0000000000..236868f02e --- /dev/null +++ b/usr/src/cmd/eqn/diacrit.c @@ -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 index 0000000000..54fa047d57 --- /dev/null +++ b/usr/src/cmd/eqn/e.h @@ -0,0 +1,42 @@ +#include + +#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 index 0000000000..f294e59738 --- /dev/null +++ b/usr/src/cmd/eqn/e.y @@ -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 index 0000000000..2aea8da378 --- /dev/null +++ b/usr/src/cmd/eqn/eqnbox.c @@ -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 index 0000000000..3ef0e85c7b --- /dev/null +++ b/usr/src/cmd/eqn/font.c @@ -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 index 0000000000..d973b15d82 --- /dev/null +++ b/usr/src/cmd/eqn/fromto.c @@ -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 index 0000000000..a041d14265 --- /dev/null +++ b/usr/src/cmd/eqn/funny.c @@ -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 index 0000000000..834a33f4f6 --- /dev/null +++ b/usr/src/cmd/eqn/glob.c @@ -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 index 0000000000..6e4bcb7b74 --- /dev/null +++ b/usr/src/cmd/eqn/integral.c @@ -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 index 0000000000..776bac7877 --- /dev/null +++ b/usr/src/cmd/eqn/io.c @@ -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 index 0000000000..19860a2307 --- /dev/null +++ b/usr/src/cmd/eqn/lex.c @@ -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 index 0000000000..aa6ea9279b --- /dev/null +++ b/usr/src/cmd/eqn/lookup.c @@ -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 index 0000000000..6e03156bfa --- /dev/null +++ b/usr/src/cmd/eqn/mark.c @@ -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 index 0000000000..209e37be71 --- /dev/null +++ b/usr/src/cmd/eqn/matrix.c @@ -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\\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 index 0000000000..f789581414 --- /dev/null +++ b/usr/src/cmd/eqn/paren.c @@ -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; jmid; 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\\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 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 index 0000000000..8f99fa6804 --- /dev/null +++ b/usr/src/cmd/eqn/size.c @@ -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 index 0000000000..2229328854 --- /dev/null +++ b/usr/src/cmd/eqn/sqrt.c @@ -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 index 0000000000..79289d0845 --- /dev/null +++ b/usr/src/cmd/eqn/text.c @@ -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 index 0000000000..7bd4125549 --- /dev/null +++ b/usr/src/cmd/graph/graph.c @@ -0,0 +1,693 @@ +#include +#include +#include +#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;ixlbf && p->xlb>v[i].xv) + p->xlb = v[i].xv; + if(!p->xubf && p->xubxub = 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= 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/2) + r /= 2; + else if(r0) { + 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; ixf==log10&&!p->xqf) { + for(x=p->xquant; xxub; 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; ixa*(*p->xf)(xv*p->xmult) + p->xb; + if(ixxbot || 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 index 0000000000..1d5333e2a9 --- /dev/null +++ b/usr/src/cmd/learn/README @@ -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 index 0000000000..8d1f0f753a --- /dev/null +++ b/usr/src/cmd/learn/copy.c @@ -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 index 0000000000..26a65d423e --- /dev/null +++ b/usr/src/cmd/learn/dounit.c @@ -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 index 0000000000..110d827bc9 --- /dev/null +++ b/usr/src/cmd/learn/lcount.c @@ -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 index 0000000000..3080f3f214 --- /dev/null +++ b/usr/src/cmd/learn/learn.c @@ -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 index 0000000000..76cf6e8999 --- /dev/null +++ b/usr/src/cmd/learn/list.c @@ -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 index 0000000000..be6b992df5 --- /dev/null +++ b/usr/src/cmd/learn/lrndef @@ -0,0 +1,18 @@ +#include +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 index 0000000000..602c0b2fc9 --- /dev/null +++ b/usr/src/cmd/learn/lrnref @@ -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 index 0000000000..94e09c8f26 --- /dev/null +++ b/usr/src/cmd/learn/makpipe.c @@ -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 index 0000000000..1585ac2a64 --- /dev/null +++ b/usr/src/cmd/learn/maktee.c @@ -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 index 0000000000..b226a8d5c8 --- /dev/null +++ b/usr/src/cmd/learn/mem.c @@ -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 index 0000000000..77b4a2e556 --- /dev/null +++ b/usr/src/cmd/learn/mysys.c @@ -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 index 0000000000..e7aa1f116c --- /dev/null +++ b/usr/src/cmd/learn/origmakefile @@ -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 index 0000000000..0685a5fdff --- /dev/null +++ b/usr/src/cmd/learn/selsub.c @@ -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 index 0000000000..ed5d1c9ee4 --- /dev/null +++ b/usr/src/cmd/learn/selunit.c @@ -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; k1) { + 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 index 0000000000..8fe50c03fc --- /dev/null +++ b/usr/src/cmd/learn/temp @@ -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 index 0000000000..7a61164659 --- /dev/null +++ b/usr/src/cmd/learn/whatnow.c @@ -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 index 0000000000..cdf44cca62 --- /dev/null +++ b/usr/src/cmd/learn/wrapup.c @@ -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 index 0000000000..1e9561cc3f --- /dev/null +++ b/usr/src/cmd/lex/header.c @@ -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 +# 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 index 0000000000..3ef43af2ef --- /dev/null +++ b/usr/src/cmd/lex/lmain.c @@ -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(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 index 0000000000..8ca51b4cb5 --- /dev/null +++ b/usr/src/cmd/lex/ncform @@ -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 index 0000000000..f9b524975d --- /dev/null +++ b/usr/src/cmd/lex/once.c @@ -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 index 0000000000..81df2d0387 --- /dev/null +++ b/usr/src/cmd/lex/parser.y @@ -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 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){ + 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= 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 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 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= 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 index 0000000000..45dc1a99eb --- /dev/null +++ b/usr/src/cmd/lex/sub1.c @@ -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) return; + i = cindex[i]; + /* see if ccl is already in our table */ + j = 0; + if(i){ + for(j=1;j= NCH) return; /* already in */ + m = 0; + k = 0; + for(i=1;i 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= 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= 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= 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 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 LINESIZE){ + charc = 0; + printf("\n\t"); + } + } + putchar('\n'); + } +# endif + /* for each char, calculate next state */ + n = 0; + for(i = 1; i= 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=0;i--){ /* for each state */ + j = state[i]; + if(count == *j++){ + for(k=0;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 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 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= 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;iNACTIONS) 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 LINESIZE){ + printf("\n\t"); + charc = 0; + } + } + putchar('\n'); + } + charc = 0; + printf("match:\n"); + for(i=0;i LINESIZE){ + putchar('\n'); + charc = 0; + } + } + putchar('\n'); + return; + } +# endif +mkmatch(){ + register int i; + char tab[NCH]; + for(i=0; i 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=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=0;i--){ + j = array[i]; + if(j && *j++ == count){ + for(k=0;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 index 0000000000..4d4dd044cd --- /dev/null +++ b/usr/src/cmd/lint/READ_ME @@ -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 index 0000000000..dbb6febe57 --- /dev/null +++ b/usr/src/cmd/lint/SHELL @@ -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 index 0000000000..663cd634c2 --- /dev/null +++ b/usr/src/cmd/lint/lint.c @@ -0,0 +1,793 @@ +# include "mfile1" + +# include "lmanifest" + +# include + +# 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; iop == 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 index 0000000000..ebff38efe1 --- /dev/null +++ b/usr/src/cmd/lint/llib-lc @@ -0,0 +1,105 @@ + /* LINTLIBRARY */ +#include +#include +#include +#include +#include +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 index 0000000000..c4773af05b --- /dev/null +++ b/usr/src/cmd/lint/llib-port @@ -0,0 +1,44 @@ + /* LINTLIBRARY */ +#include + 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 index 0000000000..2a6ed882a4 --- /dev/null +++ b/usr/src/cmd/lint/lmanifest @@ -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 index 0000000000..5c2086470d --- /dev/null +++ b/usr/src/cmd/lint/lpass2.c @@ -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; iatyp[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; inargs; ++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 index 0000000000..3ec81bc365 --- /dev/null +++ b/usr/src/cmd/lint/macdefs @@ -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 index 0000000000..3e6ce5bc52 --- /dev/null +++ b/usr/src/cmd/m4/m4.c @@ -0,0 +1,899 @@ +#include +#include + +#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; inext) + 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 index 0000000000..40f5a3b787 --- /dev/null +++ b/usr/src/cmd/m4/m4y.y @@ -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 index 0000000000..d38d24db38 --- /dev/null +++ b/usr/src/cmd/neqn/diacrit.c @@ -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 index 0000000000..4722f6b4f2 --- /dev/null +++ b/usr/src/cmd/neqn/e.h @@ -0,0 +1,42 @@ +#include + +#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 index 0000000000..f294e59738 --- /dev/null +++ b/usr/src/cmd/neqn/e.y @@ -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 index 0000000000..2aea8da378 --- /dev/null +++ b/usr/src/cmd/neqn/eqnbox.c @@ -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 index 0000000000..e4e026e6be --- /dev/null +++ b/usr/src/cmd/neqn/font.c @@ -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 index 0000000000..d792d1e70d --- /dev/null +++ b/usr/src/cmd/neqn/fromto.c @@ -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 index 0000000000..1b93818e89 --- /dev/null +++ b/usr/src/cmd/neqn/funny.c @@ -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 index 0000000000..834a33f4f6 --- /dev/null +++ b/usr/src/cmd/neqn/glob.c @@ -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 index 0000000000..1247250709 --- /dev/null +++ b/usr/src/cmd/neqn/integral.c @@ -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 index 0000000000..541d31dd60 --- /dev/null +++ b/usr/src/cmd/neqn/io.c @@ -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 index 0000000000..19860a2307 --- /dev/null +++ b/usr/src/cmd/neqn/lex.c @@ -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 index 0000000000..aa6ea9279b --- /dev/null +++ b/usr/src/cmd/neqn/lookup.c @@ -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 index 0000000000..6e03156bfa --- /dev/null +++ b/usr/src/cmd/neqn/mark.c @@ -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 index 0000000000..209e37be71 --- /dev/null +++ b/usr/src/cmd/neqn/matrix.c @@ -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\\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 index 0000000000..58c91bb252 --- /dev/null +++ b/usr/src/cmd/neqn/paren.c @@ -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; jmid; 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\\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 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 index 0000000000..8f99fa6804 --- /dev/null +++ b/usr/src/cmd/neqn/size.c @@ -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 index 0000000000..ea20beae7e --- /dev/null +++ b/usr/src/cmd/neqn/sqrt.c @@ -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 index 0000000000..0686dcac45 --- /dev/null +++ b/usr/src/cmd/neqn/text.c @@ -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 index 0000000000..4d8a81acc9 --- /dev/null +++ b/usr/src/cmd/plot/chrtab.c @@ -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 index 0000000000..52d0b1f30c --- /dev/null +++ b/usr/src/cmd/plot/driver.c @@ -0,0 +1,128 @@ +#include + +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 + +#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 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 index 0000000000..519c1ecc2a --- /dev/null +++ b/usr/src/cmd/prof/prof.c @@ -0,0 +1,321 @@ +/* + * Print execution profile + */ + +#include +#include +#include +#include + +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 (cpvalue > 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= 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; npvalue < 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; nptime/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 (ab) + 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 index 0000000000..c692f2ce6f --- /dev/null +++ b/usr/src/cmd/ratfor/r.g @@ -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 index 0000000000..47a6ee7e7b --- /dev/null +++ b/usr/src/cmd/ratfor/r.h @@ -0,0 +1,64 @@ +#include +#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 index 0000000000..3d84e705c1 --- /dev/null +++ b/usr/src/cmd/ratfor/r0.c @@ -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 index 0000000000..b43b8c0683 --- /dev/null +++ b/usr/src/cmd/ratfor/r1.c @@ -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 index 0000000000..435933c73d --- /dev/null +++ b/usr/src/cmd/ratfor/r2.c @@ -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 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 index 0000000000..c150d24862 --- /dev/null +++ b/usr/src/cmd/ratfor/rlex.c @@ -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 index 0000000000..0ebf64a923 --- /dev/null +++ b/usr/src/cmd/ratfor/rlook.c @@ -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 index 0000000000..ad96bcc375 --- /dev/null +++ b/usr/src/cmd/refer/Makefile @@ -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 index 0000000000..ae4a57bf30 --- /dev/null +++ b/usr/src/cmd/refer/deliv1.c @@ -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 index 0000000000..2405991de6 --- /dev/null +++ b/usr/src/cmd/refer/deliv2.c @@ -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 index 0000000000..435cd5a505 --- /dev/null +++ b/usr/src/cmd/refer/flagger.c @@ -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 index 0000000000..076fbbe08e --- /dev/null +++ b/usr/src/cmd/refer/glue1.c @@ -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=t && *s != '/') s--; + if (s 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 index 0000000000..53cfaac5e4 --- /dev/null +++ b/usr/src/cmd/refer/glue4.c @@ -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 index 0000000000..6c6ddc90c2 --- /dev/null +++ b/usr/src/cmd/refer/hunt1.c @@ -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; ktags ? tags: nfound, fc); + } +} + +char * +todir(t) + char *t; +{ + char *s; + s=t; + while (*s) s++; + while (s>=t && *s != '/') s--; + if (s0); +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; i0) + { + for(j=0; j=nf) break; + if (j= 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 nterm) + { + _assert(g0) + { + best=0; + for(j=0; jbest) best = coord[j]; +# if D1 + fprintf(stderr, "colevel %d best %d\n", colevel, best); +# endif + reached = best; + for(g=j=0; j 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_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 index 0000000000..589f6c39b6 --- /dev/null +++ b/usr/src/cmd/refer/hunt6.c @@ -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= 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 index 0000000000..6a7430897c --- /dev/null +++ b/usr/src/cmd/refer/hunt7.c @@ -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= 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 index 0000000000..73b615f561 --- /dev/null +++ b/usr/src/cmd/refer/hunt9.c @@ -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 index 0000000000..a3f9e419df --- /dev/null +++ b/usr/src/cmd/refer/inv2.c @@ -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; ikey) + 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 index 0000000000..0448f4e486 --- /dev/null +++ b/usr/src/cmd/refer/inv3.c @@ -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 index 0000000000..7aa5886cd4 --- /dev/null +++ b/usr/src/cmd/refer/inv5.c @@ -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'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;i0) + { + 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 index 0000000000..94949b1293 --- /dev/null +++ b/usr/src/cmd/refer/mkey2.c @@ -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) && (used0 && 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 index 0000000000..0787400eeb --- /dev/null +++ b/usr/src/cmd/refer/mkey3.c @@ -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; iNSERCH) + 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 index 0000000000..ccec3dab76 --- /dev/null +++ b/usr/src/cmd/refer/refer2.c @@ -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 (rLLINE) + 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)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 index 0000000000..748fe9196a --- /dev/null +++ b/usr/src/cmd/refer/refer5.c @@ -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 (sd0) 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= 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; iNFLAB) + 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 1) + { + igap /= 2; + imax = n-igap; + do + { + iex=0; + for(i=0; i0); + } +} diff --git a/usr/src/cmd/refer/test b/usr/src/cmd/refer/test new file mode 100644 index 0000000000..74a0e118eb --- /dev/null +++ b/usr/src/cmd/refer/test @@ -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 index 0000000000..037800c81e --- /dev/null +++ b/usr/src/cmd/refer/thash.c @@ -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; i0 ? n : -n); +} diff --git a/usr/src/cmd/refer/types.c b/usr/src/cmd/refer/types.c new file mode 100644 index 0000000000..d9348e6542 --- /dev/null +++ b/usr/src/cmd/refer/types.c @@ -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 index 0000000000..0aa00a517d --- /dev/null +++ b/usr/src/cmd/refer/what..c @@ -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 index 0000000000..6fbb4c1cc9 --- /dev/null +++ b/usr/src/cmd/refer/what1.c @@ -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; ifdate != 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; affdate); + 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 (knm, 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_file); +for(iarg=1; iargnm=s, NAMES, ansf)==0) + break; + trimnl(s); + if (*s==0) continue; + while (*s++); + _assert(snm, &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 index 0000000000..e9a2bd38cd --- /dev/null +++ b/usr/src/cmd/refer/what4.c @@ -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] && nf0) + word[j].ct++; + } + } while (any>0); +shell ( TSIZE, wcomp, wexch ); +for(nw=0; word[nw].ct >0 && nw=nin*2 && word[nw].ct != word[0].ct) + break; +for(i=0; i0 ? 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 +#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 index 0000000000..5fe26de528 --- /dev/null +++ b/usr/src/cmd/sh/args.c @@ -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 index 0000000000..df09ace0f1 --- /dev/null +++ b/usr/src/cmd/sh/blok.c @@ -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 pword) &= ~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 qbloktop 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 index 0000000000..2c4c254be3 --- /dev/null +++ b/usr/src/cmd/sh/brkincr.h @@ -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 index 0000000000..9125740da8 --- /dev/null +++ b/usr/src/cmd/sh/builtin.c @@ -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 index 0000000000..94c33379ed --- /dev/null +++ b/usr/src/cmd/sh/cmd.c @@ -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 index 0000000000..63cebe5330 --- /dev/null +++ b/usr/src/cmd/sh/ctype.c @@ -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 index 0000000000..0566f7c3a2 --- /dev/null +++ b/usr/src/cmd/sh/ctype.h @@ -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)"E)==0 ANDF _ctype1[c]&(T_SPC)) +#define eofmeta(c) (((c)"E)==0 ANDF _ctype1[c]&(_META|T_EOF)) +#define qotchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_QOT)) +#define eolchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_EOR|T_EOF)) +#define dipchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_DIP)) +#define subchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_SUB|T_QOT)) +#define escchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_ESC)) + +char _ctype2[]; + +#define digit(c) (((c)"E)==0 ANDF _ctype2[c]&(T_DIG)) +#define fngchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_FNG)) +#define dolchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_AST|T_BRC|T_DIG|T_IDC|T_SHN)) +#define defchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_DEF)) +#define setchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_SET)) +#define digchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_AST|T_DIG)) +#define letter(c) (((c)"E)==0 ANDF _ctype2[c]&(T_IDC)) +#define alphanum(c) (((c)"E)==0 ANDF _ctype2[c]&(_IDCH)) +#define astchar(c) (((c)"E)==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 index 0000000000..4d65981d02 --- /dev/null +++ b/usr/src/cmd/sh/dup.h @@ -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 index 0000000000..144aa66b94 --- /dev/null +++ b/usr/src/cmd/sh/error.c @@ -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 index 0000000000..dd96540914 --- /dev/null +++ b/usr/src/cmd/sh/expand.c @@ -0,0 +1,190 @@ +# +/* + * UNIX shell + * + * S. R. Bourne + * Bell Telephone Laboratories + * + */ + +#include "defs.h" +#include +#define DIRSIZ 15 +#include +#include + + + +/* 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 index 0000000000..9a60de3ed9 --- /dev/null +++ b/usr/src/cmd/sh/fault.c @@ -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 index 0000000000..46f0ab10fa --- /dev/null +++ b/usr/src/cmd/sh/mac.h @@ -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 index 0000000000..fd9b4eba1e --- /dev/null +++ b/usr/src/cmd/sh/macro.c @@ -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 index 0000000000..4fb3a52de4 --- /dev/null +++ b/usr/src/cmd/sh/mode.h @@ -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 index 0000000000..6567b55d96 --- /dev/null +++ b/usr/src/cmd/sh/name.c @@ -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 index 0000000000..4686107aab --- /dev/null +++ b/usr/src/cmd/sh/name.h @@ -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 index 0000000000..740268eeae --- /dev/null +++ b/usr/src/cmd/sh/print.c @@ -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 index 0000000000..84745c70b2 --- /dev/null +++ b/usr/src/cmd/sh/setbrk.c @@ -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 index 0000000000..ed36f084e4 --- /dev/null +++ b/usr/src/cmd/sh/stak.c @@ -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-stakbotADR(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 index 0000000000..09b853d5f7 --- /dev/null +++ b/usr/src/cmd/sh/stak.h @@ -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 index 0000000000..5ad20e8cda --- /dev/null +++ b/usr/src/cmd/sh/string.c @@ -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 index 0000000000..0ed5623a4a --- /dev/null +++ b/usr/src/cmd/sh/sym.h @@ -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 index 0000000000..d194446f12 --- /dev/null +++ b/usr/src/cmd/sh/word.c @@ -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 index 0000000000..7015f97888 --- /dev/null +++ b/usr/src/cmd/spell/american @@ -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 index 0000000000..9d58195643 --- /dev/null +++ b/usr/src/cmd/spell/british @@ -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 index 0000000000..e69de29bb2 diff --git a/usr/src/cmd/spell/spell.c b/usr/src/cmd/spell/spell.c new file mode 100644 index 0000000000..13369c4e0d --- /dev/null +++ b/usr/src/cmd/spell/spell.c @@ -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; cpsuf;t++) { + cp = ep; + while(*sp) + if(*--cp!=*sp++) + goto next; + for(sp=cp; --sp>=word&&!vowel(*sp); ) ; + if(spp1)(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))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;cp0); + strcat(affix,"\t"); + return(i); +} + + +monosyl(bp,ep) +char *bp, *ep; +{ + if(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 +#include + +#ifndef unix +#define SHIFT 5 +#define TABSIZE (int)(400000/(1< 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>SHIFT]&(1<<((int)h&((1<>SHIFT] |= 1<<((int)h&((1<>$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 index 0000000000..3f46c2b9a4 --- /dev/null +++ b/usr/src/cmd/spell/spellin.c @@ -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; i1 && 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 +#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 = nblk))+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 index 0000000000..8df41c7c51 --- /dev/null +++ b/usr/src/cmd/struct/0.args.c @@ -0,0 +1,98 @@ +#include +# +#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 index 0000000000..4c4b32d5a8 --- /dev/null +++ b/usr/src/cmd/struct/0.def.c @@ -0,0 +1,11 @@ +#include +#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 index 0000000000..a558e2393f --- /dev/null +++ b/usr/src/cmd/struct/0.extr.c @@ -0,0 +1,26 @@ +#include +#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 index 0000000000..f2618f68f5 --- /dev/null +++ b/usr/src/cmd/struct/0.graph.c @@ -0,0 +1,59 @@ +#include +#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 index 0000000000..de8d1ae19f --- /dev/null +++ b/usr/src/cmd/struct/0.list.c @@ -0,0 +1,66 @@ +#include +#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 index 0000000000..e9241719aa --- /dev/null +++ b/usr/src/cmd/struct/0.parts.c @@ -0,0 +1,120 @@ +#include +#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 index 0000000000..994ec421f6 --- /dev/null +++ b/usr/src/cmd/struct/0.string.c @@ -0,0 +1,106 @@ +#include +#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 index 0000000000..d0ab63fbb5 --- /dev/null +++ b/usr/src/cmd/struct/1.defs.h @@ -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 index 0000000000..14045fde0f --- /dev/null +++ b/usr/src/cmd/struct/1.finish.c @@ -0,0 +1,38 @@ +#include +#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 index 0000000000..df8173c320 --- /dev/null +++ b/usr/src/cmd/struct/1.form.c @@ -0,0 +1,218 @@ +#include +#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 index 0000000000..5dc0658650 --- /dev/null +++ b/usr/src/cmd/struct/1.fort.c @@ -0,0 +1,260 @@ +#include +#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 index 0000000000..db0847ea28 --- /dev/null +++ b/usr/src/cmd/struct/1.hash.c @@ -0,0 +1,238 @@ +#include +#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) 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 index 0000000000..1ff82a9840 --- /dev/null +++ b/usr/src/cmd/struct/1.incl.h @@ -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 index 0000000000..5f907e3a67 --- /dev/null +++ b/usr/src/cmd/struct/1.init.c @@ -0,0 +1,48 @@ +#include +#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 index 0000000000..7cc98e95e2 --- /dev/null +++ b/usr/src/cmd/struct/1.line.c @@ -0,0 +1,116 @@ +#include +# +#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 index 0000000000..40e78488af --- /dev/null +++ b/usr/src/cmd/struct/1.main.c @@ -0,0 +1,13 @@ +#include +#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 index 0000000000..b57ff11cff --- /dev/null +++ b/usr/src/cmd/struct/1.node.c @@ -0,0 +1,48 @@ +#include +#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 index 0000000000..6e15c84554 --- /dev/null +++ b/usr/src/cmd/struct/1.recog.c @@ -0,0 +1,374 @@ +#include +#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 index 0000000000..490456eb4e --- /dev/null +++ b/usr/src/cmd/struct/1.tables.c @@ -0,0 +1,220 @@ +#include + +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 index 0000000000..7f6795ebf6 --- /dev/null +++ b/usr/src/cmd/struct/2.def.h @@ -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 index 0000000000..36eeb1b468 --- /dev/null +++ b/usr/src/cmd/struct/2.dfs.c @@ -0,0 +1,173 @@ +#include +# +/* 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 index 0000000000..e0a9f852a0 --- /dev/null +++ b/usr/src/cmd/struct/2.dom.c @@ -0,0 +1,50 @@ +#include +# +/* +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 index 0000000000..f538bce86c --- /dev/null +++ b/usr/src/cmd/struct/2.head.c @@ -0,0 +1,107 @@ +#include +# +/* +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 index 0000000000..dc9f060f4d --- /dev/null +++ b/usr/src/cmd/struct/2.inarc.c @@ -0,0 +1,69 @@ +#include +# +/* 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 index 0000000000..4e0bf65ff7 --- /dev/null +++ b/usr/src/cmd/struct/2.main.c @@ -0,0 +1,49 @@ +#include +#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 index 0000000000..7ce2bf470f --- /dev/null +++ b/usr/src/cmd/struct/2.test.c @@ -0,0 +1,45 @@ +#include +# +/* 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 index 0000000000..f8a33e3e55 --- /dev/null +++ b/usr/src/cmd/struct/2.tree.c @@ -0,0 +1,131 @@ +#include +# +/* 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 index 0000000000..58768e4be5 --- /dev/null +++ b/usr/src/cmd/struct/3.branch.c @@ -0,0 +1,88 @@ +#include +#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 index 0000000000..6722a535b4 --- /dev/null +++ b/usr/src/cmd/struct/3.def.h @@ -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 index 0000000000..7f3fad473d --- /dev/null +++ b/usr/src/cmd/struct/3.flow.c @@ -0,0 +1,89 @@ +#include +# +/* +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 index 0000000000..6d5ef5cdb7 --- /dev/null +++ b/usr/src/cmd/struct/3.loop.c @@ -0,0 +1,152 @@ +#include +#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 index 0000000000..fb4dd5934c --- /dev/null +++ b/usr/src/cmd/struct/3.main.c @@ -0,0 +1,33 @@ +#include +#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 index 0000000000..99e6a42264 --- /dev/null +++ b/usr/src/cmd/struct/3.reach.c @@ -0,0 +1,143 @@ +#include +# +/* +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 index 0000000000..b389e4c142 --- /dev/null +++ b/usr/src/cmd/struct/3.test.c @@ -0,0 +1,11 @@ +#include +# +/* 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 index 0000000000..6b056bf453 --- /dev/null +++ b/usr/src/cmd/struct/3.then.c @@ -0,0 +1,75 @@ +#include +#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 index 0000000000..1d14d780f0 --- /dev/null +++ b/usr/src/cmd/struct/4.brace.c @@ -0,0 +1,56 @@ +#include +#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 index 0000000000..a5530d134d --- /dev/null +++ b/usr/src/cmd/struct/4.def.h @@ -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 index 0000000000..c85ec44f37 --- /dev/null +++ b/usr/src/cmd/struct/4.form.c @@ -0,0 +1,113 @@ +#include +# +#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 index 0000000000..3002a1fb8b --- /dev/null +++ b/usr/src/cmd/struct/4.main.c @@ -0,0 +1,22 @@ +#include +#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 index 0000000000..89ec32e5e7 --- /dev/null +++ b/usr/src/cmd/struct/4.out.c @@ -0,0 +1,292 @@ +#include +#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 index 0000000000..bbbe3e70c1 --- /dev/null +++ b/usr/src/cmd/struct/Makefile @@ -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 index 0000000000..24b7509c9b --- /dev/null +++ b/usr/src/cmd/struct/b.h @@ -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 index 0000000000..88aa3d200c --- /dev/null +++ b/usr/src/cmd/struct/bdef.c @@ -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 index 0000000000..067c08cab6 --- /dev/null +++ b/usr/src/cmd/struct/beauty.y @@ -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 +%} + +%% +%{ +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 +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 index 0000000000..47d86c711f --- /dev/null +++ b/usr/src/cmd/struct/def.h @@ -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 index 0000000000..6842baf7eb --- /dev/null +++ b/usr/src/cmd/struct/lextab.l @@ -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 index 0000000000..8a8b5a12c7 --- /dev/null +++ b/usr/src/cmd/struct/main.c @@ -0,0 +1,69 @@ +#include +#include +#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 index 0000000000..69d2383943 --- /dev/null +++ b/usr/src/cmd/struct/struct @@ -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 + + +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 index 0000000000..4334622511 --- /dev/null +++ b/usr/src/cmd/tbl/t..c @@ -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 index 0000000000..5ad82c6377 --- /dev/null +++ b/usr/src/cmd/tbl/t0.c @@ -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 index 0000000000..780dc79ffe --- /dev/null +++ b/usr/src/cmd/tbl/t2.c @@ -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 index 0000000000..22f71ec019 --- /dev/null +++ b/usr/src/cmd/tbl/t3.c @@ -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 index 0000000000..61ad3574bb --- /dev/null +++ b/usr/src/cmd/tbl/t4.c @@ -0,0 +1,233 @@ + /* t4.c: read table specification */ +# include "t..c" +int oncol; +getspec() +{ +int icol, i; +for(icol=0; icol0) {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=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 index 0000000000..1cc245f582 --- /dev/null +++ b/usr/src/cmd/tbl/t5.c @@ -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 MAXCHS) + cstore = cspace = chspace(); + } +last = cstore; +permute(); +if (textflg) untext(); +return; +} +nodata(il) +{ +int c; +for (c=0; c=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 index 0000000000..3909b98da5 --- /dev/null +++ b/usr/src/cmd/tbl/t6.c @@ -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 =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=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\\n(%d .nr %d \\n(%d\n", + icol+CRIGHT, TMP, TMP, icol+CRIGHT); + } + for(icol=0; icol0 .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 index 0000000000..40bb471499 --- /dev/null +++ b/usr/src/cmd/tbl/t7.c @@ -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=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=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=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 index 0000000000..e868dd8e98 --- /dev/null +++ b/usr/src/cmd/tbl/t8.c @@ -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; c0 && 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=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=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=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; c0) 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=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=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 index 0000000000..dda72eeaf4 --- /dev/null +++ b/usr/src/cmd/tbl/t9.c @@ -0,0 +1,62 @@ + /* t9.c: write lines for tables over 200 lines */ +# include "t..c" +static useln; +yetmore() +{ +for(useln=0; 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 =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= 128 || s<0); +} diff --git a/usr/src/cmd/tbl/tf.c b/usr/src/cmd/tbl/tf.c new file mode 100644 index 0000000000..e65a632c31 --- /dev/null +++ b/usr/src/cmd/tbl/tf.c @@ -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\\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 index 0000000000..5df0c3a58d --- /dev/null +++ b/usr/src/cmd/tbl/ti.c @@ -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 index 0000000000..e9c03286e5 --- /dev/null +++ b/usr/src/cmd/tbl/tm.c @@ -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 index 0000000000..e0f8b1c43d --- /dev/null +++ b/usr/src/cmd/tbl/ts.c @@ -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 index 0000000000..ae345569df --- /dev/null +++ b/usr/src/cmd/tbl/tt.c @@ -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(arcol : 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 index 0000000000..4a08347702 --- /dev/null +++ b/usr/src/cmd/tbl/tu.c @@ -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; cr0 && vspand(prev(i),cl,1)) + cl++; + for(cr=cl; cr0 && vspand(prev(i),cr,1)) + break; + if (cl1) + { + 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=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=0 && lefdata(i,c)==kind) + i=prev(li=i); +if (prev(li)== -1) li=0; +*lwidp=kind; +for(lj= i+1; lj=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 =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 index 0000000000..eaf0c8b058 --- /dev/null +++ b/usr/src/cmd/tbl/tv.c @@ -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; ln1) + 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 index 0000000000..a3a29d57c1 --- /dev/null +++ b/usr/src/cmd/tp/tp.h @@ -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 index 0000000000..04a5c21724 --- /dev/null +++ b/usr/src/cmd/tp/tp0.c @@ -0,0 +1,2 @@ +#include "tp.h" +#include diff --git a/usr/src/cmd/tp/tp2.c b/usr/src/cmd/tp/tp2.c new file mode 100644 index 0000000000..09197a41e6 --- /dev/null +++ b/usr/src/cmd/tp/tp2.c @@ -0,0 +1,348 @@ +#include "tp.h" +#include +#include +#include +#include + +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;ipathnam[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 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 index 0000000000..c754ae6d61 --- /dev/null +++ b/usr/src/cmd/tp/tp3.c @@ -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= 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 index 0000000000..eaf6514223 --- /dev/null +++ b/usr/src/cmd/troff/term/code.300 @@ -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 index 0000000000..f4af9eea53 --- /dev/null +++ b/usr/src/cmd/troff/term/tab300.c @@ -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 index 0000000000..8d2b8581fb --- /dev/null +++ b/usr/src/cmd/troff/term/tab300S.c @@ -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 index 0000000000..f4af9eea53 --- /dev/null +++ b/usr/src/cmd/troff/term/tab300X.c @@ -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 index 0000000000..8d2b8581fb --- /dev/null +++ b/usr/src/cmd/troff/term/tab300s.c @@ -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 index 0000000000..e391923628 --- /dev/null +++ b/usr/src/cmd/troff/term/tab37.c @@ -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 index 0000000000..f38e7ad450 --- /dev/null +++ b/usr/src/cmd/troff/term/tab450-12.c @@ -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 index 0000000000..1ebcd34adf --- /dev/null +++ b/usr/src/cmd/troff/term/tab450.c @@ -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 index 0000000000..687afb22d4 --- /dev/null +++ b/usr/src/cmd/troff/term/tab450X.c @@ -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 index 0000000000..fa1934e8a9 --- /dev/null +++ b/usr/src/cmd/troff/term/tabtn300.c @@ -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 index 0000000000..1ee56e91ce --- /dev/null +++ b/usr/src/cmd/uudiff/lenrem.c @@ -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 index 0000000000..e0a7176396 --- /dev/null +++ b/usr/src/cmd/uudiff/locpart.c @@ -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 index 0000000000..2c94072fae --- /dev/null +++ b/usr/src/cmd/uudiff/printable.c @@ -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 index 0000000000..e2aa3427ab --- /dev/null +++ b/usr/src/cmd/uudiff/remdiff @@ -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 <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 <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 index 0000000000..60e6553d5c --- /dev/null +++ b/usr/src/cmd/uudiff/run1.c @@ -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 index 0000000000..c989966b43 --- /dev/null +++ b/usr/src/cmd/uudiff/trim.c @@ -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 index 0000000000..f2e8e14d03 --- /dev/null +++ b/usr/src/cmd/xsend/enroll.c @@ -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 index 0000000000..22508a71df --- /dev/null +++ b/usr/src/cmd/xsend/lib.c @@ -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 index 0000000000..93b06aa1e9 --- /dev/null +++ b/usr/src/cmd/xsend/xget.c @@ -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= 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 index 0000000000..1d637a343a --- /dev/null +++ b/usr/src/cmd/xsend/xmail.h @@ -0,0 +1,8 @@ +#include +#include +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 index 0000000000..cd53806bad --- /dev/null +++ b/usr/src/cmd/xsend/xsend.c @@ -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 +# include +# 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;i0 ; ++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; ilset; + 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 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= 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;lpitem != 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; llook->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]; spitem == *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= 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 index 0000000000..a625896a5f --- /dev/null +++ b/usr/src/cmd/yacc/y2.c @@ -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)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 $ 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 index 0000000000..7e793734e8 --- /dev/null +++ b/usr/src/cmd/yacc/y3.c @@ -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 && cpitem) ) 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 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 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; i1 ) 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 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; r1 ) 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; n1 ) 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= 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 &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 index 0000000000..e5f7f4fda6 --- /dev/null +++ b/usr/src/cmd/yacc/yaccdiffs @@ -0,0 +1,198 @@ + + + + + + + + + + Yacc Differences + + + + + +This document gives a short list of differences between the +new Yacc and earlier Yaccs. + +_B_u_g_s _F_i_x_e_d + +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. + +_S_p_e_e_d_u_p_s, _S_h_r_i_n_k_s, _a_n_d _D_i_d_d_l_e_s + +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. + +_N_e_w _F_e_a_t_u_r_e_s + +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 index 0000000000..547c81e41b --- /dev/null +++ b/usr/src/cmd/yacc/yaccnews @@ -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 + $$ + and + $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 index 0000000000..daa01c4f5b --- /dev/null +++ b/usr/src/cmd/yacc/yaccpar @@ -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 */ + + } -- 2.20.1