From: Bill Joy Date: Mon, 12 Feb 1979 13:51:39 +0000 (-0800) Subject: BSD 4 development X-Git-Tag: BSD-4~655 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/aaa7ced1b84fa0d4da00361d50f95982dcf5da97?hp=4ea773b42de23f78cf1d0c20f79ae98839331db3 BSD 4 development Work on file usr/src/cmd/eqn/diacrit.c Work on file usr/src/cmd/dc/dc.h Work on file usr/src/cmd/eqn/e.h Work on file usr/src/cmd/eqn/shift.c Work on file usr/src/cmd/eqn/font.c Work on file usr/src/cmd/eqn/eqnbox.c Work on file usr/src/cmd/eqn/integral.c Work on file usr/src/cmd/eqn/pile.c Work on file usr/src/cmd/eqn/over.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/matrix.c Work on file usr/src/cmd/eqn/glob.c Work on file usr/src/cmd/eqn/io.c Work on file usr/src/cmd/eqn/funny.c Work on file usr/src/cmd/eqn/move.c Work on file usr/src/cmd/eqn/size.c Work on file usr/src/cmd/eqn/e.y Work on file usr/src/cmd/eqn/text.c Work on file usr/src/cmd/eqn/paren.c Work on file usr/src/cmd/eqn/mark.c Work on file usr/src/cmd/eqn/sqrt.c Work on file usr/src/cmd/graph/graph.c Work on file usr/src/cmd/learn/selunit.c Work on file usr/src/cmd/learn/copy.c Work on file usr/src/cmd/learn/lrndef Work on file usr/src/cmd/learn/mysys.c Work on file usr/src/cmd/learn/lcount.c Work on file usr/src/cmd/learn/README Work on file usr/src/cmd/learn/list.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/dounit.c Work on file usr/src/cmd/learn/makpipe.c Work on file usr/src/cmd/learn/learn.c Work on file usr/src/cmd/learn/maktee.c Work on file usr/src/cmd/learn/selsub.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/ldefs.c Work on file usr/src/cmd/lex/lmain.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/parser.y Work on file usr/src/cmd/lex/sub1.c Work on file usr/src/cmd/lex/sub2.c Work on file usr/src/cmd/lex/once.c Work on file usr/src/cmd/m4/m4y.y Work on file usr/src/cmd/m4/m4.c Work on file usr/src/cmd/neqn/io.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/fromto.c 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/integral.c Work on file usr/src/cmd/neqn/funny.c Work on file usr/src/cmd/neqn/font.c Work on file usr/src/cmd/neqn/glob.c Work on file usr/src/cmd/neqn/pile.c Work on file usr/src/cmd/neqn/lex.c Work on file usr/src/cmd/neqn/text.c Work on file usr/src/cmd/neqn/paren.c Work on file usr/src/cmd/neqn/lookup.c Work on file usr/src/cmd/neqn/mark.c Work on file usr/src/cmd/neqn/move.c Work on file usr/src/cmd/neqn/shift.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/sqrt.c Work on file usr/src/cmd/neqn/size.c Work on file usr/src/cmd/plot/chrtab.c Work on file usr/src/cmd/plot/vplot.c Work on file usr/src/cmd/plot/driver.c Work on file usr/src/cmd/ratfor/rlook.c Work on file usr/src/cmd/ratfor/rlex.c Work on file usr/src/cmd/ratfor/r2.c Work on file usr/src/cmd/ratfor/r.h Work on file usr/src/cmd/ratfor/r1.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/refer/glue2.c Work on file usr/src/cmd/refer/hunt3.c Work on file usr/src/cmd/refer/Makefile Work on file usr/src/cmd/refer/glue1.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/hunt6.c Work on file usr/src/cmd/refer/flagger.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/hunt1.c Work on file usr/src/cmd/refer/deliv1.c Work on file usr/src/cmd/refer/deliv2.c Work on file usr/src/cmd/refer/glue4.c Work on file usr/src/cmd/refer/glue3.c Work on file usr/src/cmd/refer/inv2.c Work on file usr/src/cmd/refer/refer3.c Work on file usr/src/cmd/refer/inv6.c Work on file usr/src/cmd/refer/refer2.c Work on file usr/src/cmd/refer/refer8.c Work on file usr/src/cmd/refer/refer4.c Work on file usr/src/cmd/refer/mkey2.c Work on file usr/src/cmd/refer/inv3.c Work on file usr/src/cmd/refer/mkey3.c Work on file usr/src/cmd/refer/kaiser.c Work on file usr/src/cmd/refer/refer0.c Work on file usr/src/cmd/refer/refer5.c Work on file usr/src/cmd/refer/refer1.c Work on file usr/src/cmd/refer/inv5.c Work on file usr/src/cmd/refer/thash.c Work on file usr/src/cmd/refer/sample 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/what4.c Work on file usr/src/cmd/refer/shell.c Work on file usr/src/cmd/refer/what1.c Work on file usr/src/cmd/refer/test Work on file usr/src/cmd/refer/types.c Work on file usr/src/cmd/sed/sed0.c Work on file usr/src/cmd/sh/expand.c Work on file usr/src/cmd/sh/fault.c Work on file usr/src/cmd/sh/args.c Work on file usr/src/cmd/sh/error.c Work on file usr/src/cmd/sh/dup.h Work on file usr/src/cmd/sh/ctype.c Work on file usr/src/cmd/sh/blok.c Work on file usr/src/cmd/sh/cmd.c Work on file usr/src/cmd/sh/builtin.c Work on file usr/src/cmd/sh/brkincr.h Work on file usr/src/cmd/sh/ctype.h Work on file usr/src/cmd/sh/mac.h Work on file usr/src/cmd/sh/name.c Work on file usr/src/cmd/sh/setbrk.c Work on file usr/src/cmd/sh/stak.c Work on file usr/src/cmd/sh/string.c 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/sym.h Work on file usr/src/cmd/sh/macro.c Work on file usr/src/cmd/sh/name.h Work on file usr/src/cmd/sh/stak.h Work on file usr/src/cmd/spell/american Work on file usr/src/cmd/spell/spell.sh Work on file usr/src/cmd/spell/spell.h Work on file usr/src/cmd/spell/spell.c Work on file usr/src/cmd/spell/british Work on file usr/src/cmd/spell/stop 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/1.main.c Work on file usr/src/cmd/struct/1.defs.h Work on file usr/src/cmd/struct/0.list.c Work on file usr/src/cmd/struct/1.form.c Work on file usr/src/cmd/struct/1.finish.c Work on file usr/src/cmd/struct/0.parts.c Work on file usr/src/cmd/struct/1.hash.c Work on file usr/src/cmd/struct/0.args.c Work on file usr/src/cmd/struct/1.node.c Work on file usr/src/cmd/struct/0.extr.c Work on file usr/src/cmd/struct/1.line.c Work on file usr/src/cmd/struct/1.init.c Work on file usr/src/cmd/struct/0.def.c Work on file usr/src/cmd/struct/1.fort.c Work on file usr/src/cmd/struct/1.incl.h Work on file usr/src/cmd/struct/0.alloc.c Work on file usr/src/cmd/struct/0.string.c Work on file usr/src/cmd/struct/0.graph.c Work on file usr/src/cmd/struct/3.loop.c Work on file usr/src/cmd/struct/1.recog.c Work on file usr/src/cmd/struct/3.test.c Work on file usr/src/cmd/struct/3.flow.c Work on file usr/src/cmd/struct/1.tables.c Work on file usr/src/cmd/struct/2.main.c Work on file usr/src/cmd/struct/2.inarc.c Work on file usr/src/cmd/struct/3.then.c Work on file usr/src/cmd/struct/3.def.h Work on file usr/src/cmd/struct/3.branch.c Work on file usr/src/cmd/struct/2.head.c Work on file usr/src/cmd/struct/2.test.c Work on file usr/src/cmd/struct/2.tree.c Work on file usr/src/cmd/struct/2.def.h Work on file usr/src/cmd/struct/3.reach.c Work on file usr/src/cmd/struct/2.dom.c Work on file usr/src/cmd/struct/3.main.c Work on file usr/src/cmd/struct/2.dfs.c Work on file usr/src/cmd/struct/4.out.c Work on file usr/src/cmd/struct/4.def.h Work on file usr/src/cmd/struct/lextab.l Work on file usr/src/cmd/struct/bdef.c Work on file usr/src/cmd/struct/struct Work on file usr/src/cmd/struct/4.main.c Work on file usr/src/cmd/struct/4.form.c Work on file usr/src/cmd/struct/b.h Work on file usr/src/cmd/struct/Makefile Work on file usr/src/cmd/struct/tree.c Work on file usr/src/cmd/struct/beauty.y 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.brace.c Work on file usr/src/cmd/tbl/t2.c Work on file usr/src/cmd/tbl/t8.c Work on file usr/src/cmd/tbl/t9.c Work on file usr/src/cmd/tbl/t0.c Work on file usr/src/cmd/tbl/t5.c Work on file usr/src/cmd/tbl/t4.c Work on file usr/src/cmd/tbl/t3.c Work on file usr/src/cmd/tbl/t6.c Work on file usr/src/cmd/tbl/t..c Work on file usr/src/cmd/tbl/t7.c Work on file usr/src/cmd/tbl/tm.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/tf.c Work on file usr/src/cmd/tbl/tg.c Work on file usr/src/cmd/tbl/tt.c Work on file usr/src/cmd/tbl/ts.c Work on file usr/src/cmd/tbl/tv.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/troff/term/tab300X.c Work on file usr/src/cmd/troff/term/tab450-12.c Work on file usr/src/cmd/troff/term/tab37.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/tab450.c Work on file usr/src/cmd/troff/term/tab300S.c Work on file usr/src/cmd/troff/term/tabtn300.c Work on file usr/src/cmd/troff/term/tab300.c Work on file usr/src/cmd/troff/term/tab450X.c Work on file usr/src/cmd/uudiff/locpart.c Work on file usr/src/cmd/uudiff/run1.c Work on file usr/src/cmd/uudiff/remdiff Work on file usr/src/cmd/uudiff/lenrem.c Work on file usr/src/cmd/uudiff/printable.c Work on file usr/src/cmd/uudiff/trim.c Work on file usr/src/cmd/xsend/xget.c Work on file usr/src/cmd/xsend/lib.c Work on file usr/src/cmd/xsend/enroll.c Work on file usr/src/cmd/xsend/xsend.c Work on file usr/src/cmd/yacc/y3.c Work on file usr/src/cmd/yacc/dextern Work on file usr/src/cmd/yacc/y1.c Work on file usr/src/cmd/yacc/yaccpar Work on file usr/src/cmd/yacc/y4.c Work on file usr/src/cmd/yacc/yaccdiffs Work on file usr/src/cmd/yacc/y2.c Work on file usr/src/cmd/yacc/yaccnews Synthesized-from: CSRG//cd1/4.0 --- 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/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/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/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/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/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/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/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/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 */ + + }