BSD 4_1c_2 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Tue, 8 Jun 1982 14:04:50 +0000 (06:04 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Tue, 8 Jun 1982 14:04:50 +0000 (06:04 -0800)
Work on file usr/src/usr.bin/lex/header.c
Work on file usr/src/usr.bin/lex/lmain.c
Work on file usr/src/usr.bin/lex/ldefs.c
Work on file usr/src/usr.bin/lex/ncform
Work on file usr/src/usr.bin/lex/once.c
Work on file usr/src/usr.bin/lex/sub2.c
Work on file usr/src/usr.bin/lex/sub1.c
Work on file usr/src/usr.bin/lex/parser.y
Work on file usr/src/usr.bin/neqn/diacrit.c
Work on file usr/src/usr.bin/neqn/Makefile
Work on file usr/src/usr.bin/neqn/e.h
Work on file usr/src/usr.bin/neqn/e.y
Work on file usr/src/usr.bin/neqn/eqnbox.c
Work on file usr/src/usr.bin/neqn/font.c
Work on file usr/src/usr.bin/neqn/fromto.c
Work on file usr/src/usr.bin/neqn/funny.c
Work on file usr/src/usr.bin/neqn/glob.c
Work on file usr/src/usr.bin/neqn/io.c
Work on file usr/src/usr.bin/neqn/lex.c
Work on file usr/src/usr.bin/neqn/integral.c
Work on file usr/src/usr.bin/neqn/mark.c
Work on file usr/src/usr.bin/neqn/lookup.c
Work on file usr/src/usr.bin/neqn/matrix.c
Work on file usr/src/usr.bin/neqn/pile.c
Work on file usr/src/usr.bin/neqn/over.c
Work on file usr/src/usr.bin/neqn/move.c
Work on file usr/src/usr.bin/neqn/paren.c
Work on file usr/src/usr.bin/neqn/shift.c
Work on file usr/src/usr.bin/neqn/size.c
Work on file usr/src/usr.bin/neqn/sqrt.c
Work on file usr/src/usr.bin/neqn/text.c

Synthesized-from: CSRG/cd1/4.1c.2

31 files changed:
usr/src/usr.bin/lex/header.c [new file with mode: 0644]
usr/src/usr.bin/lex/ldefs.c [new file with mode: 0644]
usr/src/usr.bin/lex/lmain.c [new file with mode: 0644]
usr/src/usr.bin/lex/ncform [new file with mode: 0644]
usr/src/usr.bin/lex/once.c [new file with mode: 0644]
usr/src/usr.bin/lex/parser.y [new file with mode: 0644]
usr/src/usr.bin/lex/sub1.c [new file with mode: 0644]
usr/src/usr.bin/lex/sub2.c [new file with mode: 0644]
usr/src/usr.bin/neqn/Makefile [new file with mode: 0644]
usr/src/usr.bin/neqn/diacrit.c [new file with mode: 0644]
usr/src/usr.bin/neqn/e.h [new file with mode: 0644]
usr/src/usr.bin/neqn/e.y [new file with mode: 0644]
usr/src/usr.bin/neqn/eqnbox.c [new file with mode: 0644]
usr/src/usr.bin/neqn/font.c [new file with mode: 0644]
usr/src/usr.bin/neqn/fromto.c [new file with mode: 0644]
usr/src/usr.bin/neqn/funny.c [new file with mode: 0644]
usr/src/usr.bin/neqn/glob.c [new file with mode: 0644]
usr/src/usr.bin/neqn/integral.c [new file with mode: 0644]
usr/src/usr.bin/neqn/io.c [new file with mode: 0644]
usr/src/usr.bin/neqn/lex.c [new file with mode: 0644]
usr/src/usr.bin/neqn/lookup.c [new file with mode: 0644]
usr/src/usr.bin/neqn/mark.c [new file with mode: 0644]
usr/src/usr.bin/neqn/matrix.c [new file with mode: 0644]
usr/src/usr.bin/neqn/move.c [new file with mode: 0644]
usr/src/usr.bin/neqn/over.c [new file with mode: 0644]
usr/src/usr.bin/neqn/paren.c [new file with mode: 0644]
usr/src/usr.bin/neqn/pile.c [new file with mode: 0644]
usr/src/usr.bin/neqn/shift.c [new file with mode: 0644]
usr/src/usr.bin/neqn/size.c [new file with mode: 0644]
usr/src/usr.bin/neqn/sqrt.c [new file with mode: 0644]
usr/src/usr.bin/neqn/text.c [new file with mode: 0644]

diff --git a/usr/src/usr.bin/lex/header.c b/usr/src/usr.bin/lex/header.c
new file mode 100644 (file)
index 0000000..1e9561c
--- /dev/null
@@ -0,0 +1,109 @@
+# include "ldefs.c"
+phead1(){
+       ratfor ? rhd1() : chd1();
+       }
+
+chd1(){
+       fprintf(fout,"# include \"stdio.h\"\n");
+       if (ZCH>NCH)
+       fprintf(fout, "# define U(x) ((x)&0377)\n");
+       else
+       fprintf(fout, "# define U(x) x\n");
+       fprintf(fout, "# define NLSTATE yyprevious=YYNEWLINE\n");
+       fprintf(fout,"# define BEGIN yybgin = yysvec + 1 +\n");
+       fprintf(fout,"# define INITIAL 0\n");
+       fprintf(fout,"# define YYLERR yysvec\n");
+       fprintf(fout,"# define YYSTATE (yyestate-yysvec-1)\n");
+       if(optim)
+               fprintf(fout,"# define YYOPTIM 1\n");
+# ifdef DEBUG
+       fprintf(fout,"# define LEXDEBUG 1\n");
+# endif
+       fprintf(fout,"# define YYLMAX 200\n");
+       fprintf(fout,"# define output(c) putc(c,yyout)\n");
+       fprintf(fout, "%s%d%s\n",
+  "# define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==",
+       ctable['\n'],
+ "?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)");
+       fprintf(fout,
+"# define unput(c) {yytchar= (c);if(yytchar=='\\n')yylineno--;*yysptr++=yytchar;}\n");
+       fprintf(fout,"# define yymore() (yymorfg=1)\n");
+       fprintf(fout,"# define ECHO fprintf(yyout, \"%%s\",yytext)\n");
+       fprintf(fout,"# define REJECT { nstr = yyreject(); goto yyfussy;}\n");
+       fprintf(fout,"int yyleng; extern char yytext[];\n");
+       fprintf(fout,"int yymorfg;\n");
+       fprintf(fout,"extern char *yysptr, yysbuf[];\n");
+       fprintf(fout,"int yytchar;\n");
+       fprintf(fout,"FILE *yyin ={stdin}, *yyout ={stdout};\n");
+       fprintf(fout,"extern int yylineno;\n");
+       fprintf(fout,"struct yysvf { \n");
+       fprintf(fout,"\tstruct yywork *yystoff;\n");
+       fprintf(fout,"\tstruct yysvf *yyother;\n");
+       fprintf(fout,"\tint *yystops;};\n");
+       fprintf(fout,"struct yysvf *yyestate;\n");
+       fprintf(fout,"extern struct yysvf yysvec[], *yybgin;\n");
+       }
+
+rhd1(){
+       fprintf(fout,"integer function yylex(dummy)\n");
+       fprintf(fout,"define YYLMAX 200\n");
+       fprintf(fout,"define ECHO call yyecho(yytext,yyleng)\n");
+       fprintf(fout,"define REJECT nstr = yyrjct(yytext,yyleng);goto 30998\n");
+       fprintf(fout,"integer nstr,yylook,yywrap\n");
+       fprintf(fout,"integer yyleng, yytext(YYLMAX)\n");
+       fprintf(fout,"common /yyxel/ yyleng, yytext\n");
+       fprintf(fout,"common /yyldat/ yyfnd, yymorf, yyprev, yybgin, yylsp, yylsta\n");
+       fprintf(fout,"integer yyfnd, yymorf, yyprev, yybgin, yylsp, yylsta(YYLMAX)\n");
+       fprintf(fout,"for(;;){\n");
+       fprintf(fout,"\t30999 nstr = yylook(dummy)\n");
+       fprintf(fout,"\tgoto 30998\n");
+       fprintf(fout,"\t30000 k = yywrap(dummy)\n");
+       fprintf(fout,"\tif(k .ne. 0){\n");
+       fprintf(fout,"\tyylex=0; return; }\n");
+       fprintf(fout,"\t\telse goto 30998\n");
+       }
+
+phead2(){
+       if(!ratfor)chd2();
+       }
+
+chd2(){
+       fprintf(fout,"while((nstr = yylook()) >= 0)\n");
+       fprintf(fout,"yyfussy: switch(nstr){\n");
+       fprintf(fout,"case 0:\n");
+       fprintf(fout,"if(yywrap()) return(0); break;\n");
+       }
+
+ptail(){
+       if(!pflag)
+               ratfor ? rtail() : ctail();
+       pflag = 1;
+       }
+
+ctail(){
+       fprintf(fout,"case -1:\nbreak;\n");             /* for reject */
+       fprintf(fout,"default:\n");
+       fprintf(fout,"fprintf(yyout,\"bad switch yylook %%d\",nstr);\n");
+       fprintf(fout,"} return(0); }\n");
+       fprintf(fout,"/* end of yylex */\n");
+       }
+
+rtail(){
+       register int i;
+       fprintf(fout,"\n30998 if(nstr .lt. 0 .or. nstr .gt. %d)goto 30999\n",casecount);
+       fprintf(fout,"nstr = nstr + 1\n");
+       fprintf(fout,"goto(\n");
+       for(i=0; i<casecount; i++)
+               fprintf(fout,"%d,\n",30000+i);
+       fprintf(fout,"30999),nstr\n");
+       fprintf(fout,"30997 continue\n");
+       fprintf(fout,"}\nend\n");
+       }
+statistics(){
+       fprintf(errorf,"%d/%d nodes(%%e), %d/%d positions(%%p), %d/%d (%%n), %ld transitions\n",
+               tptr, treesize, nxtpos-positions, maxpos, stnum+1, nstates, rcount);
+       fprintf(errorf, ", %d/%d packed char classes(%%k)", pcptr-pchar, pchlen);
+       if(optim)fprintf(errorf,", %d/%d packed transitions(%%a)",nptr, ntrans);
+       fprintf(errorf, ", %d/%d output slots(%%o)", yytop, outsize);
+       putc('\n',errorf);
+       }
diff --git a/usr/src/usr.bin/lex/ldefs.c b/usr/src/usr.bin/lex/ldefs.c
new file mode 100644 (file)
index 0000000..f874c87
--- /dev/null
@@ -0,0 +1,162 @@
+# include <stdio.h>
+# define PP 1
+# ifdef unix
+
+# define CWIDTH 7
+# define CMASK 0177
+# define ASCII 1
+# endif
+
+# ifdef gcos
+# define CWIDTH 9
+# define CMASK 0777
+# define ASCII 1
+# endif
+
+# ifdef ibm
+# define CWIDTH 8
+# define CMASK 0377
+# define EBCDIC 1
+# endif
+
+# ifdef ASCII
+# define NCH 128
+# endif
+
+# ifdef EBCDIC
+# define NCH 256
+# endif
+
+
+# define TOKENSIZE 1000
+# define DEFSIZE 40
+# define DEFCHAR 1000
+# define STARTCHAR 100
+# define STARTSIZE 256
+# define CCLSIZE 1000
+# ifdef SMALL
+# define TREESIZE 600
+# define NTRANS 1500
+# define NSTATES 300
+# define MAXPOS 1500
+# define NOUTPUT 1500
+# endif
+
+# ifndef SMALL
+# define TREESIZE 1000
+# define NSTATES 500
+# define MAXPOS 2500
+# define NTRANS 2000
+# define NOUTPUT 3000
+# endif
+# define NACTIONS 100
+# define ALITTLEEXTRA 30
+
+# define RCCL NCH+90
+# define RNCCL NCH+91
+# define RSTR NCH+92
+# define RSCON NCH+93
+# define RNEWE NCH+94
+# define FINAL NCH+95
+# define RNULLS NCH+96
+# define RCAT NCH+97
+# define STAR NCH+98
+# define PLUS NCH+99
+# define QUEST NCH+100
+# define DIV NCH+101
+# define BAR NCH+102
+# define CARAT NCH+103
+# define S1FINAL NCH+104
+# define S2FINAL NCH+105
+
+# define DEFSECTION 1
+# define RULESECTION 2
+# define ENDSECTION 5
+# define TRUE 1
+# define FALSE 0
+
+# define PC 1
+# define PS 1
+
+# ifdef DEBUG
+# define LINESIZE 110
+extern int yydebug;
+extern int debug;              /* 1 = on */
+extern int charc;
+# endif
+
+# ifndef DEBUG
+# define freturn(s) s
+# endif
+
+extern int sargc;
+extern char **sargv;
+extern char buf[520];
+extern int ratfor;             /* 1 = ratfor, 0 = C */
+extern int yyline;             /* line number of file */
+extern int sect;
+extern int eof;
+extern int lgatflg;
+extern int divflg;
+extern int funcflag;
+extern int pflag;
+extern int casecount;
+extern int chset;      /* 1 = char set modified */
+extern FILE *fin, *fout, *fother, *errorf;
+extern int fptr;
+extern char *ratname, *cname;
+extern int prev;       /* previous input character */
+extern int pres;       /* present input character */
+extern int peek;       /* next input character */
+extern int *name;
+extern int *left;
+extern int *right;
+extern int *parent;
+extern char *nullstr;
+extern int tptr;
+extern char pushc[TOKENSIZE];
+extern char *pushptr;
+extern char slist[STARTSIZE];
+extern char *slptr;
+extern char **def, **subs, *dchar;
+extern char **sname, *schar;
+extern char *ccl;
+extern char *ccptr;
+extern char *dp, *sp;
+extern int dptr, sptr;
+extern char *bptr;             /* store input position */
+extern char *tmpstat;
+extern int count;
+extern int **foll;
+extern int *nxtpos;
+extern int *positions;
+extern int *gotof;
+extern int *nexts;
+extern char *nchar;
+extern int **state;
+extern int *sfall;             /* fallback state num */
+extern char *cpackflg;         /* true if state has been character packed */
+extern int *atable, aptr;
+extern int nptr;
+extern char symbol[NCH];
+extern char cindex[NCH];
+extern int xstate;
+extern int stnum;
+extern int ctable[];
+extern int ZCH;
+extern int ccount;
+extern char match[NCH];
+extern char extra[NACTIONS];
+extern char *pcptr, *pchar;
+extern int pchlen;
+extern int nstates, maxpos;
+extern int yytop;
+extern int report;
+extern int ntrans, treesize, outsize;
+extern long rcount;
+extern int optim;
+extern int *verify, *advance, *stoff;
+extern int scon;
+extern char *psave;
+extern char *calloc(), *myalloc();
+extern int buserr(), segviol();
diff --git a/usr/src/usr.bin/lex/lmain.c b/usr/src/usr.bin/lex/lmain.c
new file mode 100644 (file)
index 0000000..3ef43af
--- /dev/null
@@ -0,0 +1,227 @@
+# include "ldefs.c"
+# include "once.c"
+
+       /* lex [-[drcyvntf]] [file] ... [file] */
+
+       /* Copyright 1976, Bell Telephone Laboratories, Inc.,
+           written by Eric Schmidt, August 27, 1976   */
+
+main(argc,argv)
+  int argc;
+  char **argv; {
+       register int i;
+# ifdef DEBUG
+#include <signal.h>
+       signal(SIGBUS,buserr);
+       signal(SIGSEGV,segviol);
+# endif
+       while (argc > 1 && argv[1][0] == '-' ){
+               i = 0;
+               while(argv[1][++i]){
+                       switch (argv[1][i]){
+# ifdef DEBUG
+                               case 'd': debug++; break;
+                               case 'y': yydebug = TRUE; break;
+# endif
+                               case 'r': case 'R':
+                                       ratfor=TRUE; break;
+                               case 'c': case 'C':
+                                       ratfor=FALSE; break;
+                               case 't': case 'T':
+                                       fout = stdout;
+                                       errorf = stderr;
+                                       break;
+                               case 'v': case 'V':
+                                       report = 1;
+                                       break;
+                               case 'f': case 'F':
+                                       optim = FALSE;
+                                       break;
+                               case 'n': case 'N':
+                                       report = 0;
+                                       break;
+                               default:
+                                       warning("Unknown option %c",argv[1][i]);
+                               }
+                       }
+               argc--;
+               argv++;
+               }
+       sargc = argc;
+       sargv = argv;
+       if (argc > 1){
+               fin = fopen(argv[++fptr], "r");         /* open argv[1] */
+               sargc--;
+               sargv++;
+               }
+       else fin = stdin;
+       if(fin == NULL)
+               error ("Can't read input file %s",argc>1?argv[1]:"standard input");
+       gch();
+               /* may be gotten: def, subs, sname, schar, ccl, dchar */
+       get1core();
+               /* may be gotten: name, left, right, nullstr, parent */
+       scopy("INITIAL",sp);
+       sname[0] = sp;
+       sp += slength("INITIAL") + 1;
+       sname[1] = 0;
+       if(yyparse(0)) exit(1); /* error return code */
+               /* may be disposed of: def, subs, dchar */
+       free1core();
+               /* may be gotten: tmpstat, foll, positions, gotof, nexts, nchar, state, atable, sfall, cpackflg */
+       get2core();
+       ptail();
+       mkmatch();
+# ifdef DEBUG
+       if(debug) pccl();
+# endif
+       sect  = ENDSECTION;
+       if(tptr>0)cfoll(tptr-1);
+# ifdef DEBUG
+       if(debug)pfoll();
+# endif
+       cgoto();
+# ifdef DEBUG
+       if(debug){
+               printf("Print %d states:\n",stnum+1);
+               for(i=0;i<=stnum;i++)stprt(i);
+               }
+# endif
+               /* may be disposed of: positions, tmpstat, foll, state, name, left, right, parent, ccl, schar, sname */
+               /* may be gotten: verify, advance, stoff */
+       free2core();
+       get3core();
+       layout();
+               /* may be disposed of: verify, advance, stoff, nexts, nchar,
+                       gotof, atable, ccpackflg, sfall */
+# ifdef DEBUG
+       free3core();
+# endif
+       if (ZCH>NCH) cname="/usr/lib/lex/ebcform";
+       fother = fopen(ratfor?ratname:cname,"r");
+       if(fother == NULL)
+               error("Lex driver missing, file %s",ratfor?ratname:cname);
+       while ( (i=getc(fother)) != EOF)
+               putc(i,fout);
+
+       fclose(fother);
+       fclose(fout);
+       if(
+# ifdef DEBUG
+               debug   ||
+# endif
+                       report == 1)statistics();
+       fclose(stdout);
+       fclose(stderr);
+       exit(0);        /* success return code */
+       }
+get1core(){
+       register int i, val;
+       register char *p;
+ccptr =        ccl = myalloc(CCLSIZE,sizeof(*ccl));
+pcptr = pchar = myalloc(pchlen, sizeof(*pchar));
+       def = myalloc(DEFSIZE,sizeof(*def));
+       subs = myalloc(DEFSIZE,sizeof(*subs));
+dp =   dchar = myalloc(DEFCHAR,sizeof(*dchar));
+       sname = myalloc(STARTSIZE,sizeof(*sname));
+sp =   schar = myalloc(STARTCHAR,sizeof(*schar));
+       if(ccl == 0 || def == 0 || subs == 0 || dchar == 0 || sname == 0 || schar == 0)
+               error("Too little core to begin");
+       }
+free1core(){
+       cfree(def,DEFSIZE,sizeof(*def));
+       cfree(subs,DEFSIZE,sizeof(*subs));
+       cfree(dchar,DEFCHAR,sizeof(*dchar));
+       }
+get2core(){
+       register int i, val;
+       register char *p;
+       gotof = myalloc(nstates,sizeof(*gotof));
+       nexts = myalloc(ntrans,sizeof(*nexts));
+       nchar = myalloc(ntrans,sizeof(*nchar));
+       state = myalloc(nstates,sizeof(*state));
+       atable = myalloc(nstates,sizeof(*atable));
+       sfall = myalloc(nstates,sizeof(*sfall));
+       cpackflg = myalloc(nstates,sizeof(*cpackflg));
+       tmpstat = myalloc(tptr+1,sizeof(*tmpstat));
+       foll = myalloc(tptr+1,sizeof(*foll));
+nxtpos = positions = myalloc(maxpos,sizeof(*positions));
+       if(tmpstat == 0 || foll == 0 || positions == 0 ||
+               gotof == 0 || nexts == 0 || nchar == 0 || state == 0 || atable == 0 || sfall == 0 || cpackflg == 0 )
+               error("Too little core for state generation");
+       for(i=0;i<=tptr;i++)foll[i] = 0;
+       }
+free2core(){
+       cfree(positions,maxpos,sizeof(*positions));
+       cfree(tmpstat,tptr+1,sizeof(*tmpstat));
+       cfree(foll,tptr+1,sizeof(*foll));
+       cfree(name,treesize,sizeof(*name));
+       cfree(left,treesize,sizeof(*left));
+       cfree(right,treesize,sizeof(*right));
+       cfree(parent,treesize,sizeof(*parent));
+       cfree(nullstr,treesize,sizeof(*nullstr));
+       cfree(state,nstates,sizeof(*state));
+       cfree(sname,STARTSIZE,sizeof(*sname));
+       cfree(schar,STARTCHAR,sizeof(*schar));
+       cfree(ccl,CCLSIZE,sizeof(*ccl));
+       }
+get3core(){
+       register int i, val;
+       register char *p;
+       verify = myalloc(outsize,sizeof(*verify));
+       advance = myalloc(outsize,sizeof(*advance));
+       stoff = myalloc(stnum+2,sizeof(*stoff));
+       if(verify == 0 || advance == 0 || stoff == 0)
+               error("Too little core for final packing");
+       }
+# ifdef DEBUG
+free3core(){
+       cfree(advance,outsize,sizeof(*advance));
+       cfree(verify,outsize,sizeof(*verify));
+       cfree(stoff,stnum+1,sizeof(*stoff));
+       cfree(gotof,nstates,sizeof(*gotof));
+       cfree(nexts,ntrans,sizeof(*nexts));
+       cfree(nchar,ntrans,sizeof(*nchar));
+       cfree(atable,nstates,sizeof(*atable));
+       cfree(sfall,nstates,sizeof(*sfall));
+       cfree(cpackflg,nstates,sizeof(*cpackflg));
+       }
+# endif
+char *myalloc(a,b)
+  int a,b; {
+       register int i;
+       i = calloc(a, b);
+       if(i==0)
+               warning("OOPS - calloc returns a 0");
+       else if(i == -1){
+# ifdef DEBUG
+               warning("calloc returns a -1");
+# endif
+               return(0);
+               }
+       return(i);
+       }
+# ifdef DEBUG
+buserr(){
+       fflush(errorf);
+       fflush(fout);
+       fflush(stdout);
+       fprintf(errorf,"Bus error\n");
+       if(report == 1)statistics();
+       fflush(errorf);
+       }
+segviol(){
+       fflush(errorf);
+       fflush(fout);
+       fflush(stdout);
+       fprintf(errorf,"Segmentation violation\n");
+       if(report == 1)statistics();
+       fflush(errorf);
+       }
+# endif
+
+yyerror(s)
+char *s;
+{
+       fprintf(stderr, "%s\n", s);
+}
diff --git a/usr/src/usr.bin/lex/ncform b/usr/src/usr.bin/lex/ncform
new file mode 100644 (file)
index 0000000..8ca51b4
--- /dev/null
@@ -0,0 +1,179 @@
+int yylineno =1;
+# define YYU(x) x
+# define NLSTATE yyprevious=YYNEWLINE
+char yytext[YYLMAX];
+struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp;
+char yysbuf[YYLMAX];
+char *yysptr = yysbuf;
+int *yyfnd;
+extern struct yysvf *yyestate;
+int yyprevious = YYNEWLINE;
+yylook(){
+       register struct yysvf *yystate, **lsp;
+       register struct yywork *yyt;
+       struct yysvf *yyz;
+       int yych;
+       struct yywork *yyr;
+# ifdef LEXDEBUG
+       int debug;
+# endif
+       char *yylastch;
+       /* start off machines */
+# ifdef LEXDEBUG
+       debug = 0;
+# endif
+       if (!yymorfg)
+               yylastch = yytext;
+       else {
+               yymorfg=0;
+               yylastch = yytext+yyleng;
+               }
+       for(;;){
+               lsp = yylstate;
+               yyestate = yystate = yybgin;
+               if (yyprevious==YYNEWLINE) yystate++;
+               for (;;){
+# ifdef LEXDEBUG
+                       if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1);
+# endif
+                       yyt = yystate->yystoff;
+                       if(yyt == yycrank){             /* may not be any transitions */
+                               yyz = yystate->yyother;
+                               if(yyz == 0)break;
+                               if(yyz->yystoff == yycrank)break;
+                               }
+                       *yylastch++ = yych = input();
+               tryagain:
+# ifdef LEXDEBUG
+                       if(debug){
+                               fprintf(yyout,"char ");
+                               allprint(yych);
+                               putchar('\n');
+                               }
+# endif
+                       yyr = yyt;
+                       if ( (int)yyt > (int)yycrank){
+                               yyt = yyr + yych;
+                               if (yyt <= yytop && yyt->verify+yysvec == yystate){
+                                       if(yyt->advance+yysvec == YYLERR)       /* error transitions */
+                                               {unput(*--yylastch);break;}
+                                       *lsp++ = yystate = yyt->advance+yysvec;
+                                       goto contin;
+                                       }
+                               }
+# ifdef YYOPTIM
+                       else if((int)yyt < (int)yycrank) {              /* r < yycrank */
+                               yyt = yyr = yycrank+(yycrank-yyt);
+# ifdef LEXDEBUG
+                               if(debug)fprintf(yyout,"compressed state\n");
+# endif
+                               yyt = yyt + yych;
+                               if(yyt <= yytop && yyt->verify+yysvec == yystate){
+                                       if(yyt->advance+yysvec == YYLERR)       /* error transitions */
+                                               {unput(*--yylastch);break;}
+                                       *lsp++ = yystate = yyt->advance+yysvec;
+                                       goto contin;
+                                       }
+                               yyt = yyr + YYU(yymatch[yych]);
+# ifdef LEXDEBUG
+                               if(debug){
+                                       fprintf(yyout,"try fall back character ");
+                                       allprint(YYU(yymatch[yych]));
+                                       putchar('\n');
+                                       }
+# endif
+                               if(yyt <= yytop && yyt->verify+yysvec == yystate){
+                                       if(yyt->advance+yysvec == YYLERR)       /* error transition */
+                                               {unput(*--yylastch);break;}
+                                       *lsp++ = yystate = yyt->advance+yysvec;
+                                       goto contin;
+                                       }
+                               }
+                       if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){
+# ifdef LEXDEBUG
+                               if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1);
+# endif
+                               goto tryagain;
+                               }
+# endif
+                       else
+                               {unput(*--yylastch);break;}
+               contin:
+# ifdef LEXDEBUG
+                       if(debug){
+                               fprintf(yyout,"state %d char ",yystate-yysvec-1);
+                               allprint(yych);
+                               putchar('\n');
+                               }
+# endif
+                       ;
+                       }
+# ifdef LEXDEBUG
+               if(debug){
+                       fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1);
+                       allprint(yych);
+                       putchar('\n');
+                       }
+# endif
+               while (lsp-- > yylstate){
+                       *yylastch-- = 0;
+                       if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){
+                               yyolsp = lsp;
+                               if(yyextra[*yyfnd]){            /* must backup */
+                                       while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){
+                                               lsp--;
+                                               unput(*yylastch--);
+                                               }
+                                       }
+                               yyprevious = YYU(*yylastch);
+                               yylsp = lsp;
+                               yyleng = yylastch-yytext+1;
+                               yytext[yyleng] = 0;
+# ifdef LEXDEBUG
+                               if(debug){
+                                       fprintf(yyout,"\nmatch ");
+                                       sprint(yytext);
+                                       fprintf(yyout," action %d\n",*yyfnd);
+                                       }
+# endif
+                               return(*yyfnd++);
+                               }
+                       unput(*yylastch);
+                       }
+               if (yytext[0] == 0  /* && feof(yyin) */)
+                       {
+                       yysptr=yysbuf;
+                       return(0);
+                       }
+               yyprevious = yytext[0] = input();
+               if (yyprevious>0)
+                       output(yyprevious);
+               yylastch=yytext;
+# ifdef LEXDEBUG
+               if(debug)putchar('\n');
+# endif
+               }
+       }
+yyback(p, m)
+       int *p;
+{
+if (p==0) return(0);
+while (*p)
+       {
+       if (*p++ == m)
+               return(1);
+       }
+return(0);
+}
+       /* the following are only used in the lex library */
+yyinput(){
+       return(input());
+       }
+yyoutput(c)
+  int c; {
+       output(c);
+       }
+yyunput(c)
+   int c; {
+       unput(c);
+       }
diff --git a/usr/src/usr.bin/lex/once.c b/usr/src/usr.bin/lex/once.c
new file mode 100644 (file)
index 0000000..f9b5249
--- /dev/null
@@ -0,0 +1,130 @@
+       /* because of external definitions, this code should occur only once */
+# ifdef ASCII
+int ctable[2*NCH] = {
+  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+100,101,102,103,104,105,106,107,108,109,
+110,111,112,113,114,115,116,117,118,119,
+120,121,122,123,124,125,126,127};
+# endif
+# ifdef EBCDIC
+int ctable[2*NCH] = {
+  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+100,101,102,103,104,105,106,107,108,109,
+110,111,112,113,114,115,116,117,118,119,
+120,121,122,123,124,125,126,127,128,129,
+130,131,132,133,134,135,136,137,138,139,
+140,141,142,143,144,145,146,147,148,149,
+150,151,152,153,154,155,156,157,158,159,
+160,161,162,163,164,165,166,167,168,169,
+170,171,172,173,174,175,176,177,178,179,
+180,181,182,183,184,185,186,187,188,189,
+190,191,192,193,194,195,196,197,198,199,
+200,201,202,203,204,205,206,207,208,209,
+210,211,212,213,214,215,216,217,218,219,
+220,221,222,223,224,225,226,227,228,229,
+230,231,232,233,234,235,236,237,238,239,
+240,241,242,243,244,245,246,247,248,249,
+250,251,252,253,254,255};
+# endif
+int ZCH = NCH;
+FILE *fout = NULL, *errorf = {stdout};
+int sect = DEFSECTION;
+int prev = '\n';       /* previous input character */
+int pres = '\n';       /* present input character */
+int peek = '\n';       /* next input character */
+char *pushptr = pushc;
+char *slptr = slist;
+
+# if (unix || ibm)
+char *cname = "/usr/lib/lex/ncform";
+char *ratname = "/usr/lib/lex/nrform";
+# endif
+
+# ifdef gcos
+char *cname = "pounce/lexcform";
+char *ratname = "pounce/lexrform";
+# endif
+int ccount = 1;
+int casecount = 1;
+int aptr = 1;
+int nstates = NSTATES, maxpos = MAXPOS;
+int treesize = TREESIZE, ntrans = NTRANS;
+int yytop;
+int outsize = NOUTPUT;
+int sptr = 1;
+int optim = TRUE;
+int report = 2;
+int debug;             /* 1 = on */
+int charc;
+int sargc;
+char **sargv;
+char buf[520];
+int ratfor;            /* 1 = ratfor, 0 = C */
+int yyline;            /* line number of file */
+int eof;
+int lgatflg;
+int divflg;
+int funcflag;
+int pflag;
+int chset;     /* 1 = char set modified */
+FILE *fin, *fother;
+int fptr;
+int *name;
+int *left;
+int *right;
+int *parent;
+char *nullstr;
+int tptr;
+char pushc[TOKENSIZE];
+char slist[STARTSIZE];
+char **def, **subs, *dchar;
+char **sname, *schar;
+char *ccl;
+char *ccptr;
+char *dp, *sp;
+int dptr;
+char *bptr;            /* store input position */
+char *tmpstat;
+int count;
+int **foll;
+int *nxtpos;
+int *positions;
+int *gotof;
+int *nexts;
+char *nchar;
+int **state;
+int *sfall;            /* fallback state num */
+char *cpackflg;                /* true if state has been character packed */
+int *atable;
+int nptr;
+char symbol[NCH];
+char cindex[NCH];
+int xstate;
+int stnum;
+char match[NCH];
+char extra[NACTIONS];
+char *pchar, *pcptr;
+int pchlen = TOKENSIZE;
+ long rcount;
+int *verify, *advance, *stoff;
+int scon;
+char *psave;
+int buserr(), segviol();
diff --git a/usr/src/usr.bin/lex/parser.y b/usr/src/usr.bin/lex/parser.y
new file mode 100644 (file)
index 0000000..81df2d0
--- /dev/null
@@ -0,0 +1,710 @@
+%token CHAR CCL NCCL STR DELIM SCON ITER NEWE NULLS
+%left SCON '/' NEWE
+%left '|'
+%left '$' '^'
+%left CHAR CCL NCCL '(' '.' STR NULLS
+%left ITER
+%left CAT
+%left '*' '+' '?'
+
+%{
+# include "ldefs.c"
+%}
+%%
+%{
+int i;
+int j,k;
+int g;
+char *p;
+%}
+acc    :       lexinput
+       ={      
+# ifdef DEBUG
+               if(debug) sect2dump();
+# endif
+       }
+       ;
+lexinput:      defns delim prods end
+       |       defns delim end
+       ={
+               if(!funcflag)phead2();
+               funcflag = TRUE;
+       }
+       | error
+       ={
+# ifdef DEBUG
+               if(debug) {
+                       sect1dump();
+                       sect2dump();
+                       }
+# endif
+               }
+       ;
+end:           delim | ;
+defns: defns STR STR
+       ={      scopy($2,dp);
+               def[dptr] = dp;
+               dp += slength($2) + 1;
+               scopy($3,dp);
+               subs[dptr++] = dp;
+               if(dptr >= DEFSIZE)
+                       error("Too many definitions");
+               dp += slength($3) + 1;
+               if(dp >= dchar+DEFCHAR)
+                       error("Definitions too long");
+               subs[dptr]=def[dptr]=0; /* for lookup - require ending null */
+       }
+       |
+       ;
+delim: DELIM
+       ={
+# ifdef DEBUG
+               if(sect == DEFSECTION && debug) sect1dump();
+# endif
+               sect++;
+               }
+       ;
+prods: prods pr
+       ={      $$ = mn2(RNEWE,$1,$2);
+               }
+       |       pr
+       ={      $$ = $1;}
+       ;
+pr:    r NEWE
+       ={
+               if(divflg == TRUE)
+                       i = mn1(S1FINAL,casecount);
+               else i = mn1(FINAL,casecount);
+               $$ = mn2(RCAT,$1,i);
+               divflg = FALSE;
+               casecount++;
+               }
+       | error NEWE
+       ={
+# ifdef DEBUG
+               if(debug) sect2dump();
+# endif
+               }
+r:     CHAR
+       ={      $$ = mn0($1); }
+       | STR
+       ={
+               p = $1;
+               i = mn0(*p++);
+               while(*p)
+                       i = mn2(RSTR,i,*p++);
+               $$ = i;
+               }
+       | '.'
+       ={      symbol['\n'] = 0;
+               if(psave == FALSE){
+                       p = ccptr;
+                       psave = ccptr;
+                       for(i=1;i<'\n';i++){
+                               symbol[i] = 1;
+                               *ccptr++ = i;
+                               }
+                       for(i='\n'+1;i<NCH;i++){
+                               symbol[i] = 1;
+                               *ccptr++ = i;
+                               }
+                       *ccptr++ = 0;
+                       if(ccptr > ccl+CCLSIZE)
+                               error("Too many large character classes");
+                       }
+               else
+                       p = psave;
+               $$ = mn1(RCCL,p);
+               cclinter(1);
+               }
+       | CCL
+       ={      $$ = mn1(RCCL,$1); }
+       | NCCL
+       ={      $$ = mn1(RNCCL,$1); }
+       | r '*'
+       ={      $$ = mn1(STAR,$1); }
+       | r '+'
+       ={      $$ = mn1(PLUS,$1); }
+       | r '?'
+       ={      $$ = mn1(QUEST,$1); }
+       | r '|' r
+       ={      $$ = mn2(BAR,$1,$3); }
+       | r r %prec CAT
+       ={      $$ = mn2(RCAT,$1,$2); }
+       | r '/' r
+       ={      if(!divflg){
+                       j = mn1(S2FINAL,-casecount);
+                       i = mn2(RCAT,$1,j);
+                       $$ = mn2(DIV,i,$3);
+                       }
+               else {
+                       $$ = mn2(RCAT,$1,$3);
+                       warning("Extra slash removed");
+                       }
+               divflg = TRUE;
+               }
+       | r ITER ',' ITER '}'
+       ={      if($2 > $4){
+                       i = $2;
+                       $2 = $4;
+                       $4 = i;
+                       }
+               if($4 <= 0)
+                       warning("Iteration range must be positive");
+               else {
+                       j = $1;
+                       for(k = 2; k<=$2;k++)
+                               j = mn2(RCAT,j,dupl($1));
+                       for(i = $2+1; i<=$4; i++){
+                               g = dupl($1);
+                               for(k=2;k<=i;k++)
+                                       g = mn2(RCAT,g,dupl($1));
+                               j = mn2(BAR,j,g);
+                               }
+                       $$ = j;
+                       }
+       }
+       | r ITER '}'
+       ={
+               if($2 < 0)warning("Can't have negative iteration");
+               else if($2 == 0) $$ = mn0(RNULLS);
+               else {
+                       j = $1;
+                       for(k=2;k<=$2;k++)
+                               j = mn2(RCAT,j,dupl($1));
+                       $$ = j;
+                       }
+               }
+       | r ITER ',' '}'
+       ={
+                               /* from n to infinity */
+               if($2 < 0)warning("Can't have negative iteration");
+               else if($2 == 0) $$ = mn1(STAR,$1);
+               else if($2 == 1)$$ = mn1(PLUS,$1);
+               else {          /* >= 2 iterations minimum */
+                       j = $1;
+                       for(k=2;k<$2;k++)
+                               j = mn2(RCAT,j,dupl($1));
+                       k = mn1(PLUS,dupl($1));
+                       $$ = mn2(RCAT,j,k);
+                       }
+               }
+       | SCON r
+       ={      $$ = mn2(RSCON,$2,$1); }
+       | '^' r
+       ={      $$ = mn1(CARAT,$2); }
+       | r '$'
+       ={      i = mn0('\n');
+               if(!divflg){
+                       j = mn1(S2FINAL,-casecount);
+                       k = mn2(RCAT,$1,j);
+                       $$ = mn2(DIV,k,i);
+                       }
+               else $$ = mn2(RCAT,$1,i);
+               divflg = TRUE;
+               }
+       | '(' r ')'
+       ={      $$ = $2; }
+       |       NULLS
+       ={      $$ = mn0(RNULLS); }
+       ;
+%%
+yylex(){
+       register char *p;
+       register int c, i;
+       char  *t, *xp;
+       int n, j, k, x;
+       static int sectbegin;
+       static char token[TOKENSIZE];
+       static int iter;
+
+# ifdef DEBUG
+       yylval = 0;
+# endif
+
+       if(sect == DEFSECTION) {                /* definitions section */
+               while(!eof) {
+                       if(prev == '\n'){               /* next char is at beginning of line */
+                               getl(p=buf);
+                               switch(*p){
+                               case '%':
+                                       switch(c= *(p+1)){
+                                       case '%':
+                                               lgate();
+                                               if(!ratfor)fprintf(fout,"# ");
+                                               fprintf(fout,"define YYNEWLINE %d\n",ctable['\n']);
+                                               if(!ratfor)fprintf(fout,"yylex(){\nint nstr; extern int yyprevious;\n");
+                                               sectbegin = TRUE;
+                                               i = treesize*(sizeof(*name)+sizeof(*left)+
+                                                       sizeof(*right)+sizeof(*nullstr)+sizeof(*parent))+ALITTLEEXTRA;
+                                               c = myalloc(i,1);
+                                               if(c == 0)
+                                                       error("Too little core for parse tree");
+                                               p = c;
+                                               cfree(p,i,1);
+                                               name = myalloc(treesize,sizeof(*name));
+                                               left = myalloc(treesize,sizeof(*left));
+                                               right = myalloc(treesize,sizeof(*right));
+                                               nullstr = myalloc(treesize,sizeof(*nullstr));
+                                               parent = myalloc(treesize,sizeof(*parent));
+                                               if(name == 0 || left == 0 || right == 0 || parent == 0 || nullstr == 0)
+                                                       error("Too little core for parse tree");
+                                               return(freturn(DELIM));
+                                       case 'p': case 'P':     /* has overridden number of positions */
+                                               while(*p && !digit(*p))p++;
+                                               maxpos = siconv(p);
+# ifdef DEBUG
+                                               if (debug) printf("positions (%%p) now %d\n",maxpos);
+# endif
+                                               if(report == 2)report = 1;
+                                               continue;
+                                       case 'n': case 'N':     /* has overridden number of states */
+                                               while(*p && !digit(*p))p++;
+                                               nstates = siconv(p);
+# ifdef DEBUG
+                                               if(debug)printf( " no. states (%%n) now %d\n",nstates);
+# endif
+                                               if(report == 2)report = 1;
+                                               continue;
+                                       case 'e': case 'E':             /* has overridden number of tree nodes */
+                                               while(*p && !digit(*p))p++;
+                                               treesize = siconv(p);
+# ifdef DEBUG
+                                               if (debug) printf("treesize (%%e) now %d\n",treesize);
+# endif
+                                               if(report == 2)report = 1;
+                                               continue;
+                                       case 'o': case 'O':
+                                               while (*p && !digit(*p))p++;
+                                               outsize = siconv(p);
+                                               if (report ==2) report=1;
+                                               continue;
+                                       case 'a': case 'A':             /* has overridden number of transitions */
+                                               while(*p && !digit(*p))p++;
+                                               if(report == 2)report = 1;
+                                               ntrans = siconv(p);
+# ifdef DEBUG
+                                               if (debug)printf("N. trans (%%a) now %d\n",ntrans);
+# endif
+                                               continue;
+                                       case 'k': case 'K': /* overriden packed char classes */
+                                               while (*p && !digit(*p))p++;
+                                               if (report==2) report=1;
+                                               cfree(pchar, pchlen, sizeof(*pchar));
+                                               pchlen = siconv(p);
+# ifdef DEBUG
+                                               if (debug) printf( "Size classes (%%k) now %d\n",pchlen);
+# endif
+                                               pchar=pcptr=myalloc(pchlen, sizeof(*pchar));
+                                               continue;
+                                       case 't': case 'T':     /* character set specifier */
+                                               ZCH = atoi(p+2);
+                                               if (ZCH < NCH) ZCH = NCH;
+                                               if (ZCH > 2*NCH) error("ch table needs redeclaration");
+                                               chset = TRUE;
+                                               for(i = 0; i<ZCH; i++)
+                                                       ctable[i] = 0;
+                                               while(getl(p) && scomp(p,"%T") != 0 && scomp(p,"%t") != 0){
+                                                       if((n = siconv(p)) <= 0 || n > ZCH){
+                                                               warning("Character value %d out of range",n);
+                                                               continue;
+                                                               }
+                                                       while(!space(*p) && *p) p++;
+                                                       while(space(*p)) p++;
+                                                       t = p;
+                                                       while(*t){
+                                                               c = ctrans(&t);
+                                                               if(ctable[c]){
+                                                                       if (printable(c))
+                                                                               warning("Character '%c' used twice",c);
+                                                                       else
+                                                                               warning("Character %o used twice",c);
+                                                                       }
+                                                               else ctable[c] = n;
+                                                               t++;
+                                                               }
+                                                       p = buf;
+                                                       }
+                                               {
+                                               char chused[2*NCH]; int kr;
+                                               for(i=0; i<ZCH; i++)
+                                                       chused[i]=0;
+                                               for(i=0; i<NCH; i++)
+                                                       chused[ctable[i]]=1;
+                                               for(kr=i=1; i<NCH; i++)
+                                                       if (ctable[i]==0)
+                                                               {
+                                                               while (chused[kr] == 0)
+                                                                       kr++;
+                                                               ctable[i]=kr;
+                                                               chused[kr]=1;
+                                                               }
+                                               }
+                                               lgate();
+                                               continue;
+                                       case 'r': case 'R':
+                                               c = 'r';
+                                       case 'c': case 'C':
+                                               if(lgatflg)
+                                                       error("Too late for language specifier");
+                                               ratfor = (c == 'r');
+                                               continue;
+                                       case '{':
+                                               lgate();
+                                               while(getl(p) && scomp(p,"%}") != 0)
+                                                       fprintf(fout, "%s\n",p);
+                                               if(p[0] == '%') continue;
+                                               error("Premature eof");
+                                       case 's': case 'S':             /* start conditions */
+                                               lgate();
+                                               while(*p && index(*p," \t,") < 0) p++;
+                                               n = TRUE;
+                                               while(n){
+                                                       while(*p && index(*p," \t,") >= 0) p++;
+                                                       t = p;
+                                                       while(*p && index(*p," \t,") < 0)p++;
+                                                       if(!*p) n = FALSE;
+                                                       *p++ = 0;
+                                                       if (*t == 0) continue;
+                                                       i = sptr*2;
+                                                       if(!ratfor)fprintf(fout,"# ");
+                                                       fprintf(fout,"define %s %d\n",t,i);
+                                                       scopy(t,sp);
+                                                       sname[sptr++] = sp;
+                                                       sname[sptr] = 0;        /* required by lookup */
+                                                       if(sptr >= STARTSIZE)
+                                                               error("Too many start conditions");
+                                                       sp += slength(sp) + 1;
+                                                       if(sp >= schar+STARTCHAR)
+                                                               error("Start conditions too long");
+                                                       }
+                                               continue;
+                                       default:
+                                               warning("Invalid request %s",p);
+                                               continue;
+                                               }       /* end of switch after seeing '%' */
+                               case ' ': case '\t':            /* must be code */
+                                       lgate();
+                                       fprintf(fout, "%s\n",p);
+                                       continue;
+                               default:                /* definition */
+                                       while(*p && !space(*p)) p++;
+                                       if(*p == 0)
+                                               continue;
+                                       prev = *p;
+                                       *p = 0;
+                                       bptr = p+1;
+                                       yylval = buf;
+                                       if(digit(buf[0]))
+                                               warning("Substitution strings may not begin with digits");
+                                       return(freturn(STR));
+                                       }
+                               }
+                       /* still sect 1, but prev != '\n' */
+                       else {
+                               p = bptr;
+                               while(*p && space(*p)) p++;
+                               if(*p == 0)
+                                       warning("No translation given - null string assumed");
+                               scopy(p,token);
+                               yylval = token;
+                               prev = '\n';
+                               return(freturn(STR));
+                               }
+                       }
+               /* end of section one processing */
+               }
+       else if(sect == RULESECTION){           /* rules and actions */
+               while(!eof){
+                       switch(c=gch()){
+                       case '\0':
+                               return(freturn(0));
+                       case '\n':
+                               if(prev == '\n') continue;
+                               x = NEWE;
+                               break;
+                       case ' ':
+                       case '\t':
+                               if(sectbegin == TRUE){
+                                       cpyact();
+                                       while((c=gch()) && c != '\n');
+                                       continue;
+                                       }
+                               if(!funcflag)phead2();
+                               funcflag = TRUE;
+                               if(ratfor)fprintf(fout,"%d\n",30000+casecount);
+                               else fprintf(fout,"case %d:\n",casecount);
+                               if(cpyact()){
+                                       if(ratfor)fprintf(fout,"goto 30997\n");
+                                       else fprintf(fout,"break;\n");
+                                       }
+                               while((c=gch()) && c != '\n');
+                               if(peek == ' ' || peek == '\t' || sectbegin == TRUE){
+                                       warning("Executable statements should occur right after %%");
+                                       continue;
+                                       }
+                               x = NEWE;
+                               break;
+                       case '%':
+                               if(prev != '\n') goto character;
+                               if(peek == '{'){        /* included code */
+                                       getl(buf);
+                                       while(!eof && getl(buf) && scomp("%}",buf) != 0)
+                                               fprintf(fout,"%s\n",buf);
+                                       continue;
+                                       }
+                               if(peek == '%'){
+                                       c = gch();
+                                       c = gch();
+                                       x = DELIM;
+                                       break;
+                                       }
+                               goto character;
+                       case '|':
+                               if(peek == ' ' || peek == '\t' || peek == '\n'){
+                                       if(ratfor)fprintf(fout,"%d\n",30000+casecount++);
+                                       else fprintf(fout,"case %d:\n",casecount++);
+                                       continue;
+                                       }
+                               x = '|';
+                               break;
+                       case '$':
+                               if(peek == '\n' || peek == ' ' || peek == '\t' || peek == '|' || peek == '/'){
+                                       x = c;
+                                       break;
+                                       }
+                               goto character;
+                       case '^':
+                               if(prev != '\n' && scon != TRUE) goto character;        /* valid only at line begin */
+                               x = c;
+                               break;
+                       case '?':
+                       case '+':
+                       case '.':
+                       case '*':
+                       case '(':
+                       case ')':
+                       case ',':
+                       case '/':
+                               x = c;
+                               break;
+                       case '}':
+                               iter = FALSE;
+                               x = c;
+                               break;
+                       case '{':       /* either iteration or definition */
+                               if(digit(c=gch())){     /* iteration */
+                                       iter = TRUE;
+                               ieval:
+                                       i = 0;
+                                       while(digit(c)){
+                                               token[i++] = c;
+                                               c = gch();
+                                               }
+                                       token[i] = 0;
+                                       yylval = siconv(token);
+                                       munput('c',c);
+                                       x = ITER;
+                                       break;
+                                       }
+                               else {          /* definition */
+                                       i = 0;
+                                       while(c && c!='}'){
+                                               token[i++] = c;
+                                               c = gch();
+                                               }
+                                       token[i] = 0;
+                                       i = lookup(token,def);
+                                       if(i < 0)
+                                               warning("Definition %s not found",token);
+                                       else
+                                               munput('s',subs[i]);
+                                       continue;
+                                       }
+                       case '<':               /* start condition ? */
+                               if(prev != '\n')                /* not at line begin, not start */
+                                       goto character;
+                               t = slptr;
+                               do {
+                                       i = 0;
+                                       c = gch();
+                                       while(c != ',' && c && c != '>'){
+                                               token[i++] = c;
+                                               c = gch();
+                                               }
+                                       token[i] = 0;
+                                       if(i == 0)
+                                               goto character;
+                                       i = lookup(token,sname);
+                                       if(i < 0) {
+                                               warning("Undefined start condition %s",token);
+                                               continue;
+                                               }
+                                       *slptr++ = i+1;
+                                       } while(c && c != '>');
+                               *slptr++ = 0;
+                               /* check if previous value re-usable */
+                               for (xp=slist; xp<t; )
+                                       {
+                                       if (strcmp(xp, t)==0)
+                                               break;
+                                       while (*xp++);
+                                       }
+                               if (xp<t)
+                                       {
+                                       /* re-use previous pointer to string */
+                                       slptr=t;
+                                       t=xp;
+                                       }
+                               if(slptr > slist+STARTSIZE)             /* note not packed ! */
+                                       error("Too many start conditions used");
+                               yylval = t;
+                               x = SCON;
+                               break;
+                       case '"':
+                               i = 0;
+                               while((c=gch()) && c != '"' && c != '\n'){
+                                       if(c == '\\') c = usescape(c=gch());
+                                       token[i++] = c;
+                                       if(i > TOKENSIZE){
+                                               warning("String too long");
+                                               i = TOKENSIZE-1;
+                                               break;
+                                               }
+                                       }
+                               if(c == '\n') {
+                                       yyline--;
+                                       warning("Non-terminated string");
+                                       yyline++;
+                                       }
+                               token[i] = 0;
+                               if(i == 0)x = NULLS;
+                               else if(i == 1){
+                                       yylval = token[0];
+                                       x = CHAR;
+                                       }
+                               else {
+                                       yylval = token;
+                                       x = STR;
+                                       }
+                               break;
+                       case '[':
+                               for(i=1;i<NCH;i++) symbol[i] = 0;
+                               x = CCL;
+                               if((c = gch()) == '^'){
+                                       x = NCCL;
+                                       c = gch();
+                                       }
+                               while(c != ']' && c){
+                                       if(c == '\\') c = usescape(c=gch());
+                                       symbol[c] = 1;
+                                       j = c;
+                                       if((c=gch()) == '-' && peek != ']'){            /* range specified */
+                                               c = gch();
+                                               if(c == '\\') c = usescape(c=gch());
+                                               k = c;
+                                               if(j > k) {
+                                                       n = j;
+                                                       j = k;
+                                                       k = n;
+                                                       }
+                                               if(!(('A' <= j && k <= 'Z') ||
+                                                    ('a' <= j && k <= 'z') ||
+                                                    ('0' <= j && k <= '9')))
+                                                       warning("Non-portable Character Class");
+                                               for(n=j+1;n<=k;n++)
+                                                       symbol[n] = 1;          /* implementation dependent */
+                                               c = gch();
+                                               }
+                                       }
+                               /* try to pack ccl's */
+                               i = 0;
+                               for(j=0;j<NCH;j++)
+                                       if(symbol[j])token[i++] = j;
+                               token[i] = 0;
+                               p = ccptr;
+                               if(optim){
+                                       p = ccl;
+                                       while(p <ccptr && scomp(token,p) != 0)p++;
+                                       }
+                               if(p < ccptr)   /* found it */
+                                       yylval = p;
+                               else {
+                                       yylval = ccptr;
+                                       scopy(token,ccptr);
+                                       ccptr += slength(token) + 1;
+                                       if(ccptr >= ccl+CCLSIZE)
+                                               error("Too many large character classes");
+                                       }
+                               cclinter(x==CCL);
+                               break;
+                       case '\\':
+                               c = usescape(c=gch());
+                       default:
+                       character:
+                               if(iter){       /* second part of an iteration */
+                                       iter = FALSE;
+                                       if('0' <= c && c <= '9')
+                                               goto ieval;
+                                       }
+                               if(alpha(peek)){
+                                       i = 0;
+                                       yylval = token;
+                                       token[i++] = c;
+                                       while(alpha(peek))
+                                               token[i++] = gch();
+                                       if(peek == '?' || peek == '*' || peek == '+')
+                                               munput('c',token[--i]);
+                                       token[i] = 0;
+                                       if(i == 1){
+                                               yylval = token[0];
+                                               x = CHAR;
+                                               }
+                                       else x = STR;
+                                       }
+                               else {
+                                       yylval = c;
+                                       x = CHAR;
+                                       }
+                               }
+                       scon = FALSE;
+                       if(x == SCON)scon = TRUE;
+                       sectbegin = FALSE;
+                       return(freturn(x));
+                       }
+               }
+       /* section three */
+       ptail();
+# ifdef DEBUG
+       if(debug)
+               fprintf(fout,"\n/*this comes from section three - debug */\n");
+# endif
+       while(getl(buf) && !eof)
+               fprintf(fout,"%s\n",buf);
+       return(freturn(0));
+       }
+/* end of yylex */
+# ifdef DEBUG
+freturn(i)
+  int i; {
+       if(yydebug) {
+               printf("now return ");
+               if(i < NCH) allprint(i);
+               else printf("%d",i);
+               printf("   yylval = ");
+               switch(i){
+                       case STR: case CCL: case NCCL:
+                               strpt(yylval);
+                               break;
+                       case CHAR:
+                               allprint(yylval);
+                               break;
+                       default:
+                               printf("%d",yylval);
+                               break;
+                       }
+               putchar('\n');
+               }
+       return(i);
+       }
+# endif
diff --git a/usr/src/usr.bin/lex/sub1.c b/usr/src/usr.bin/lex/sub1.c
new file mode 100644 (file)
index 0000000..45dc1a9
--- /dev/null
@@ -0,0 +1,683 @@
+# include "ldefs.c"
+char *
+getl(p)        /* return next line of input, throw away trailing '\n' */
+       /* returns 0 if eof is had immediately */
+  char *p;
+       {
+       register int c;
+       register char *s, *t;
+       t = s = p;
+       while(((c = gch()) != 0) && c != '\n')
+               *t++ = c;
+       *t = 0;
+       if(c == 0 && s == t) return(0);
+       prev = '\n';
+       pres = '\n';
+       return(s);
+       }
+space(ch)
+       {
+       switch(ch)
+               {
+               case ' ':
+               case '\t':
+               case '\n':
+                       return(1);
+               }
+       return(0);
+       }
+
+digit(c)
+{
+       return(c>='0' && c <= '9');
+}
+error(s,p,d)
+       {
+       if(!eof)fprintf(errorf,"%d: ",yyline);
+       fprintf(errorf,"(Error) ");
+       fprintf(errorf,s,p,d);
+       putc('\n',errorf);
+# ifdef DEBUG
+       if(debug && sect != ENDSECTION) {
+               sect1dump();
+               sect2dump();
+       }
+# endif
+       if(
+# ifdef DEBUG
+               debug ||
+# endif
+               report == 1) statistics();
+       exit(1);        /* error return code */
+       }
+
+warning(s,p,d)
+       {
+       if(!eof)fprintf(errorf,"%d: ",yyline);
+       fprintf(errorf,"(Warning) ");
+       fprintf(errorf,s,p,d);
+       putc('\n',errorf);
+       fflush(errorf);
+       fflush(fout);
+       fflush(stdout);
+       }
+index(a,s)
+       char *s;
+{
+       register int k;
+       for(k=0; s[k]; k++)
+               if (s[k]== a)
+                       return(k);
+       return(-1);
+       }
+
+alpha(c)
+  int c; {
+# ifdef ASCII
+return('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z');
+# endif
+# ifdef EBCDIC
+return(index(c,"abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") >= 0);
+# endif
+}
+printable(c)
+{
+# ifdef ASCII
+return( c>040 && c < 0177);
+# endif
+# ifdef EBCDIC
+return(index(c, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,;:><+*)('&%!-=\"")>=0);
+# endif
+}
+lgate()
+{
+       char fname[20];
+       if (lgatflg) return;
+       lgatflg=1;
+       if(fout == NULL){
+               sprintf(fname, "lex.yy.%c", ratfor ? 'r' : 'c' );
+               fout = fopen(fname, "w");
+               }
+       if(fout == NULL) error("Can't open %s",fname);
+       if(ratfor) fprintf( fout, "#\n");
+       phead1();
+       }
+/* scopy(ptr to str, ptr to str) - copy first arg str to second */
+/* returns ptr to second arg */
+scopy(s,t)
+  char *s, *t; {
+       register char *i;
+       i = t;
+       while(*i++ = *s++);
+       return;
+       }
+siconv(t)      /* convert string t, return integer value */
+  char *t; {
+       register int i,sw;
+       register char *s;
+       s = t;
+       while(!(('0' <= *s && *s <= '9') || *s == '-') && *s) s++;
+       sw = 0;
+       if(*s == '-'){  /* neg */
+               sw = 1;
+               s++;
+               }
+       i = 0;
+       while('0' <= *s && *s <= '9')
+               i = i * 10 + (*(s++)-'0');
+       return(sw ? -i : i);
+       }
+/* slength(ptr to str) - return integer length of string arg */
+/* excludes '\0' terminator */
+slength(s)
+  char *s; {
+       register int n;
+       register char *t;
+       t = s;
+       for (n = 0; *t++; n++);
+       return(n);
+       }
+/* scomp(x,y) - return -1 if x < y,
+               0 if x == y,
+               return 1 if x > y, all lexicographically */
+scomp(x,y)
+  char *x,*y; {
+       register char *a,*d;
+       a = x;
+       d = y;
+       while(*a || *d){
+               if(*a > *d)
+                       return(1);      /* greater */
+               if(*a < *d)
+                       return(-1);     /* less */
+               a++;
+               d++;
+               }
+       return(0);      /* equal */
+       }
+ctrans(ss)
+       char **ss;
+{
+       register int c, k;
+       if ((c = **ss) != '\\')
+               return(c);
+       switch(c= *++*ss)
+       {
+       case 'n': c = '\n'; break;
+       case 't': c = '\t'; break;
+       case 'r': c = '\r'; break;
+       case 'b': c = '\b'; break;
+       case 'f': c = 014; break;               /* form feed for ascii */
+       case '\\': c = '\\'; break;
+       case '0': case '1': case '2': case '3':
+       case '4': case '5': case '6': case '7':
+               c -= '0';
+               while ((k = *(*ss+1)) >= '0' && k <= '7')
+                       {
+                       c = c*8 + k - '0';
+                       (*ss)++;
+                       }
+               break;
+       }
+       return(c);
+}
+cclinter(sw)
+  int sw; {
+               /* sw = 1 ==> ccl */
+       register int i, j, k;
+       int m;
+       if(!sw){                /* is NCCL */
+               for(i=1;i<NCH;i++)
+                       symbol[i] ^= 1;                 /* reverse value */
+               }
+       for(i=1;i<NCH;i++)
+               if(symbol[i]) break;
+       if(i >= NCH) return;
+       i = cindex[i];
+       /* see if ccl is already in our table */
+       j = 0;
+       if(i){
+               for(j=1;j<NCH;j++){
+                       if((symbol[j] && cindex[j] != i) ||
+                          (!symbol[j] && cindex[j] == i)) break;
+                       }
+               }
+       if(j >= NCH) return;            /* already in */
+       m = 0;
+       k = 0;
+       for(i=1;i<NCH;i++)
+               if(symbol[i]){
+                       if(!cindex[i]){
+                               cindex[i] = ccount;
+                               symbol[i] = 0;
+                               m = 1;
+                               }
+                       else k = 1;
+                       }
+                       /* m == 1 implies last value of ccount has been used */
+       if(m)ccount++;
+       if(k == 0) return;      /* is now in as ccount wholly */
+       /* intersection must be computed */
+       for(i=1;i<NCH;i++){
+               if(symbol[i]){
+                       m = 0;
+                       j = cindex[i];  /* will be non-zero */
+                       for(k=1;k<NCH;k++){
+                               if(cindex[k] == j){
+                                       if(symbol[k]) symbol[k] = 0;
+                                       else {
+                                               cindex[k] = ccount;
+                                               m = 1;
+                                               }
+                                       }
+                               }
+                       if(m)ccount++;
+                       }
+               }
+       return;
+       }
+usescape(c)
+  int c; {
+       register char d;
+       switch(c){
+       case 'n': c = '\n'; break;
+       case 'r': c = '\r'; break;
+       case 't': c = '\t'; break;
+       case 'b': c = '\b'; break;
+       case 'f': c = 014; break;               /* form feed for ascii */
+       case '0': case '1': case '2': case '3':
+       case '4': case '5': case '6': case '7':
+               c -= '0';
+               while('0' <= (d=gch()) && d <= '7'){
+                       c = c * 8 + (d-'0');
+                       if(!('0' <= peek && peek <= '7')) break;
+                       }
+               break;
+       }
+       return(c);
+       }
+lookup(s,t)
+  char *s;
+  char **t; {
+       register int i;
+       i = 0;
+       while(*t){
+               if(scomp(s,*t) == 0)
+                       return(i);
+               i++;
+               t++;
+               }
+       return(-1);
+       }
+cpyact(){ /* copy C action to the next ; or closing } */
+       register int brac, c, mth;
+       int savline, sw;
+
+       brac = 0;
+       sw = TRUE;
+
+while(!eof){
+       c = gch();
+swt:
+       switch( c ){
+
+case '|':      if(brac == 0 && sw == TRUE){
+                       if(peek == '|')gch();           /* eat up an extra '|' */
+                       return(0);
+                       }
+               break;
+
+case ';':
+               if( brac == 0 ){
+                       putc(c,fout);
+                       putc('\n',fout);
+                       return(1);
+                       }
+               break;
+
+case '{':
+               brac++;
+               savline=yyline;
+               break;
+
+case '}':
+               brac--;
+               if( brac == 0 ){
+                       putc(c,fout);
+                       putc('\n',fout);
+                       return(1);
+                       }
+               break;
+
+case '/':      /* look for comments */
+               putc(c,fout);
+               c = gch();
+               if( c != '*' ) goto swt;
+
+               /* it really is a comment */
+
+               putc(c,fout);
+               savline=yyline;
+               while( c=gch() ){
+                       if( c=='*' ){
+                               putc(c,fout);
+                               if( (c=gch()) == '/' ) goto loop;
+                               }
+                       putc(c,fout);
+                       }
+               yyline=savline;
+               error( "EOF inside comment" );
+
+case '\'':     /* character constant */
+               mth = '\'';
+               goto string;
+
+case '"':      /* character string */
+               mth = '"';
+
+       string:
+
+               putc(c,fout);
+               while( c=gch() ){
+                       if( c=='\\' ){
+                               putc(c,fout);
+                               c=gch();
+                               }
+                       else if( c==mth ) goto loop;
+                       putc(c,fout);
+                       if (c == '\n')
+                               {
+                               yyline--;
+                               error( "Non-terminated string or character constant");
+                               }
+                       }
+               error( "EOF in string or character constant" );
+
+case '\0':
+               yyline = savline;
+               error("Action does not terminate");
+default:
+               break;          /* usual character */
+               }
+loop:
+       if(c != ' ' && c != '\t' && c != '\n') sw = FALSE;
+       putc(c,fout);
+       }
+error("Premature EOF");
+}
+gch(){
+       register int c;
+       prev = pres;
+       c = pres = peek;
+       peek = pushptr > pushc ? *--pushptr : getc(fin);
+       if(peek == EOF && sargc > 1){
+               fclose(fin);
+               fin = fopen(sargv[++fptr],"r");
+               if(fin == NULL)
+                       error("Cannot open file %s",sargv[fptr]);
+               peek = getc(fin);
+               sargc--;
+               sargv++;
+               }
+       if(c == EOF) {
+               eof = TRUE;
+               fclose(fin);
+               return(0);
+               }
+       if(c == '\n')yyline++;
+       return(c);
+       }
+mn2(a,d,c)
+  int a,d,c;
+       {
+       name[tptr] = a;
+       left[tptr] = d;
+       right[tptr] = c;
+       parent[tptr] = 0;
+       nullstr[tptr] = 0;
+       switch(a){
+       case RSTR:
+               parent[d] = tptr;
+               break;
+       case BAR:
+       case RNEWE:
+               if(nullstr[d] || nullstr[c]) nullstr[tptr] = TRUE;
+               parent[d] = parent[c] = tptr;
+               break;
+       case RCAT:
+       case DIV:
+               if(nullstr[d] && nullstr[c])nullstr[tptr] = TRUE;
+               parent[d] = parent[c] = tptr;
+               break;
+       case RSCON:
+               parent[d] = tptr;
+               nullstr[tptr] = nullstr[d];
+               break;
+# ifdef DEBUG
+       default:
+               warning("bad switch mn2 %d %d",a,d);
+               break;
+# endif
+               }
+       if(tptr > treesize)
+               error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
+       return(tptr++);
+       }
+mn1(a,d)
+  int a,d;
+       {
+       name[tptr] = a;
+       left[tptr] = d;
+       parent[tptr] = 0;
+       nullstr[tptr] = 0;
+       switch(a){
+       case RCCL:
+       case RNCCL:
+               if(slength(d) == 0) nullstr[tptr] = TRUE;
+               break;
+       case STAR:
+       case QUEST:
+               nullstr[tptr] = TRUE;
+               parent[d] = tptr;
+               break;
+       case PLUS:
+       case CARAT:
+               nullstr[tptr] = nullstr[d];
+               parent[d] = tptr;
+               break;
+       case S2FINAL:
+               nullstr[tptr] = TRUE;
+               break;
+# ifdef DEBUG
+       case FINAL:
+       case S1FINAL:
+               break;
+       default:
+               warning("bad switch mn1 %d %d",a,d);
+               break;
+# endif
+               }
+       if(tptr > treesize)
+               error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
+       return(tptr++);
+       }
+mn0(a)
+  int a;
+       {
+       name[tptr] = a;
+       parent[tptr] = 0;
+       nullstr[tptr] = 0;
+       if(a >= NCH) switch(a){
+       case RNULLS: nullstr[tptr] = TRUE; break;
+# ifdef DEBUG
+       default:
+               warning("bad switch mn0 %d",a);
+               break;
+# endif
+       }
+       if(tptr > treesize)
+               error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
+       return(tptr++);
+       }
+munput(t,p)    /* implementation dependent */
+  char *p;
+  int t; {
+       register int i,j;
+       if(t == 'c'){
+               *pushptr++ = peek;              /* watch out for this */
+               peek = p;
+               }
+       else if(t == 's'){
+               *pushptr++ = peek;
+               peek = p[0];
+               i = slength(p);
+               for(j = i-1; j>=1; j--)
+                       *pushptr++ = p[j];
+               }
+# ifdef DEBUG
+       else error("Unrecognized munput option %c",t);
+# endif
+       if(pushptr >= pushc+TOKENSIZE)
+               error("Too many characters pushed");
+       return;
+       }
+
+dupl(n)
+  int n; {
+       /* duplicate the subtree whose root is n, return ptr to it */
+       register int i;
+       i = name[n];
+       if(i < NCH) return(mn0(i));
+       switch(i){
+       case RNULLS:
+               return(mn0(i));
+       case RCCL: case RNCCL: case FINAL: case S1FINAL: case S2FINAL:
+               return(mn1(i,left[n]));
+       case STAR: case QUEST: case PLUS: case CARAT:
+               return(mn1(i,dupl(left[n])));
+       case RSTR: case RSCON:
+               return(mn2(i,dupl(left[n]),right[n]));
+       case BAR: case RNEWE: case RCAT: case DIV:
+               return(mn2(i,dupl(left[n]),dupl(right[n])));
+# ifdef DEBUG
+       default:
+               warning("bad switch dupl %d",n);
+# endif
+       }
+       return(0);
+       }
+# ifdef DEBUG
+allprint(c)
+  char c; {
+       switch(c){
+               case 014:
+                       printf("\\f");
+                       charc++;
+                       break;
+               case '\n':
+                       printf("\\n");
+                       charc++;
+                       break;
+               case '\t':
+                       printf("\\t");
+                       charc++;
+                       break;
+               case '\b':
+                       printf("\\b");
+                       charc++;
+                       break;
+               case ' ':
+                       printf("\\\bb");
+                       break;
+               default:
+                       if(!printable(c)){
+                               printf("\\%-3o",c);
+                               charc =+ 3;
+                               }
+                       else 
+                               putchar(c);
+                       break;
+               }
+       charc++;
+       return;
+       }
+strpt(s)
+  char *s; {
+       charc = 0;
+       while(*s){
+               allprint(*s++);
+               if(charc > LINESIZE){
+                       charc = 0;
+                       printf("\n\t");
+                       }
+               }
+       return;
+       }
+sect1dump(){
+       register int i;
+       printf("Sect 1:\n");
+       if(def[0]){
+               printf("str     trans\n");
+               i = -1;
+               while(def[++i])
+                       printf("%s\t%s\n",def[i],subs[i]);
+               }
+       if(sname[0]){
+               printf("start names\n");
+               i = -1;
+               while(sname[++i])
+                       printf("%s\n",sname[i]);
+               }
+       if(chset == TRUE){
+               printf("char set changed\n");
+               for(i=1;i<NCH;i++){
+                       if(i != ctable[i]){
+                               allprint(i);
+                               putchar(' ');
+                               printable(ctable[i]) ? putchar(ctable[i]) : printf("%d",ctable[i]);
+                               putchar('\n');
+                               }
+                       }
+               }
+       }
+sect2dump(){
+       printf("Sect 2:\n");
+       treedump();
+       }
+treedump()
+       {
+       register int t;
+       register char *p;
+       printf("treedump %d nodes:\n",tptr);
+       for(t=0;t<tptr;t++){
+               printf("%4d ",t);
+               parent[t] ? printf("p=%4d",parent[t]) : printf("      ");
+               printf("  ");
+               if(name[t] < NCH) {
+                               allprint(name[t]);
+                               }
+               else switch(name[t]){
+                       case RSTR:
+                               printf("%d ",left[t]);
+                               allprint(right[t]);
+                               break;
+                       case RCCL:
+                               printf("ccl ");
+                               strpt(left[t]);
+                               break;
+                       case RNCCL:
+                               printf("nccl ");
+                               strpt(left[t]);
+                               break;
+                       case DIV:
+                               printf("/ %d %d",left[t],right[t]);
+                               break;
+                       case BAR:
+                               printf("| %d %d",left[t],right[t]);
+                               break;
+                       case RCAT:
+                               printf("cat %d %d",left[t],right[t]);
+                               break;
+                       case PLUS:
+                               printf("+ %d",left[t]);
+                               break;
+                       case STAR:
+                               printf("* %d",left[t]);
+                               break;
+                       case CARAT:
+                               printf("^ %d",left[t]);
+                               break;
+                       case QUEST:
+                               printf("? %d",left[t]);
+                               break;
+                       case RNULLS:
+                               printf("nullstring");
+                               break;
+                       case FINAL:
+                               printf("final %d",left[t]);
+                               break;
+                       case S1FINAL:
+                               printf("s1final %d",left[t]);   
+                               break;
+                       case S2FINAL:
+                               printf("s2final %d",left[t]);
+                               break;
+                       case RNEWE:
+                               printf("new %d %d",left[t],right[t]);
+                               break;
+                       case RSCON:
+                               p = right[t];
+                               printf("start %s",sname[*p++-1]);
+                               while(*p)
+                                       printf(", %s",sname[*p++-1]);
+                               printf(" %d",left[t]);
+                               break;
+                       default:
+                               printf("unknown %d %d %d",name[t],left[t],right[t]);
+                               break;
+                       }
+               if(nullstr[t])printf("\t(null poss.)");
+               putchar('\n');
+               }
+       }
+# endif
diff --git a/usr/src/usr.bin/lex/sub2.c b/usr/src/usr.bin/lex/sub2.c
new file mode 100644 (file)
index 0000000..ce0741d
--- /dev/null
@@ -0,0 +1,951 @@
+# include "ldefs.c"
+cfoll(v)
+       int v;
+       {
+       register int i,j,k;
+       char *p;
+       i = name[v];
+       if(i < NCH) i = 1;      /* character */
+       switch(i){
+               case 1: case RSTR: case RCCL: case RNCCL: case RNULLS:
+                       for(j=0;j<tptr;j++)
+                               tmpstat[j] = FALSE;
+                       count = 0;
+                       follow(v);
+# ifdef PP
+                       padd(foll,v);           /* packing version */
+# endif
+# ifndef PP
+                       add(foll,v);            /* no packing version */
+# endif
+                       if(i == RSTR) cfoll(left[v]);
+                       else if(i == RCCL || i == RNCCL){       /* compress ccl list */
+                               for(j=1; j<NCH;j++)
+                                       symbol[j] = (i==RNCCL);
+                               p = left[v];
+                               while(*p)
+                                       symbol[*p++] = (i == RCCL);
+                               p = pcptr;
+                               for(j=1;j<NCH;j++)
+                                       if(symbol[j]){
+                                               for(k=0;p+k < pcptr; k++)
+                                                       if(cindex[j] == *(p+k))
+                                                               break;
+                                               if(p+k >= pcptr)*pcptr++ = cindex[j];
+                                               }
+                               *pcptr++ = 0;
+                               if(pcptr > pchar + pchlen)
+                                       error("Too many packed character classes");
+                               left[v] = p;
+                               name[v] = RCCL; /* RNCCL eliminated */
+# ifdef DEBUG
+                               if(debug && *p){
+                                       printf("ccl %d: %d",v,*p++);
+                                       while(*p)
+                                               printf(", %d",*p++);
+                                       putchar('\n');
+                                       }
+# endif
+                               }
+                       break;
+               case CARAT:
+                       cfoll(left[v]);
+                       break;
+               case STAR: case PLUS: case QUEST: case RSCON: 
+                       cfoll(left[v]);
+                       break;
+               case BAR: case RCAT: case DIV: case RNEWE:
+                       cfoll(left[v]);
+                       cfoll(right[v]);
+                       break;
+# ifdef DEBUG
+               case FINAL:
+               case S1FINAL:
+               case S2FINAL:
+                       break;
+               default:
+                       warning("bad switch cfoll %d",v);
+# endif
+               }
+       return;
+       }
+# ifdef DEBUG
+pfoll()
+       {
+       register int i,k,*p;
+       int j;
+       /* print sets of chars which may follow positions */
+       printf("pos\tchars\n");
+       for(i=0;i<tptr;i++)
+               if(p=foll[i]){
+                       j = *p++;
+                       if(j >= 1){
+                               printf("%d:\t%d",i,*p++);
+                               for(k=2;k<=j;k++)
+                                       printf(", %d",*p++);
+                               putchar('\n');
+                               }
+                       }
+       return;
+       }
+# endif
+add(array,n)
+  int **array;
+  int n; {
+       register int i, *temp;
+       register char *ctemp;
+       temp = nxtpos;
+       ctemp = tmpstat;
+       array[n] = nxtpos;              /* note no packing is done in positions */
+       *temp++ = count;
+       for(i=0;i<tptr;i++)
+               if(ctemp[i] == TRUE)
+                       *temp++ = i;
+       nxtpos = temp;
+       if(nxtpos >= positions+maxpos)
+               error("Too many positions %s",(maxpos== MAXPOS?"\nTry using %p num":""));
+       return;
+       }
+follow(v)
+  int v;
+       {
+       register int p;
+       if(v >= tptr-1)return;
+       p = parent[v];
+       if(p == 0) return;
+       switch(name[p]){
+                       /* will not be CHAR RNULLS FINAL S1FINAL S2FINAL RCCL RNCCL */
+               case RSTR:
+                       if(tmpstat[p] == FALSE){
+                               count++;
+                               tmpstat[p] = TRUE;
+                               }
+                       break;
+               case STAR: case PLUS:
+                       first(v);
+                       follow(p);
+                       break;
+               case BAR: case QUEST: case RNEWE:
+                       follow(p);
+                       break;
+               case RCAT: case DIV: 
+                       if(v == left[p]){
+                               if(nullstr[right[p]])
+                                       follow(p);
+                               first(right[p]);
+                               }
+                       else follow(p);
+                       break;
+               case RSCON: case CARAT: 
+                       follow(p);
+                       break;
+# ifdef DEBUG
+               default:
+                       warning("bad switch follow %d",p);
+# endif
+               }
+       return;
+       }
+first(v)       /* calculate set of positions with v as root which can be active initially */
+  int v; {
+       register int i;
+       register char *p;
+       i = name[v];
+       if(i < NCH)i = 1;
+       switch(i){
+               case 1: case RCCL: case RNCCL: case RNULLS: case FINAL: case S1FINAL: case S2FINAL:
+                       if(tmpstat[v] == FALSE){
+                               count++;
+                               tmpstat[v] = TRUE;
+                               }
+                       break;
+               case BAR: case RNEWE:
+                       first(left[v]);
+                       first(right[v]);
+                       break;
+               case CARAT:
+                       if(stnum % 2 == 1)
+                               first(left[v]);
+                       break;
+               case RSCON:
+                       i = stnum/2 +1;
+                       p = right[v];
+                       while(*p)
+                               if(*p++ == i){
+                                       first(left[v]);
+                                       break;
+                                       }
+                       break;
+               case STAR: case QUEST: case PLUS:  case RSTR:
+                       first(left[v]);
+                       break;
+               case RCAT: case DIV:
+                       first(left[v]);
+                       if(nullstr[left[v]])
+                               first(right[v]);
+                       break;
+# ifdef DEBUG
+               default:
+                       warning("bad switch first %d",v);
+# endif
+               }
+       return;
+       }
+cgoto(){
+       register int i, j, s;
+       int npos, curpos, n;
+       int tryit;
+       char tch[NCH];
+       int tst[NCH];
+       char *q;
+       /* generate initial state, for each start condition */
+       if(ratfor){
+               fprintf(fout,"blockdata\n");
+               fprintf(fout,"common /Lvstop/ vstop\n");
+               fprintf(fout,"define Svstop %d\n",nstates+1);
+               fprintf(fout,"integer vstop(Svstop)\n");
+               }
+       else fprintf(fout,"int yyvstop[] ={\n0,\n");
+       while(stnum < 2 || stnum/2 < sptr){
+               for(i = 0; i<tptr; i++) tmpstat[i] = 0;
+               count = 0;
+               if(tptr > 0)first(tptr-1);
+               add(state,stnum);
+# ifdef DEBUG
+               if(debug){
+                       if(stnum > 1)
+                               printf("%s:\n",sname[stnum/2]);
+                       pstate(stnum);
+                       }
+# endif
+               stnum++;
+               }
+       stnum--;
+       /* even stnum = might not be at line begin */
+       /* odd stnum  = must be at line begin */
+       /* even states can occur anywhere, odd states only at line begin */
+       for(s = 0; s <= stnum; s++){
+               tryit = FALSE;
+               cpackflg[s] = FALSE;
+               sfall[s] = -1;
+               acompute(s);
+               for(i=0;i<NCH;i++) symbol[i] = 0;
+               npos = *state[s];
+               for(i = 1; i<=npos; i++){
+                       curpos = *(state[s]+i);
+                       if(name[curpos] < NCH) symbol[name[curpos]] = TRUE;
+                       else switch(name[curpos]){
+                       case RCCL:
+                               tryit = TRUE;
+                               q = left[curpos];
+                               while(*q){
+                                       for(j=1;j<NCH;j++)
+                                               if(cindex[j] == *q)
+                                                       symbol[j] = TRUE;
+                                       q++;
+                                       }
+                               break;
+                       case RSTR:
+                               symbol[right[curpos]] = TRUE;
+                               break;
+# ifdef DEBUG
+                       case RNULLS:
+                       case FINAL:
+                       case S1FINAL:
+                       case S2FINAL:
+                               break;
+                       default:
+                               warning("bad switch cgoto %d state %d",curpos,s);
+                               break;
+# endif
+                       }
+               }
+# ifdef DEBUG
+               if(debug){
+                       printf("State %d transitions on:\n\t",s);
+                       charc = 0;
+                       for(i = 1; i<NCH; i++){
+                               if(symbol[i]) allprint(i);
+                               if(charc > LINESIZE){
+                                       charc = 0;
+                                       printf("\n\t");
+                                       }
+                               }
+                       putchar('\n');
+                       }
+# endif
+               /* for each char, calculate next state */
+               n = 0;
+               for(i = 1; i<NCH; i++){
+                       if(symbol[i]){
+                               nextstate(s,i);         /* executed for each state, transition pair */
+                               xstate = notin(stnum);
+                               if(xstate == -2) warning("bad state  %d %o",s,i);
+                               else if(xstate == -1){
+                                       if(stnum >= nstates)
+                                               error("Too many states %s",(nstates == NSTATES ? "\nTry using %n num":""));
+                                       add(state,++stnum);
+# ifdef DEBUG
+                                       if(debug)pstate(stnum);
+# endif
+                                       tch[n] = i;
+                                       tst[n++] = stnum;
+                                       }
+                               else {          /* xstate >= 0 ==> state exists */
+                                       tch[n] = i;
+                                       tst[n++] = xstate;
+                                       }
+                               }
+                       }
+               tch[n] = 0;
+               tst[n] = -1;
+               /* pack transitions into permanent array */
+               if(n > 0) packtrans(s,tch,tst,n,tryit);
+               else gotof[s] = -1;
+               }
+       ratfor ? fprintf(fout,"end\n") : fprintf(fout,"0};\n");
+       return;
+       }
+       /*      Beware -- 70% of total CPU time is spent in this subroutine -
+               if you don't believe me - try it yourself ! */
+nextstate(s,c)
+  int s,c; {
+       register int j, *newpos;
+       register char *temp, *tz;
+       int *pos, i, *f, num, curpos, number;
+       /* state to goto from state s on char c */
+       num = *state[s];
+       temp = tmpstat;
+       pos = state[s] + 1;
+       for(i = 0; i<num; i++){
+               curpos = *pos++;
+               j = name[curpos];
+               if(j < NCH && j == c
+               || j == RSTR && c == right[curpos]
+               || j == RCCL && member(c,left[curpos])){
+                       f = foll[curpos];
+                       number = *f;
+                       newpos = f+1;
+                       for(j=0;j<number;j++)
+                               temp[*newpos++] = 2;
+                       }
+               }
+       j = 0;
+       tz = temp + tptr;
+       while(temp < tz){
+               if(*temp == 2){
+                       j++;
+                       *temp++ = 1;
+                       }
+               else *temp++ = 0;
+               }
+       count = j;
+       return;
+       }
+notin(n)
+  int n;       {       /* see if tmpstat occurs previously */
+       register int *j,k;
+       register char *temp;
+       int i;
+       if(count == 0)
+               return(-2);
+       temp = tmpstat;
+       for(i=n;i>=0;i--){      /* for each state */
+               j = state[i];
+               if(count == *j++){
+                       for(k=0;k<count;k++)
+                               if(!temp[*j++])break;
+                       if(k >= count)
+                               return(i);
+                       }
+               }
+       return(-1);
+       }
+packtrans(st,tch,tst,cnt,tryit)
+  int st, *tst, cnt,tryit;
+  char *tch; {
+       /* pack transitions into nchar, nexts */
+       /* nchar is terminated by '\0', nexts uses cnt, followed by elements */
+       /* gotof[st] = index into nchr, nexts for state st */
+
+       /* sfall[st] =  t implies t is fall back state for st */
+       /*              == -1 implies no fall back */
+
+       int cmin, cval, tcnt, diff, p, *ast;
+       register int i,j,k;
+       char *ach;
+       int go[NCH], temp[NCH], c;
+       int swork[NCH];
+       char cwork[NCH];
+       int upper;
+
+       rcount += cnt;
+       cmin = -1;
+       cval = NCH;
+       ast = tst;
+       ach = tch;
+       /* try to pack transitions using ccl's */
+       if(!optim)goto nopack;          /* skip all compaction */
+       if(tryit){      /* ccl's used */
+               for(i=1;i<NCH;i++){
+                       go[i] = temp[i] = -1;
+                       symbol[i] = 1;
+                       }
+               for(i=0;i<cnt;i++){
+                       go[tch[i]] = tst[i];
+                       symbol[tch[i]] = 0;
+                       }
+               for(i=0; i<cnt;i++){
+                       c = match[tch[i]];
+                       if(go[c] != tst[i] || c == tch[i])
+                               temp[tch[i]] = tst[i];
+                       }
+               /* fill in error entries */
+               for(i=1;i<NCH;i++)
+                       if(symbol[i]) temp[i] = -2;     /* error trans */
+               /* count them */
+               k = 0;
+               for(i=1;i<NCH;i++)
+                       if(temp[i] != -1)k++;
+               if(k <cnt){     /* compress by char */
+# ifdef DEBUG
+                       if(debug) printf("use compression  %d,  %d vs %d\n",st,k,cnt);
+# endif
+                       k = 0;
+                       for(i=1;i<NCH;i++)
+                               if(temp[i] != -1){
+                                       cwork[k] = i;
+                                       swork[k++] = (temp[i] == -2 ? -1 : temp[i]);
+                                       }
+                       cwork[k] = 0;
+# ifdef PC
+                       ach = cwork;
+                       ast = swork;
+                       cnt = k;
+                       cpackflg[st] = TRUE;
+# endif
+                       }
+               }
+       for(i=0; i<st; i++){    /* get most similar state */
+                               /* reject state with more transitions, state already represented by a third state,
+                                       and state which is compressed by char if ours is not to be */
+               if(sfall[i] != -1) continue;
+               if(cpackflg[st] == 1) if(!(cpackflg[i] == 1)) continue;
+               p = gotof[i];
+               if(p == -1) /* no transitions */ continue;
+               tcnt = nexts[p];
+               if(tcnt > cnt) continue;
+               diff = 0;
+               k = 0;
+               j = 0;
+               upper = p + tcnt;
+               while(ach[j] && p < upper){
+                       while(ach[j] < nchar[p] && ach[j]){diff++; j++; }
+                       if(ach[j] == 0)break;
+                       if(ach[j] > nchar[p]){diff=NCH;break;}
+                       /* ach[j] == nchar[p] */
+                       if(ast[j] != nexts[++p] || ast[j] == -1 || (cpackflg[st] && ach[j] != match[ach[j]]))diff++;
+                       j++;
+                       }
+               while(ach[j]){
+                       diff++;
+                       j++;
+                       }
+               if(p < upper)diff = NCH;
+               if(diff < cval && diff < tcnt){
+                       cval = diff;
+                       cmin = i;
+                       if(cval == 0)break;
+                       }
+               }
+       /* cmin = state "most like" state st */
+# ifdef DEBUG
+       if(debug)printf("select st %d for st %d diff %d\n",cmin,st,cval);
+# endif
+# ifdef PS
+       if(cmin != -1){ /* if we can use st cmin */
+               gotof[st] = nptr;
+               k = 0;
+               sfall[st] = cmin;
+               p = gotof[cmin]+1;
+               j = 0;
+               while(ach[j]){
+                       /* if cmin has a transition on c, then so will st */
+                       /* st may be "larger" than cmin, however */
+                       while(ach[j] < nchar[p-1] && ach[j]){
+                               k++;
+                               nchar[nptr] = ach[j];
+                               nexts[++nptr] = ast[j];
+                               j++;
+                               }
+                       if(nchar[p-1] == 0)break;
+                       if(ach[j] > nchar[p-1]){
+                               warning("bad transition %d %d",st,cmin);
+                               goto nopack;
+                               }
+                       /* ach[j] == nchar[p-1] */
+                       if(ast[j] != nexts[p] || ast[j] == -1 || (cpackflg[st] && ach[j] != match[ach[j]])){
+                               k++;
+                               nchar[nptr] = ach[j];
+                               nexts[++nptr] = ast[j];
+                               }
+                       p++;
+                       j++;
+                       }
+               while(ach[j]){
+                       nchar[nptr] = ach[j];
+                       nexts[++nptr] = ast[j++];
+                       k++;
+                       }
+               nexts[gotof[st]] = cnt = k;
+               nchar[nptr++] = 0;
+               }
+       else {
+# endif
+nopack:
+       /* stick it in */
+               gotof[st] = nptr;
+               nexts[nptr] = cnt;
+               for(i=0;i<cnt;i++){
+                       nchar[nptr] = ach[i];
+                       nexts[++nptr] = ast[i];
+                       }
+               nchar[nptr++] = 0;
+# ifdef PS
+               }
+# endif
+       if(cnt < 1){
+               gotof[st] = -1;
+               nptr--;
+               }
+       else
+               if(nptr > ntrans)
+                       error("Too many transitions %s",(ntrans==NTRANS?"\nTry using %a num":""));
+       return;
+       }
+# ifdef DEBUG
+pstate(s)
+  int s; {
+       register int *p,i,j;
+       printf("State %d:\n",s);
+       p = state[s];
+       i = *p++;
+       if(i == 0) return;
+       printf("%4d",*p++);
+       for(j = 1; j<i; j++){
+               printf(", %4d",*p++);
+               if(j%30 == 0)putchar('\n');
+               }
+       putchar('\n');
+       return;
+       }
+# endif
+member(d,t)
+  int d;
+  char *t;     {
+       register int c;
+       register char *s;
+       c = d;
+       s = t;
+       c = cindex[c];
+       while(*s)
+               if(*s++ == c) return(1);
+       return(0);
+       }
+# ifdef DEBUG
+stprt(i)
+  int i; {
+       register int p, t;
+       printf("State %d:",i);
+       /* print actions, if any */
+       t = atable[i];
+       if(t != -1)printf(" final");
+       putchar('\n');
+       if(cpackflg[i] == TRUE)printf("backup char in use\n");
+       if(sfall[i] != -1)printf("fall back state %d\n",sfall[i]);
+       p = gotof[i];
+       if(p == -1) return;
+       printf("(%d transitions)\n",nexts[p]);
+       while(nchar[p]){
+               charc = 0;
+               if(nexts[p+1] >= 0)
+                       printf("%d\t",nexts[p+1]);
+               else printf("err\t");
+               allprint(nchar[p++]);
+               while(nexts[p] == nexts[p+1] && nchar[p]){
+                       if(charc > LINESIZE){
+                               charc = 0;
+                               printf("\n\t");
+                               }
+                       allprint(nchar[p++]);
+                       }
+               putchar('\n');
+               }
+       putchar('\n');
+       return;
+       }
+# endif
+acompute(s)    /* compute action list = set of poss. actions */
+  int s; {
+       register int *p, i, j;
+       int cnt, m;
+       int temp[300], k, neg[300], n;
+       k = 0;
+       n = 0;
+       p = state[s];
+       cnt = *p++;
+       if(cnt > 300)
+               error("Too many positions for one state - acompute");
+       for(i=0;i<cnt;i++){
+               if(name[*p] == FINAL)temp[k++] = left[*p];
+               else if(name[*p] == S1FINAL){temp[k++] = left[*p];
+                       if (left[*p] >NACTIONS) error("Too many right contexts");
+                       extra[left[*p]] = 1;
+                       }
+               else if(name[*p] == S2FINAL)neg[n++] = left[*p];
+               p++;
+               }
+       atable[s] = -1;
+       if(k < 1 && n < 1) return;
+# ifdef DEBUG
+       if(debug) printf("final %d actions:",s);
+# endif
+       /* sort action list */
+       for(i=0; i<k; i++)
+               for(j=i+1;j<k;j++)
+                       if(temp[j] < temp[i]){
+                               m = temp[j];
+                               temp[j] = temp[i];
+                               temp[i] = m;
+                               }
+       /* remove dups */
+       for(i=0;i<k-1;i++)
+               if(temp[i] == temp[i+1]) temp[i] = 0;
+       /* copy to permanent quarters */
+       atable[s] = aptr;
+# ifdef DEBUG
+       if(!ratfor)fprintf(fout,"/* actions for state %d */",s);
+# endif
+       putc('\n',fout);
+       for(i=0;i<k;i++)
+               if(temp[i] != 0){
+                       ratfor ? fprintf(fout,"data vstop(%d)/%d/\n",aptr,temp[i]) : fprintf(fout,"%d,\n",temp[i]);
+# ifdef DEBUG
+                       if(debug)
+                               printf("%d ",temp[i]);
+# endif
+                       aptr++;
+                       }
+       for(i=0;i<n;i++){               /* copy fall back actions - all neg */
+               ratfor ? fprintf(fout,"data vstop(%d)/%d/\n",aptr,neg[i]) : fprintf(fout,"%d,\n",neg[i]);
+               aptr++;
+# ifdef DEBUG
+               if(debug)printf("%d ",neg[i]);
+# endif
+               }
+# ifdef DEBUG
+       if(debug)putchar('\n');
+# endif
+       ratfor ? fprintf(fout,"data vstop (%d)/0/\n",aptr) : fprintf(fout,"0,\n");
+       aptr++;
+       return;
+       }
+# ifdef DEBUG
+pccl() {
+       /* print character class sets */
+       register int i, j;
+       printf("char class intersection\n");
+       for(i=0; i< ccount; i++){
+               charc = 0;
+               printf("class %d:\n\t",i);
+               for(j=1;j<NCH;j++)
+                       if(cindex[j] == i){
+                               allprint(j);
+                               if(charc > LINESIZE){
+                                       printf("\n\t");
+                                       charc = 0;
+                                       }
+                               }
+               putchar('\n');
+               }
+       charc = 0;
+       printf("match:\n");
+       for(i=0;i<NCH;i++){
+               allprint(match[i]);
+               if(charc > LINESIZE){
+                       putchar('\n');
+                       charc = 0;
+                       }
+               }
+       putchar('\n');
+       return;
+       }
+# endif
+mkmatch(){
+       register int i;
+       char tab[NCH];
+       for(i=0; i<ccount; i++)
+               tab[i] = 0;
+       for(i=1;i<NCH;i++)
+               if(tab[cindex[i]] == 0)
+                       tab[cindex[i]] = i;
+       /* tab[i] = principal char for new ccl i */
+       for(i = 1; i<NCH; i++)
+               match[i] = tab[cindex[i]];
+       return;
+       }
+layout(){
+       /* format and output final program's tables */
+       register int i, j, k;
+       int  top, bot, startup, omin;
+       startup = 0;
+       for(i=0; i<outsize;i++)
+               verify[i] = advance[i] = 0;
+       omin = 0;
+       yytop = 0;
+       for(i=0; i<= stnum; i++){       /* for each state */
+               j = gotof[i];
+               if(j == -1){
+                       stoff[i] = 0;
+                       continue;
+                       }
+               bot = j;
+               while(nchar[j])j++;
+               top = j - 1;
+# if DEBUG
+               if (debug)
+                       {
+                       printf("State %d: (layout)\n", i);
+                       for(j=bot; j<=top;j++)
+                               {
+                               printf("  %o", nchar[j]);
+                               if (j%10==0) putchar('\n');
+                               }
+                       putchar('\n');
+                       }
+# endif
+               while(verify[omin+ZCH]) omin++;
+               startup = omin;
+# if DEBUG
+               if (debug) printf("bot,top %d, %d startup begins %d\n",bot,top,startup);
+# endif
+               if(chset){
+                       do {
+                               ++startup;
+                               if(startup > outsize - ZCH)
+                                       error("output table overflow");
+                               for(j = bot; j<= top; j++){
+                                       k=startup+ctable[nchar[j]];
+                                       if(verify[k])break;
+                                       }
+                               } while (j <= top);
+# if DEBUG
+                       if (debug) printf(" startup will be %d\n",startup);
+# endif
+                       /* have found place */
+                       for(j = bot; j<= top; j++){
+                               k = startup + ctable[nchar[j]];
+                               if (ctable[nchar[j]]<=0)
+                                printf("j %d nchar %d ctable.nch %d\n",j,nchar[j],ctable[nchar[k]]);
+                               verify[k] = i+1;                        /* state number + 1*/
+                               advance[k] = nexts[j+1]+1;              /* state number + 1*/
+                               if(yytop < k) yytop = k;
+                               }
+                       }
+               else {
+                       do {
+                               ++startup;
+                               if(startup > outsize - ZCH)
+                                       error("output table overflow");
+                               for(j = bot; j<= top; j++){
+                                       k = startup + nchar[j];
+                                       if(verify[k])break;
+                                       }
+                               } while (j <= top);
+                       /* have found place */
+# if DEBUG
+       if (debug) printf(" startup going to be %d\n", startup);
+# endif
+                       for(j = bot; j<= top; j++){
+                               k = startup + nchar[j];
+                               verify[k] = i+1;                        /* state number + 1*/
+                               advance[k] = nexts[j+1]+1;              /* state number + 1*/
+                               if(yytop < k) yytop = k;
+                               }
+                       }
+               stoff[i] = startup;
+               }
+
+       /* stoff[i] = offset into verify, advance for trans for state i */
+       /* put out yywork */
+       if(ratfor){
+               fprintf(fout, "define YYTOPVAL %d\n", yytop);
+               rprint(verify,"verif",yytop+1);
+               rprint(advance,"advan",yytop+1);
+               shiftr(stoff, stnum); 
+               rprint(stoff,"stoff",stnum+1);
+               shiftr(sfall, stnum); upone(sfall, stnum+1);
+               rprint(sfall,"sfall",stnum+1);
+               bprint(extra,"extra",casecount+1);
+               bprint(match,"match",NCH);
+               shiftr(atable, stnum);
+               rprint(atable,"atable",stnum+1);
+               return;
+               }
+       fprintf(fout,"# define YYTYPE %s\n",stnum+1 > NCH ? "int" : "char");
+       fprintf(fout,"struct yywork { YYTYPE verify, advance; } yycrank[] ={\n");
+       for(i=0;i<=yytop;i+=4){
+               for(j=0;j<4;j++){
+                       k = i+j;
+                       if(verify[k])
+                               fprintf(fout,"%d,%d,\t",verify[k],advance[k]);
+                       else
+                               fprintf(fout,"0,0,\t");
+                       }
+               putc('\n',fout);
+               }
+       fprintf(fout,"0,0};\n");
+
+       /* put out yysvec */
+
+       fprintf(fout,"struct yysvf yysvec[] ={\n");
+       fprintf(fout,"0,\t0,\t0,\n");
+       for(i=0;i<=stnum;i++){  /* for each state */
+               if(cpackflg[i])stoff[i] = -stoff[i];
+               fprintf(fout,"yycrank+%d,\t",stoff[i]);
+               if(sfall[i] != -1)
+                       fprintf(fout,"yysvec+%d,\t", sfall[i]+1);       /* state + 1 */
+               else fprintf(fout,"0,\t\t");
+               if(atable[i] != -1)
+                       fprintf(fout,"yyvstop+%d,",atable[i]);
+               else fprintf(fout,"0,\t");
+# ifdef DEBUG
+               fprintf(fout,"\t\t/* state %d */",i);
+# endif
+               putc('\n',fout);
+               }
+       fprintf(fout,"0,\t0,\t0};\n");
+
+       /* put out yymatch */
+       
+       fprintf(fout,"struct yywork *yytop = yycrank+%d;\n",yytop);
+       fprintf(fout,"struct yysvf *yybgin = yysvec+1;\n");
+       if(optim){
+               fprintf(fout,"char yymatch[] ={\n");
+               if (chset==0) /* no chset, put out in normal order */
+                       {
+                       for(i=0; i<NCH; i+=8){
+                               for(j=0; j<8; j++){
+                                       int fbch;
+                                       fbch = match[i+j];
+                                       if(printable(fbch) && fbch != '\'' && fbch != '\\')
+                                               fprintf(fout,"'%c' ,",fbch);
+                                       else fprintf(fout,"0%-3o,",fbch);
+                                       }
+                               putc('\n',fout);
+                               }
+                       }
+               else
+                       {
+                       int *fbarr;
+                       fbarr = myalloc(2*NCH, sizeof(*fbarr));
+                       if (fbarr==0)
+                               error("No space for char table reverse",0);
+                       for(i=0; i<ZCH; i++)
+                               fbarr[i]=0;
+                       for(i=0; i<NCH; i++)
+                               fbarr[ctable[i]] = ctable[match[i]];
+                       for(i=0; i<ZCH; i+=8)
+                               {
+                               for(j=0; j<8; j++)
+                                       fprintf(fout, "0%-3o,",fbarr[i+j]);
+                               putc('\n',fout);
+                               }
+                       cfree(fbarr, 2*NCH, 1);
+                       }
+               fprintf(fout,"0};\n");
+               }
+       /* put out yyextra */
+       fprintf(fout,"char yyextra[] ={\n");
+       for(i=0;i<casecount;i+=8){
+               for(j=0;j<8;j++)
+                       fprintf(fout, "%d,", i+j<NACTIONS ?
+                               extra[i+j] : 0);
+               putc('\n',fout);
+               }
+       fprintf(fout,"0};\n");
+       return;
+       }
+rprint(a,s,n)
+  char *s;
+  int *a, n; {
+       register int i;
+       fprintf(fout,"block data\n");
+       fprintf(fout,"common /L%s/ %s\n",s,s);
+       fprintf(fout,"define S%s %d\n",s,n);
+       fprintf(fout,"integer %s (S%s)\n",s,s);
+       for(i=1; i<=n; i++)
+               {
+               if (i%8==1) fprintf(fout, "data ");
+               fprintf(fout, "%s (%d)/%d/",s,i,a[i]);
+               fprintf(fout, (i%8 && i<n) ? ", " : "\n");
+               }
+       fprintf(fout,"end\n");
+       }
+shiftr(a, n)
+       int *a;
+{
+int i;
+for(i=n; i>=0; i--)
+       a[i+1]=a[i];
+}
+upone(a,n)
+       int *a;
+{
+int i;
+for(i=0; i<=n ; i++)
+       a[i]++;
+}
+bprint(a,s,n)
+ char *s,  *a;
+ int  n; {
+       register int i, j, k;
+       fprintf(fout,"block data\n");
+       fprintf(fout,"common /L%s/ %s\n",s,s);
+       fprintf(fout,"define S%s %d\n",s,n);
+       fprintf(fout,"integer %s (S%s)\n",s,s);
+       for(i=1;i<n;i+=8){
+               fprintf(fout,"data %s (%d)/%d/",s,i,a[i]);
+               for(j=1;j<8;j++){
+                       k = i+j;
+                       if(k < n)fprintf(fout,", %s (%d)/%d/",s,k,a[k]);
+                       }
+               putc('\n',fout);
+               }
+       fprintf(fout,"end\n");
+       }
+# ifdef PP
+padd(array,n)
+  int **array;
+  int n; {
+       register int i, *j, k;
+       array[n] = nxtpos;
+       if(count == 0){
+               *nxtpos++ = 0;
+               return;
+               }
+       for(i=tptr-1;i>=0;i--){
+               j = array[i];
+               if(j && *j++ == count){
+                       for(k=0;k<count;k++)
+                               if(!tmpstat[*j++])break;
+                       if(k >= count){
+                               array[n] = array[i];
+                               return;
+                               }
+                       }
+               }
+       add(array,n);
+       return;
+       }
+# endif
diff --git a/usr/src/usr.bin/neqn/Makefile b/usr/src/usr.bin/neqn/Makefile
new file mode 100644 (file)
index 0000000..19b0b5c
--- /dev/null
@@ -0,0 +1,34 @@
+CFLAGS=-O -DNEQN -d2
+YFLAGS=-d
+
+SOURCE = e.y e.h diacrit.c eqnbox.c font.c fromto.c funny.c glob.c integral.c \
+ io.c lex.c lookup.c mark.c matrix.c move.c over.c paren.c \
+ pile.c shift.c size.c sqrt.c text.c
+
+FILES = e.o diacrit.o eqnbox.o font.o fromto.o funny.o glob.o integral.o \
+ io.o lex.o lookup.o mark.o matrix.o move.o over.o paren.o \
+ pile.o shift.o size.o sqrt.o text.o
+
+neqn:  $(FILES)
+       cc $(CFLAGS) $(FILES) -o neqn
+
+e.c:   e.def
+
+e.def: e.y
+       yacc -d e.y
+       mv y.tab.c e.c
+       mv y.tab.h e.def
+
+$(FILES):      e.h e.def
+install: neqn
+       install -s neqn $(DESTDIR)/usr/bin
+
+clean:
+       rm -f *.o e.c e.def
+
+
+list:
+       pr TODO $(SOURCE) makefile
+
+lint:  y.tab.c
+       lint -spb *.c
diff --git a/usr/src/usr.bin/neqn/diacrit.c b/usr/src/usr.bin/neqn/diacrit.c
new file mode 100644 (file)
index 0000000..d38d24d
--- /dev/null
@@ -0,0 +1,44 @@
+# include "e.h"
+# include "e.def"
+
+diacrit(p1, type) int p1, type; {
+       int c, t;
+
+       c = oalloc();
+       t = oalloc();
+       nrwid(p1, ps, p1);
+       printf(".nr 10 %du\n", max(eht[p1]-ebase[p1]-VERT(2),0));
+       switch(type) {
+               case VEC:       /* vec */
+               case DYAD:      /* dyad */
+                       printf(".ds %d \\v'-1'_\\v'1'\n", c);
+                       break;
+               case HAT:
+                       printf(".ds %d ^\n", c);
+                       break;
+               case TILDE:
+                       printf(".ds %d ~\n", c);
+                       break;
+               case DOT:
+                       printf(".ds %d \\v'-1'.\\v'1'\n", c);
+                       break;
+               case DOTDOT:
+                       printf(".ds %d \\v'-1'..\\v'1'\n", c);
+                       break;
+               case BAR:
+                       printf(".ds %d \\v'-1'\\l'\\n(%du'\\v'1'\n", 
+                               c, p1);
+                       break;
+               case UNDER:
+                       printf(".ds %d \\l'\\n(%du'\n", c, p1);
+                       break;
+               }
+       nrwid(c, ps, c);
+       printf(".as %d \\h'-\\n(%du-\\n(%du/2u'\\v'0-\\n(10u'\\*(%d", 
+               p1, p1, c, c);
+       printf("\\v'\\n(10u'\\h'-\\n(%du+\\n(%du/2u'\n", c, p1);
+       if (type != UNDER)
+               eht[p1] += VERT(1);
+       if (dbg) printf(".\tdiacrit: %c over S%d, h=%d, b=%d\n", type, p1, eht[p1], ebase[p1]);
+       ofree(c); ofree(t);
+}
diff --git a/usr/src/usr.bin/neqn/e.h b/usr/src/usr.bin/neqn/e.h
new file mode 100644 (file)
index 0000000..4722f6b
--- /dev/null
@@ -0,0 +1,42 @@
+#include <stdio.h>
+
+#define        FATAL   1
+#define        ROM     '1'
+#define        ITAL    '1'
+#define        BLD     '1'
+
+#define        VERT(n) (20 * (n))
+#define        EFFPS(p)        ((p) >= 6 ? (p) : 6)
+
+extern int     dbg;
+extern int     ct;
+extern int     lp[];
+extern int     used[]; /* available registers */
+extern int     ps;     /* dflt init pt size */
+extern int     deltaps;        /* default change in ps */
+extern int     gsize;  /* global size */
+extern int     gfont;  /* global font */
+extern int     ft;     /* dflt font */
+extern FILE    *curfile;       /* current input file */
+extern int     ifile;  /* input file number */
+extern int     linect; /* line number in current file */
+extern int     eqline; /* line where eqn started */
+extern int     svargc;
+extern char    **svargv;
+extern int     eht[];
+extern int     ebase[];
+extern int     lfont[];
+extern int     rfont[];
+extern int     yyval;
+extern int     *yypv;
+extern int     yylval;
+extern int     eqnreg, eqnht;
+extern int     lefteq, righteq;
+extern int     lastchar;       /* last character read by lex */
+extern int     markline;       /* 1 if this EQ/EN contains mark or lineup */
+
+typedef struct s_tbl {
+       char    *name;
+       char    *defn;
+       struct s_tbl *next;
+} tbl;
diff --git a/usr/src/usr.bin/neqn/e.y b/usr/src/usr.bin/neqn/e.y
new file mode 100644 (file)
index 0000000..f294e59
--- /dev/null
@@ -0,0 +1,166 @@
+%{#
+#include "e.h"
+#
+int    fromflg;
+%}
+%term  CONTIG QTEXT SPACE THIN TAB
+%term  MATRIX LCOL CCOL RCOL COL
+%term  MARK LINEUP
+%term  SUM INT PROD UNION INTER
+%term  LPILE PILE CPILE RPILE ABOVE
+%term  DEFINE TDEFINE NDEFINE DELIM GSIZE GFONT INCLUDE
+%right FROM TO
+%left  OVER SQRT
+%right SUP SUB
+%right SIZE FONT ROMAN ITALIC BOLD FAT
+%right UP DOWN BACK FWD
+%left  LEFT RIGHT
+%right DOT DOTDOT HAT TILDE BAR UNDER VEC DYAD
+
+%%
+
+stuff  : eqn   { putout($1); }
+       | error { error(!FATAL, "syntax error"); }
+       |       { eqnreg = 0; }
+       ;
+
+eqn    : box
+       | eqn box       { eqnbox($1, $2, 0); }
+       | eqn lineupbox { eqnbox($1, $2, 1); }
+       | LINEUP        { lineup(0); }
+       ;
+
+lineupbox: LINEUP box  { $$ = $2; lineup(1); }
+       ;
+
+matrix : MATRIX        { $$ = ct; } ;
+
+collist        : column
+       | collist column
+       ;
+
+column : lcol '{' list '}'     { column('L', $1); }
+       | ccol '{' list '}'     { column('C', $1); }
+       | rcol '{' list '}'     { column('R', $1); }
+       | col '{' list '}'      { column('-', $1); }
+       ;
+
+lcol   : LCOL          { $$ = ct++; } ;
+ccol   : CCOL          { $$ = ct++; } ;
+rcol   : RCOL          { $$ = ct++; } ;
+col    : COL           { $$ = ct++; } ;
+
+sbox   : sup box       %prec SUP       { $$ = $2; }
+       ;
+
+tbox   : to box        %prec TO        { $$ = $2; }
+       |               %prec FROM      { $$ = 0; }
+       ;
+
+box    : box OVER box  { boverb($1, $3); }
+       | MARK box      { mark($2); }
+       | size box      %prec SIZE      { size($1, $2); }
+       | font box      %prec FONT      { font($1, $2); }
+       | FAT box       { fatbox($2); }
+       | SQRT box      { sqrt($2); }
+       | lpile '{' list '}'    { lpile('L', $1, ct); ct = $1; }
+       | cpile '{' list '}'    { lpile('C', $1, ct); ct = $1; }
+       | rpile '{' list '}'    { lpile('R', $1, ct); ct = $1; }
+       | pile '{' list '}'     { lpile('-', $1, ct); ct = $1; }
+       | box sub box sbox      %prec SUB       { shift2($1, $3, $4); }
+       | box sub box           %prec SUB       { bshiftb($1, $2, $3); }
+       | box sup box           %prec SUP       { bshiftb($1, $2, $3); }
+       | int sub box sbox      %prec SUB       { integral($1, $3, $4); }
+       | int sub box           %prec SUB       { integral($1, $3, 0); }
+       | int sup box           %prec SUP       { integral($1, 0, $3); }
+       | int                                   { integral($1, 0, 0); }
+       | left eqn right        { paren($1, $2, $3); }
+       | pbox
+       | box from box tbox     %prec FROM      { fromto($1, $3, $4); fromflg=0; }
+       | box to box    %prec TO        { fromto($1, 0, $3); }
+       | box diacrit   { diacrit($1, $2); }
+       | fwd box       %prec UP        { move(FWD, $1, $2); }
+       | up box        %prec UP        { move(UP, $1, $2); }
+       | back box      %prec UP        { move(BACK, $1, $2); }
+       | down box      %prec UP        { move(DOWN, $1, $2); }
+       | matrix '{' collist '}'        { matrix($1); }
+       ;
+
+int    : INT   { setintegral(); }
+       ;
+
+fwd    : FWD text      { $$ = atoi((char *) $1); } ;
+up     : UP text       { $$ = atoi((char *) $1); } ;
+back   : BACK text     { $$ = atoi((char *) $1); } ;
+down   : DOWN text     { $$ = atoi((char *) $1); } ;
+
+diacrit        : HAT   { $$ = HAT; }
+       | VEC   { $$ = VEC; }
+       | DYAD  { $$ = DYAD; }
+       | BAR   { $$ = BAR; }
+       | UNDER { $$ = UNDER; } /* under bar */
+       | DOT   { $$ = DOT; }
+       | TILDE { $$ = TILDE; }
+       | DOTDOT        { $$ = DOTDOT; } /* umlaut = double dot */
+       ;
+
+from   : FROM  { $$=ps; ps -= 3; fromflg = 1;
+               if(dbg)printf(".\tfrom: old ps %d, new ps %d, fflg %d\n", $$, ps, fromflg);
+               }
+       ;
+
+to     : TO    { $$=ps; if(fromflg==0)ps -= 3; 
+                       if(dbg)printf(".\tto: old ps %d, new ps %d\n", $$, ps);
+               }
+       ;
+
+left   : LEFT text     { $$ = ((char *)$2)[0]; }
+       | LEFT '{'      { $$ = '{'; }
+       ;
+
+right  : RIGHT text    { $$ = ((char *)$2)[0]; }
+       | RIGHT '}'     { $$ = '}'; }
+       |               { $$ = 0; }
+       ;
+
+list   : eqn   { lp[ct++] = $1; }
+       | list ABOVE eqn        { lp[ct++] = $3; }
+       ;
+
+lpile  : LPILE { $$ = ct; } ;
+cpile  : CPILE { $$ = ct; } ;
+pile   : PILE  { $$ = ct; } ;
+rpile  : RPILE { $$ = ct; } ;
+
+size   : SIZE text     { $$ = ps; setsize((char *) $2); }
+       ;
+
+font   : ROMAN         { setfont(ROM); }
+       | ITALIC        { setfont(ITAL); }
+       | BOLD          { setfont(BLD); }
+       | FONT text     { setfont(((char *)$2)[0]); }
+       ;
+
+sub    : SUB   { shift(SUB); }
+       ;
+
+sup    : SUP   { shift(SUP); }
+       ;
+
+pbox   : '{' eqn '}'   { $$ = $2; }
+       | QTEXT         { text(QTEXT, (char *) $1); }
+       | CONTIG        { text(CONTIG, (char *) $1); }
+       | SPACE         { text(SPACE, 0); }
+       | THIN          { text(THIN, 0); }
+       | TAB           { text(TAB, 0); }
+       | SUM           { funny(SUM); }
+       | PROD          { funny(PROD); }
+       | UNION         { funny(UNION); }
+       | INTER         { funny(INTER); }       /* intersection */
+       ;
+
+text   : CONTIG
+       | QTEXT
+       ;
+
+%%
diff --git a/usr/src/usr.bin/neqn/eqnbox.c b/usr/src/usr.bin/neqn/eqnbox.c
new file mode 100644 (file)
index 0000000..2aea8da
--- /dev/null
@@ -0,0 +1,25 @@
+# include "e.h"
+
+eqnbox(p1, p2, lu) {
+       int b, h;
+       char *sh;
+
+       yyval = p1;
+       b = max(ebase[p1], ebase[p2]);
+       eht[yyval] = h = b + max(eht[p1]-ebase[p1], 
+               eht[p2]-ebase[p2]);
+       ebase[yyval] = b;
+       if(dbg)printf(".\te:eb: S%d <- S%d S%d; b=%d, h=%d\n", 
+               yyval, p1, p2, b, h);
+       if (rfont[p1] == ITAL && lfont[p2] == ROM)
+               sh = "\\|";
+       else
+               sh = "";
+       if (lu) {
+               printf(".nr %d \\w'\\s%d\\*(%d%s'\n", p1, ps, p1, sh);
+               printf(".ds %d \\h'|\\n(97u-\\n(%du'\\*(%d\n", p1, p1, p1);
+       }
+       printf(".as %d \"%s\\*(%d\n", yyval, sh, p2);
+       rfont[p1] = rfont[p2];
+       ofree(p2);
+}
diff --git a/usr/src/usr.bin/neqn/font.c b/usr/src/usr.bin/neqn/font.c
new file mode 100644 (file)
index 0000000..e4e026e
--- /dev/null
@@ -0,0 +1,59 @@
+# include "e.h"
+
+setfont(ch1) char ch1; {
+       /* use number '1', '2', '3' for roman, italic, bold */
+       yyval = ft;
+       if (ch1 == 'r' || ch1 == 'R')
+               ft = ROM;
+       else if (ch1 == 'i' || ch1 == 'I')
+               ft = ITAL;
+       else if (ch1 == 'b' || ch1 == 'B')
+               ft = BLD;
+       else
+               ft = ch1;
+       printf(".ft %c\n", ft);
+       if(dbg)printf(".\tsetfont %c\n", ft);
+}
+
+font(p1, p2) int p1, p2; {
+               /* old font in p1, new in ft */
+       yyval = p2;
+       lfont[yyval] = rfont[yyval] = ft==ITAL ? ITAL : ROM;
+       if(dbg)printf(".\tb:fb: S%d <- \\f%c S%d \\f%c b=%d,h=%d,lf=%c,rf=%c\n", 
+               yyval, ft, p2, p1, ebase[yyval], eht[yyval], lfont[yyval], rfont[yyval]);
+       printf(".ds %d \\f%c\\*(%d\\f%c\n", 
+               yyval, ft, p2, p1);
+       ft = p1;
+       printf(".ft %c\n", ft);
+}
+
+fatbox(p) int p; {
+       int sh;
+
+       yyval = p;
+       sh = ps / 4;
+       nrwid(p, ps, p);
+       printf(".ds %d \\*(%d\\h'-\\n(%du+%du'\\*(%d\n", p, p, p, sh, p);
+       if(dbg)printf(".\tfat %d, sh=%d\n", p, sh);
+}
+
+globfont() {
+       char temp[20];
+
+       getstr(temp, 20);
+       yyval = eqnreg = 0;
+       gfont = temp[0];
+       switch (gfont) {
+       case 'r': case 'R':
+               gfont = '1';
+               break;
+       case 'i': case 'I':
+               gfont = '2';
+               break;
+       case 'b': case 'B':
+               gfont = '3';
+               break;
+       }
+       printf(".ft %c\n", gfont);
+       ft = gfont;
+}
diff --git a/usr/src/usr.bin/neqn/fromto.c b/usr/src/usr.bin/neqn/fromto.c
new file mode 100644 (file)
index 0000000..d792d1e
--- /dev/null
@@ -0,0 +1,45 @@
+# include "e.h"
+
+fromto(p1, p2, p3) int p1, p2, p3; {
+       int b, h1, b1, pss;
+       yyval = oalloc();
+       lfont[yyval] = rfont[yyval] = 0;
+       h1 = eht[yyval] = eht[p1];
+       b1 = ebase[p1];
+       b = 0;
+       pss = EFFPS(ps);
+       ps += 3;
+       nrwid(p1, ps, p1);
+       printf(".nr %d \\n(%d\n", yyval, p1);
+       if( p2>0 ) {
+               nrwid(p2, pss, p2);
+               printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, yyval, yyval, p2);
+               eht[yyval] += eht[p2];
+               b = eht[p2];
+       }
+       if( p3>0 ) {
+               nrwid(p3, pss, p3);
+               printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p3, yyval, yyval, p3);
+               eht[yyval] += eht[p3];
+       }
+       printf(".ds %d ", yyval);       /* bottom of middle box */
+       if( p2>0 ) {
+               printf("\\v'%du'\\h'\\n(%du-\\n(%du/2u'\\s%d\\*(%d\\s%d", 
+                       eht[p2]-ebase[p2]+b1, yyval, p2, pss, p2, EFFPS(ps));
+               printf("\\h'-\\n(%du-\\n(%du/2u'\\v'%du'\\\n", 
+                       yyval, p2, -(eht[p2]-ebase[p2]+b1));
+       }
+       printf("\\h'\\n(%du-\\n(%du/2u'\\*(%d\\h'\\n(%du-\\n(%du+2u/2u'\\\n", 
+               yyval, p1, p1, yyval, p1);
+       if( p3>0 ) {
+               printf("\\v'%du'\\h'-\\n(%du-\\n(%du/2u'\\s%d\\*(%d\\s%d\\h'\\n(%du-\\n(%du/2u'\\v'%du'\\\n", 
+                       -(h1-b1+ebase[p3]), yyval, p3, pss, p3, EFFPS(ps), yyval, p3, (h1-b1+ebase[p3]));
+       }
+       printf("\n");
+       ebase[yyval] = b + b1;
+       if(dbg)printf(".\tfrom to: S%d <- %d f %d t %d; h=%d b=%d\n", 
+               yyval, p1, p2, p3, eht[yyval], ebase[yyval]);
+       ofree(p1);
+       if( p2>0 ) ofree(p2);
+       if( p3>0 ) ofree(p3);
+}
diff --git a/usr/src/usr.bin/neqn/funny.c b/usr/src/usr.bin/neqn/funny.c
new file mode 100644 (file)
index 0000000..1b93818
--- /dev/null
@@ -0,0 +1,26 @@
+# include "e.h"
+# include "e.def"
+
+funny(n) int n; {
+       char *f;
+
+       yyval = oalloc();
+       switch(n) {
+       case SUM:
+               f = "\\(*S"; break;
+       case UNION:
+               f = "\\(cu"; break;
+       case INTER:     /* intersection */
+               f = "\\(ca"; break;
+       case PROD:
+               f = "\\(*P"; break;
+       default:
+               error(FATAL, "funny type %d in funny", n);
+       }
+       printf(".ds %d %s\n", yyval, f);
+       eht[yyval] = VERT(2);
+       ebase[yyval] = 0;
+       if(dbg)printf(".\tfunny: S%d <- %s; h=%d b=%d\n", 
+               yyval, f, eht[yyval], ebase[yyval]);
+       lfont[yyval] = rfont[yyval] = ROM;
+}
diff --git a/usr/src/usr.bin/neqn/glob.c b/usr/src/usr.bin/neqn/glob.c
new file mode 100644 (file)
index 0000000..834a33f
--- /dev/null
@@ -0,0 +1,27 @@
+#include "e.h"
+
+int    dbg;    /* debugging print if non-zero */
+int    lp[80]; /* stack for things like piles and matrices */
+int    ct;     /* pointer to lp */
+int    used[100];      /* available registers */
+int    ps;     /* default init point size */
+int    deltaps = 3;    /* default change in ps */
+int    gsize   = 10;   /* default initial point size */
+int    gfont   = ITAL; /* italic */
+int    ft;     /* default font */
+FILE   *curfile;       /* current input file */
+int    ifile;
+int    linect; /* line number in file */
+int    eqline; /* line where eqn started */
+int    svargc;
+char   **svargv;
+int    eht[100];
+int    ebase[100];
+int    lfont[100];
+int    rfont[100];
+int    eqnreg; /* register where final string appears */
+int    eqnht;  /* inal height of equation */
+int    lefteq  = '\0'; /* left in-line delimiter */
+int    righteq = '\0'; /* right in-line delimiter */
+int    lastchar;       /* last character read by lex */
+int    markline        = 0;    /* 1 if this EQ/EN contains mark or lineup */
diff --git a/usr/src/usr.bin/neqn/integral.c b/usr/src/usr.bin/neqn/integral.c
new file mode 100644 (file)
index 0000000..1247250
--- /dev/null
@@ -0,0 +1,31 @@
+# include "e.h"
+# include "e.def"
+
+integral(p, p1, p2) {
+#ifndef        NEQN
+       if (p1 != 0)
+               printf(".ds %d \\h'-0.4m'\\v'0.4m'\\*(%d\\v'-0.4m'\n", p1, p1);
+       if (p2 != 0)
+               printf(".ds %d \\v'-0.3m'\\*(%d\\v'0.3m'\n", p2, p2);
+#endif
+       if (p1 != 0 && p2 != 0)
+               shift2(p, p1, p2);
+       else if (p1 != 0)
+               bshiftb(p, SUB, p1);
+       else if (p2 != 0)
+               bshiftb(p, SUP, p2);
+       if(dbg)printf(".\tintegral: S%d; h=%d b=%d\n", 
+               p, eht[p], ebase[p]);
+       lfont[p] = ROM;
+}
+
+setintegral() {
+       char *f;
+
+       yyval = oalloc();
+       f = "\\(is";
+       printf(".ds %d %s\n", yyval, f);
+       eht[yyval] = VERT(2);
+       ebase[yyval] = 0;
+       lfont[yyval] = rfont[yyval] = ROM;
+}
diff --git a/usr/src/usr.bin/neqn/io.c b/usr/src/usr.bin/neqn/io.c
new file mode 100644 (file)
index 0000000..541d31d
--- /dev/null
@@ -0,0 +1,195 @@
+# include "e.h"
+#define        MAXLINE 1200    /* maximum input line */
+
+char   in[MAXLINE];    /* input buffer */
+int    eqnexit();
+int noeqn;
+
+main(argc,argv) int argc; char *argv[];{
+
+       eqnexit(eqn(argc, argv));
+}
+
+eqnexit(n) {
+#ifdef gcos
+       if (n)
+               fprintf(stderr, "run terminated due to eqn error\n");
+       exit(0);
+#endif
+       exit(n);
+}
+
+eqn(argc,argv) int argc; char *argv[];{
+       int i, type;
+
+       setfile(argc,argv);
+       init_tbl();     /* install keywords in tables */
+       while ((type=getline(in)) != EOF) {
+               eqline = linect;
+               if (in[0]=='.' && in[1]=='E' && in[2]=='Q') {
+                       for (i=11; i<100; used[i++]=0);
+                       printf("%s",in);
+                       printf(".nr 99 \\n(.s\n.nr 98 \\n(.f\n");
+                       markline = 0;
+                       init();
+                       yyparse();
+                       if (eqnreg>0) {
+                               printf(".nr %d \\w'\\*(%d'\n", eqnreg, eqnreg);
+                               /* printf(".if \\n(%d>\\n(.l .tm too-long eqn, file %s, between lines %d-%d\n", */
+                               /*      eqnreg, svargv[ifile], eqline, linect); */
+                               printf(".nr MK %d\n", markline);        /* for -ms macros */
+                               printf(".if %d>\\n(.v .ne %du\n", eqnht, eqnht);
+                               printf(".rn %d 10\n", eqnreg);
+                               if(!noeqn)printf("\\*(10\n");
+                       }
+                       printf(".ps \\n(99\n.ft \\n(98\n");
+                       printf(".EN");
+                       if (lastchar == EOF) {
+                               putchar('\n');
+                               break;
+                       }
+                       if (putchar(lastchar) != '\n')
+                               while (putchar(gtc()) != '\n');
+               }
+               else if (type == lefteq)
+                       inline();
+               else
+                       printf("%s",in);
+       }
+       return(0);
+}
+
+getline(s) register char *s; {
+       register c;
+       while((*s++=c=gtc())!='\n' && c!=EOF && c!=lefteq)
+               if (s >= in+MAXLINE) {
+                       error( !FATAL, "input line too long: %.20s\n", in);
+                       in[MAXLINE] = '\0';
+                       break;
+               }
+       if (c==lefteq)
+               s--;
+       *s++ = '\0';
+       return(c);
+}
+
+inline() {
+       int ds;
+
+       printf(".nr 99 \\n(.s\n.nr 98 \\n(.f\n");
+       ds = oalloc();
+       printf(".rm %d \n", ds);
+       do{
+               if (*in)
+                       printf(".as %d \"%s\n", ds, in);
+               init();
+               yyparse();
+               if (eqnreg > 0) {
+                       printf(".as %d \\*(%d\n", ds, eqnreg);
+                       ofree(eqnreg);
+               }
+               printf(".ps \\n(99\n.ft \\n(98\n");
+       } while (getline(in) == lefteq);
+       if (*in)
+               printf(".as %d \"%s", ds, in);
+       printf(".ps \\n(99\n.ft \\n(98\n");
+       printf("\\*(%d\n", ds);
+       ofree(ds);
+}
+
+putout(p1) int p1; {
+       extern int gsize, gfont;
+       int before, after;
+       if(dbg)printf(".\tanswer <- S%d, h=%d,b=%d\n",p1, eht[p1], ebase[p1]);
+       eqnht = eht[p1];
+       printf(".ds %d \\x'0'", p1);
+       /* suppposed to leave room for a subscript or superscript */
+       before = eht[p1] - ebase[p1] - VERT(3); /* 3 = 1.5 lines */
+       if (before > 0)
+               printf("\\x'0-%du'", before);
+       printf("\\f%c\\s%d\\*(%d%s\\s\\n(99\\f\\n(98",
+               gfont, gsize, p1, rfont[p1] == ITAL ? "\\|" : "");
+       after = ebase[p1] - VERT(1);
+       if (after > 0)
+               printf("\\x'%du'", after);
+       putchar('\n');
+       eqnreg = p1;
+}
+
+max(i,j) int i,j; {
+       return (i>j ? i : j);
+}
+
+oalloc() {
+       int i;
+       for (i=11; i<100; i++)
+               if (used[i]++ == 0) return(i);
+       error( FATAL, "no eqn strings left", i);
+       return(0);
+}
+
+ofree(n) int n; {
+       used[n] = 0;
+}
+
+setps(p) int p; {
+       printf(".ps %d\n", EFFPS(p));
+}
+
+nrwid(n1, p, n2) int n1, p, n2; {
+       printf(".nr %d \\w'\\s%d\\*(%d'\n", n1, EFFPS(p), n2);
+}
+
+setfile(argc, argv) int argc; char *argv[]; {
+       static char *nullstr = "-";
+
+       svargc = --argc;
+       svargv = argv;
+       while (svargc > 0 && svargv[1][0] == '-') {
+               switch (svargv[1][1]) {
+
+               case 'd': lefteq=svargv[1][2]; righteq=svargv[1][3]; break;
+               case 's': gsize = atoi(&svargv[1][2]); break;
+               case 'p': deltaps = atoi(&svargv[1][2]); break;
+               case 'f': gfont = svargv[1][2]; break;
+               case 'e': noeqn++; break;
+               default: dbg = 1;
+               }
+               svargc--;
+               svargv++;
+       }
+       ifile = 1;
+       linect = 1;
+       if (svargc <= 0) {
+               curfile = stdin;
+               svargv[1] = nullstr;
+       }
+       else if ((curfile = fopen(svargv[1], "r")) == NULL)
+               error( FATAL,"can't open file %s", svargv[1]);
+}
+
+yyerror() {;}
+
+init() {
+       ct = 0;
+       ps = gsize;
+       ft = gfont;
+       setps(ps);
+       printf(".ft %c\n", ft);
+}
+
+error(fatal, s1, s2) int fatal; char *s1, *s2; {
+       if (fatal>0)
+               printf("eqn fatal error: ");
+       printf(s1,s2);
+       printf("\nfile %s, between lines %d and %d\n",
+                svargv[ifile], eqline, linect);
+       fprintf(stderr, "eqn: ");
+       if (fatal>0)
+               fprintf(stderr, "fatal error: ");
+       fprintf(stderr, s1, s2);
+       fprintf(stderr, "\nfile %s, between lines %d and %d\n",
+                svargv[ifile], eqline, linect);
+       if (fatal > 0)
+               eqnexit(1);
+}
diff --git a/usr/src/usr.bin/neqn/lex.c b/usr/src/usr.bin/neqn/lex.c
new file mode 100644 (file)
index 0000000..19860a2
--- /dev/null
@@ -0,0 +1,211 @@
+#include "e.h"
+#include "e.def"
+
+#define        SSIZE   400
+char   token[SSIZE];
+int    sp;
+#define        putbak(c)       *ip++ = c;
+#define        PUSHBACK        300     /* maximum pushback characters */
+char   ibuf[PUSHBACK+SSIZE];   /* pushback buffer for definitions, etc. */
+char   *ip     = ibuf;
+
+gtc() {
+  loop:
+       if (ip > ibuf)
+               return(*--ip);  /* already present */
+       lastchar = getc(curfile);
+       if (lastchar=='\n')
+               linect++;
+       if (lastchar != EOF)
+               return(lastchar);
+       if (++ifile > svargc) {
+               return(EOF);
+       }
+       fclose(curfile);
+       linect = 1;
+       if ((curfile=fopen(svargv[ifile], "r")) != NULL)
+               goto loop;
+       error(FATAL, "can't open file %s", svargv[ifile]);
+       return(EOF);
+}
+
+pbstr(str)
+register char *str;
+{
+       register char *p;
+
+       p = str;
+       while (*p++);
+       --p;
+       if (ip >= &ibuf[PUSHBACK])
+               error( FATAL, "pushback overflow");
+       while (p > str)
+               putbak(*--p);
+}
+
+yylex() {
+       register int c;
+       tbl *tp, *lookup();
+       extern tbl **keytbl, **deftbl;
+
+  beg:
+       while ((c=gtc())==' ' || c=='\n')
+               ;
+       yylval=c;
+       switch(c) {
+
+       case EOF:
+               return(EOF);
+       case '~':
+               return(SPACE);
+       case '^':
+               return(THIN);
+       case '\t':
+               return(TAB);
+       case '{':
+               return('{');
+       case '}':
+               return('}');
+       case '"':
+               for (sp=0; (c=gtc())!='"' && c != '\n'; ) {
+                       if (c == '\\')
+                               if ((c = gtc()) != '"')
+                                       token[sp++] = '\\';
+                       token[sp++] = c;
+                       if (sp>=SSIZE)
+                               error(FATAL, "quoted string %.20s... too long", token);
+               }
+               token[sp]='\0';
+               yylval = (int) &token[0];
+               if (c == '\n')
+                       error(!FATAL, "missing \" in %.20s", token);
+               return(QTEXT);
+       }
+       if (c==righteq)
+               return(EOF);
+
+       putbak(c);
+       getstr(token, SSIZE);
+       if (dbg)printf(".\tlex token = |%s|\n", token);
+       if ((tp = lookup(&deftbl, token, NULL)) != NULL) {
+               putbak(' ');
+               pbstr(tp->defn);
+               putbak(' ');
+               if (dbg)
+                       printf(".\tfound %s|=%s|\n", token, tp->defn);
+       }
+       else if ((tp = lookup(&keytbl, token, NULL)) == NULL) {
+               if(dbg)printf(".\t%s is not a keyword\n", token);
+               return(CONTIG);
+       }
+       else if (tp->defn == (char *) DEFINE || tp->defn == (char *) NDEFINE || tp->defn == (char *) TDEFINE)
+               define(tp->defn);
+       else if (tp->defn == (char *) DELIM)
+               delim();
+       else if (tp->defn == (char *) GSIZE)
+               globsize();
+       else if (tp->defn == (char *) GFONT)
+               globfont();
+       else if (tp->defn == (char *) INCLUDE)
+               include();
+       else {
+               return((int) tp->defn);
+       }
+       goto beg;
+}
+
+getstr(s, n) char *s; register int n; {
+       register int c;
+       register char *p;
+
+       p = s;
+       while ((c = gtc()) == ' ' || c == '\n')
+               ;
+       if (c == EOF) {
+               *s = 0;
+               return;
+       }
+       while (c != ' ' && c != '\t' && c != '\n' && c != '{' && c != '}'
+         && c != '"' && c != '~' && c != '^' && c != righteq) {
+               if (c == '\\')
+                       if ((c = gtc()) != '"')
+                               *p++ = '\\';
+               *p++ = c;
+               if (--n <= 0)
+                       error(FATAL, "token %.20s... too long", s);
+               c = gtc();
+       }
+       if (c=='{' || c=='}' || c=='"' || c=='~' || c=='^' || c=='\t' || c==righteq)
+               putbak(c);
+       *p = '\0';
+       yylval = (int) s;
+}
+
+cstr(s, quote, maxs) char *s; int quote; {
+       int del, c, i;
+
+       while((del=gtc()) == ' ' || del == '\t' || del == '\n');
+       if (quote)
+               for (i=0; (c=gtc()) != del && c != EOF;) {
+                       s[i++] = c;
+                       if (i >= maxs)
+                               return(1);      /* disaster */
+               }
+       else {
+               s[0] = del;
+               for (i=1; (c=gtc())!=' ' && c!= '\t' && c!='\n' && c!=EOF;) {
+                       s[i++]=c;
+                       if (i >= maxs)
+                               return(1);      /* disaster */
+               }
+       }
+       s[i] = '\0';
+       if (c == EOF)
+               error(FATAL, "Unexpected end of input at %.20s", s);
+       return(0);
+}
+
+define(type) int type; {
+       char *strsave(), *p1, *p2;
+       tbl *lookup();
+       extern tbl **deftbl;
+
+       getstr(token, SSIZE);   /* get name */
+       if (type != DEFINE) {
+               cstr(token, 1, SSIZE);  /* skip the definition too */
+               return;
+       }
+       p1 = strsave(token);
+       if (cstr(token, 1, SSIZE))
+               error(FATAL, "Unterminated definition at %.20s", token);
+       p2 = strsave(token);
+       lookup(&deftbl, p1, p2);
+       if (dbg)printf(".\tname %s defined as %s\n", p1, p2);
+}
+
+char *strsave(s)
+char *s;
+{
+       char *malloc();
+       register char *q;
+
+       q = malloc(strlen(s)+1);
+       if (q == NULL)
+               error(FATAL, "out of space in strsave on %s", s);
+       strcpy(q, s);
+       return(q);
+}
+
+include() {
+       error(!FATAL, "Include not yet implemented");
+}
+
+delim() {
+       yyval = eqnreg = 0;
+       if (cstr(token, 0, SSIZE))
+               error(FATAL, "Bizarre delimiters at %.20s", token);
+       lefteq = token[0];
+       righteq = token[1];
+       if (lefteq == 'o' && righteq == 'f')
+               lefteq = righteq = '\0';
+}
diff --git a/usr/src/usr.bin/neqn/lookup.c b/usr/src/usr.bin/neqn/lookup.c
new file mode 100644 (file)
index 0000000..aa6ea92
--- /dev/null
@@ -0,0 +1,217 @@
+# include "e.h"
+#include "e.def"
+
+#define        TBLSIZE 100
+
+tbl    *keytbl[TBLSIZE];       /* key words */
+tbl    *restbl[TBLSIZE];       /* reserved words */
+tbl    *deftbl[TBLSIZE];       /* user-defined names */
+
+struct {
+       char    *key;
+       int     keyval;
+} keyword[]    ={
+       "sub",  SUB, 
+       "sup",  SUP, 
+       ".EN",  EOF, 
+       "from",         FROM, 
+       "to",   TO, 
+       "sum",  SUM, 
+       "hat",  HAT, 
+       "vec", VEC, 
+       "dyad", DYAD, 
+       "dot",  DOT, 
+       "dotdot",       DOTDOT, 
+       "bar",  BAR, 
+       "tilde",        TILDE, 
+       "under",        UNDER, 
+       "prod",         PROD, 
+       "int",  INT, 
+       "integral",     INT, 
+       "union",        UNION, 
+       "inter",        INTER, 
+       "pile",         PILE, 
+       "lpile",        LPILE, 
+       "cpile",        CPILE, 
+       "rpile",        RPILE, 
+       "over",         OVER, 
+       "sqrt",         SQRT, 
+       "above",        ABOVE, 
+       "size",         SIZE, 
+       "font",         FONT, 
+       "fat", FAT, 
+       "roman",        ROMAN, 
+       "italic",       ITALIC, 
+       "bold",         BOLD, 
+       "left",         LEFT, 
+       "right",        RIGHT, 
+       "delim",        DELIM, 
+       "define",       DEFINE, 
+
+#ifdef NEQN    /* make ndefine synonym for define, tdefine a no-op */
+
+       "tdefine",      TDEFINE,
+       "ndefine",      DEFINE,
+
+#else          /* tdefine = define, ndefine = no-op */
+
+       "tdefine",      DEFINE, 
+       "ndefine",      NDEFINE, 
+
+#endif
+
+       "gsize",        GSIZE, 
+       ".gsize",       GSIZE, 
+       "gfont",        GFONT, 
+       "include",      INCLUDE, 
+       "up",   UP, 
+       "down",         DOWN, 
+       "fwd",  FWD, 
+       "back",         BACK, 
+       "mark",         MARK, 
+       "lineup",       LINEUP, 
+       "matrix",       MATRIX, 
+       "col",  COL, 
+       "lcol",         LCOL, 
+       "ccol",         CCOL, 
+       "rcol",         RCOL, 
+       0,      0
+};
+
+struct {
+       char    *res;
+       char    *resval;
+} resword[]    ={
+       ">=",   "\\(>=",
+       "<=",   "\\(<=",
+       "==",   "\\(==",
+       "!=",   "\\(!=",
+       "+-",   "\\(+-",
+       "->",   "\\(->",
+       "<-",   "\\(<-",
+       "inf",  "\\(if",
+       "infinity",     "\\(if",
+       "partial",      "\\(pd",
+       "half", "\\f1\\(12\\fP",
+       "prime",        "\\f1\\(fm\\fP",
+       "dollar",       "\\f1$\\fP",
+       "nothing",      "",
+       "times",        "\\(mu",
+       "del",  "\\(gr",
+       "grad", "\\(gr",
+#ifdef NEQN
+       "<<",   "<<",
+       ">>",   ">>",
+       "approx",       "~\b\\d~\\u",
+       "cdot", "\\v'-.5'.\\v'.5'",
+       "...",  "...",
+       ",...,",        ",...,",
+#else
+       "<<",   "<\\h'-.3m'<",
+       ">>",   ">\\h'-.3m'>",
+       "approx",       "\\v'-.2m'\\z\\(ap\\v'.25m'\\(ap\\v'-.05m'",
+       "cdot", "\\v'-.3m'.\\v'.3m'",
+       "...",  "\\v'-.3m'\\ .\\ .\\ .\\ \\v'.3m'",
+       ",...,",        ",\\ .\\ .\\ .\\ ,\\|",
+#endif
+
+       "alpha",        "\\(*a",
+       "beta", "\\(*b",
+       "gamma",        "\\(*g",
+       "GAMMA",        "\\(*G",
+       "delta",        "\\(*d",
+       "DELTA",        "\\(*D",
+       "epsilon",      "\\(*e",
+       "EPSILON",      "\\f1E\\fP",
+       "omega",        "\\(*w",
+       "OMEGA",        "\\(*W",
+       "lambda",       "\\(*l",
+       "LAMBDA",       "\\(*L",
+       "mu",   "\\(*m",
+       "nu",   "\\(*n",
+       "theta",        "\\(*h",
+       "THETA",        "\\(*H",
+       "phi",  "\\(*f",
+       "PHI",  "\\(*F",
+       "pi",   "\\(*p",
+       "PI",   "\\(*P",
+       "sigma",        "\\(*s",
+       "SIGMA",        "\\(*S",
+       "xi",   "\\(*c",
+       "XI",   "\\(*C",
+       "zeta", "\\(*z",
+       "iota", "\\(*i",
+       "eta",  "\\(*y",
+       "kappa",        "\\(*k",
+       "rho",  "\\(*r",
+       "tau",  "\\(*t",
+       "omicron",      "\\(*o",
+       "upsilon",      "\\(*u",
+       "UPSILON",      "\\(*U",
+       "psi",  "\\(*q",
+       "PSI",  "\\(*Q",
+       "chi",  "\\(*x",
+       "and",  "\\f1and\\fP",
+       "for",  "\\f1for\\fP",
+       "if",   "\\f1if\\fP",
+       "Re",   "\\f1Re\\fP",
+       "Im",   "\\f1Im\\fP",
+       "sin",  "\\f1sin\\fP",
+       "cos",  "\\f1cos\\fP",
+       "tan",  "\\f1tan\\fP",
+       "arc",  "\\f1arc\\fP",
+       "sinh", "\\f1sinh\\fP",
+       "coth", "\\f1coth\\fP",
+       "tanh", "\\f1tanh\\fP",
+       "cosh", "\\f1cosh\\fP",
+       "lim",  "\\f1lim\\fP",
+       "log",  "\\f1log\\fP",
+       "max",  "\\f1max\\fP",
+       "min",  "\\f1min\\fP",
+       "ln",   "\\f1ln\\fP",
+       "exp",  "\\f1exp\\fP",
+       "det",  "\\f1det\\fP",
+       0,      0
+};
+
+tbl *lookup(tblp, name, defn)  /* find name in tbl. if defn non-null, install */
+tbl **tblp;
+char *name, *defn;
+{
+       register tbl *p;
+       register int h;
+       register char *s = name;
+       char *malloc();
+
+       for (h = 0; *s != '\0'; )
+               h += *s++;
+       h %= TBLSIZE;
+
+       for (p = tblp[h]; p != NULL; p = p->next)
+               if (strcmp(name, p->name) == 0) {       /* found it */
+                       if (defn != NULL)
+                               p->defn = defn;
+                       return(p);
+               }
+       /* didn't find it */
+       if (defn == NULL)
+               return(NULL);
+       p = (tbl *) malloc(sizeof (tbl));
+       if (p == NULL)
+               error(FATAL, "out of space in lookup");
+       p->name = name;
+       p->defn = defn;
+       p->next = tblp[h];
+       tblp[h] = p;
+       return(p);
+}
+
+init_tbl()     /* initialize all tables */
+{
+       int i;
+
+       for (i = 0; keyword[i].key != NULL; i++)
+               lookup(keytbl, keyword[i].key, keyword[i].keyval);
+       for (i = 0; resword[i].res != NULL; i++)
+               lookup(restbl, resword[i].res, resword[i].resval);
+}
diff --git a/usr/src/usr.bin/neqn/mark.c b/usr/src/usr.bin/neqn/mark.c
new file mode 100644 (file)
index 0000000..6e03156
--- /dev/null
@@ -0,0 +1,17 @@
+#include "e.h"
+
+mark(p1) int p1; {
+       markline = 1;
+       printf(".ds %d \\k(97\\*(%d\n", p1, p1);
+       yyval = p1;
+       if(dbg)printf(".\tmark %d\n", p1);
+}
+
+lineup(p1) {
+       markline = 1;
+       if (p1 == 0) {
+               yyval = oalloc();
+               printf(".ds %d \\h'|\\n(97u'\n", yyval);
+       }
+       if(dbg)printf(".\tlineup %d\n", p1);
+}
diff --git a/usr/src/usr.bin/neqn/matrix.c b/usr/src/usr.bin/neqn/matrix.c
new file mode 100644 (file)
index 0000000..209e37b
--- /dev/null
@@ -0,0 +1,62 @@
+#include "e.h"
+
+column(type, p1) int type, p1; {
+       int i;
+
+       lp[p1] = ct - p1 - 1;
+       if( dbg ){
+               printf(".\t%d column of", type);
+               for( i=p1+1; i<ct; i++ )
+                       printf(" S%d", lp[i]);
+               printf(", rows=%d\n",lp[p1]);
+       }
+       lp[ct++] = type;
+}
+
+matrix(p1) int p1; {
+       int nrow, ncol, i, j, k, hb, b, val[100];
+       char *space;
+
+       space = "\\ \\ ";
+       nrow = lp[p1];  /* disaster if rows inconsistent */
+       ncol = 0;
+       for( i=p1; i<ct; i += lp[i]+2 ){
+               ncol++;
+               if(dbg)printf(".\tcolct=%d\n",lp[i]);
+       }
+       for( k=1; k<=nrow; k++ ) {
+               hb = b = 0;
+               j = p1 + k;
+               for( i=0; i<ncol; i++ ) {
+                       hb = max(hb, eht[lp[j]]-ebase[lp[j]]);
+                       b = max(b, ebase[lp[j]]);
+                       j += nrow + 2;
+               }
+               if(dbg)printf(".\trow %d: b=%d, hb=%d\n", k, b, hb);
+               j = p1 + k;
+               for( i=0; i<ncol; i++ ) {
+                       ebase[lp[j]] = b;
+                       eht[lp[j]] = b + hb;
+                       j += nrow + 2;
+               }
+       }
+       j = p1;
+       for( i=0; i<ncol; i++ ) {
+               lpile(lp[j+lp[j]+1], j+1, j+lp[j]+1);
+               val[i] = yyval;
+               j += nrow + 2;
+       }
+       yyval = oalloc();
+       eht[yyval] = eht[val[0]];
+       ebase[yyval] = ebase[val[0]];
+       lfont[yyval] = rfont[yyval] = 0;
+       if(dbg)printf(".\tmatrix S%d: r=%d, c=%d, h=%d, b=%d\n",
+               yyval,nrow,ncol,eht[yyval],ebase[yyval]);
+       printf(".ds %d \"", yyval);
+       for( i=0; i<ncol; i++ )  {
+               printf("\\*(%d%s", val[i], i==ncol-1 ? "" : space);
+               ofree(val[i]);
+       }
+       printf("\n");
+       ct = p1;
+}
diff --git a/usr/src/usr.bin/neqn/move.c b/usr/src/usr.bin/neqn/move.c
new file mode 100644 (file)
index 0000000..2f3076c
--- /dev/null
@@ -0,0 +1,18 @@
+# include "e.h"
+# include "e.def"
+
+move(dir, amt, p) int dir, amt, p; {
+       int a;
+
+       yyval = p;
+       a = VERT( (amt+49)/50 );        /* nearest number of half-lines */
+       printf(".ds %d ", yyval);
+       if( dir == FWD || dir == BACK ) /* fwd, back */
+               printf("\\h'%s%du'\\*(%d\n", (dir==BACK) ? "-" : "", a, p);
+       else if (dir == UP)
+               printf("\\v'-%du'\\*(%d\\v'%du'\n", a, p, a);
+       else if (dir == DOWN)
+               printf("\\v'%du'\\*(%d\\v'-%du'\n", a, p, a);
+       if(dbg)printf(".\tmove %d dir %d amt %d; h=%d b=%d\n", 
+               p, dir, a, eht[yyval], ebase[yyval]);
+}
diff --git a/usr/src/usr.bin/neqn/over.c b/usr/src/usr.bin/neqn/over.c
new file mode 100644 (file)
index 0000000..4625e36
--- /dev/null
@@ -0,0 +1,28 @@
+# include "e.h"
+
+boverb(p1, p2) int p1, p2; {
+       int h, b, treg, d;
+
+       treg = oalloc();
+       yyval = p1;
+       d = VERT(1);
+       h = eht[p1] + eht[p2];
+       b = eht[p2] - d;
+       if(dbg)printf(".\tb:bob: S%d <- S%d over S%d; b=%d, h=%d\n", 
+               yyval, p1, p2, b, h);
+       nrwid(p1, ps, p1);
+       nrwid(p2, ps, p2);
+       printf(".nr %d \\n(%d\n", treg, p1);
+       printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, treg, treg, p2);
+       printf(".ds %d \\v'%du'\\h'\\n(%du-\\n(%du/2u'\\*(%d\\\n", 
+               yyval, eht[p2]-ebase[p2]-d, treg, p2, p2);
+       printf("\\h'-\\n(%du-\\n(%du/2u'\\v'%du'\\*(%d\\\n", 
+               p2, p1, -eht[p2]+ebase[p2]-ebase[p1], p1);
+       printf("\\h'-\\n(%du-\\n(%du-2u/2u'\\v'%du'\\l'\\n(%du'\\v'%du'\n", 
+                treg, p1, ebase[p1], treg, d);
+       ebase[yyval] = b;
+       eht[yyval] = h;
+       lfont[yyval] = rfont[yyval] = 0;
+       ofree(p2);
+       ofree(treg);
+}
diff --git a/usr/src/usr.bin/neqn/paren.c b/usr/src/usr.bin/neqn/paren.c
new file mode 100644 (file)
index 0000000..58c91bb
--- /dev/null
@@ -0,0 +1,106 @@
+# include "e.h"
+
+paren(leftc, p1, rightc) int p1, leftc, rightc; {
+       int n, m, h1, j, b1, v;
+       h1 = eht[p1]; b1 = ebase[p1];
+       yyval = p1;
+       n = max(b1+VERT(1), h1-b1-VERT(1)) / VERT(1);
+       if( n<2 ) n = 1;
+       m = n-2;
+       if (leftc=='{' || rightc == '}') {
+               n = n%2 ? n : ++n;
+               if( n<3 ) n=3;
+               m = n-3;
+       }
+       eht[yyval] = VERT(2 * n);
+       ebase[yyval] = (n)/2 * VERT(2);
+       if (n%2 == 0)
+               ebase[yyval] -= VERT(1);
+       v = b1 - h1/2 + VERT(1);
+       printf(".ds %d \\|\\v'%du'", yyval, v);
+       switch( leftc ) {
+               case 'n':       /* nothing */
+               case '\0':
+                       break;
+               case 'f':       /* floor */
+                       if (n <= 1)
+                               printf("\\(lf");
+                       else
+                               brack(m, "\\(bv", "\\(bv", "\\(lf");
+                       break;
+               case 'c':       /* ceiling */
+                       if (n <= 1)
+                               printf("\\(lc");
+                       else
+                               brack(m, "\\(lc", "\\(bv", "\\(bv");
+                       break;
+               case '{':
+                       printf("\\b'\\(lt");
+                       for(j = 0; j < m; j += 2) printf("\\(bv");
+                       printf("\\(lk");
+                       for(j = 0; j < m; j += 2) printf("\\(bv");
+                       printf("\\(lb'");
+                       break;
+               case '(':
+                       brack(m, "\\(lt", "\\(bv", "\\(lb");
+                       break;
+               case '[':
+                       brack(m, "\\(lc", "\\(bv", "\\(lf");
+                       break;
+               case '|':
+                       brack(m, "|", "|", "|");
+                       break;
+               default:
+                       brack(m, (char *) &leftc, (char *) &leftc, (char *) &leftc);
+                       break;
+               }
+       printf("\\v'%du'\\*(%d", -v, p1);
+       if( rightc ) {
+               printf("\\|\\v'%du'", v);
+               switch( rightc ) {
+                       case 'f':       /* floor */
+                               if (n <= 1)
+                                       printf("\\(rf");
+                               else
+                                       brack(m, "\\(bv", "\\(bv", "\\(rf");
+                               break;
+                       case 'c':       /* ceiling */
+                               if (n <= 1)
+                                       printf("\\(rc");
+                               else
+                                       brack(m, "\\(rc", "\\(bv", "\\(bv");
+                               break;
+                       case '}':
+                               printf("\\b'\\(rt");
+                               for(j = 0; j< m; j += 2)printf("\\(bv");
+                               printf("\\(rk");
+                               for(j = 0; j< m; j += 2) printf("\\(bv");
+                               printf("\\(rb'");
+                               break;
+                       case ']':
+                               brack(m, "\\(rc", "\\(bv", "\\(rf");
+                               break;
+                       case ')':
+                               brack(m, "\\(rt", "\\(bv", "\\(rb");
+                               break;
+                       case '|':
+                               brack(m, "|", "|", "|");
+                               break;
+                       default:
+                               brack(m, (char *) &rightc, (char *) &rightc, (char *) &rightc);
+                               break;
+               }
+               printf("\\v'%du'", -v);
+       }
+       printf("\n");
+       if(dbg)printf(".\tcurly: h=%d b=%d n=%d v=%d l=%c, r=%c\n", 
+               eht[yyval], ebase[yyval], n, v, leftc, rightc);
+}
+
+brack(m, t, c, b) int m; char *t, *c, *b; {
+       int j;
+       printf("\\b'%s", t);
+       for( j=0; j<m; j++)
+               printf("%s", c);
+       printf("%s'", b);
+}
diff --git a/usr/src/usr.bin/neqn/pile.c b/usr/src/usr.bin/neqn/pile.c
new file mode 100644 (file)
index 0000000..c2fca93
--- /dev/null
@@ -0,0 +1,62 @@
+# include "e.h"
+
+lpile(type, p1, p2) int type, p1, p2; {
+       int bi, hi, i, gap, h, b, nlist, nlist2, mid;
+       yyval = oalloc();
+       gap = VERT(1);
+       if( type=='-' ) gap = 0;
+       nlist = p2 - p1;
+       nlist2 = (nlist+1)/2;
+       mid = p1 + nlist2 -1;
+       h = 0;
+       for( i=p1; i<p2; i++ )
+               h += eht[lp[i]];
+       eht[yyval] = h + (nlist-1)*gap;
+       b = 0;
+       for( i=p2-1; i>mid; i-- )
+               b += eht[lp[i]] + gap;
+       ebase[yyval] = (nlist%2) ? b + ebase[lp[mid]]
+                       : b - VERT(1) - gap;
+       if(dbg) {
+               printf(".\tS%d <- %c pile of:", yyval, type);
+               for( i=p1; i<p2; i++)
+                       printf(" S%d", lp[i]);
+               printf(";h=%d b=%d\n", eht[yyval], ebase[yyval]);
+       }
+       nrwid(lp[p1], ps, lp[p1]);
+       printf(".nr %d \\n(%d\n", yyval, lp[p1]);
+       for( i = p1+1; i<p2; i++ ) {
+               nrwid(lp[i], ps, lp[i]);
+               printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", 
+                       lp[i], yyval, yyval, lp[i]);
+       }
+       printf(".ds %d \\v'%du'\\h'%du*\\n(%du'\\\n", yyval, ebase[yyval], 
+               type=='R' ? 1 : 0, yyval);
+       for(i = p2-1; i >=p1; i--) {
+               hi = eht[lp[i]]; 
+               bi = ebase[lp[i]];
+       switch(type) {
+
+       case 'L':
+               printf("\\v'%du'\\*(%d\\h'-\\n(%du'\\v'0-%du'\\\n", 
+                       -bi, lp[i], lp[i], hi-bi+gap);
+               continue;
+       case 'R':
+               printf("\\v'%du'\\h'-\\n(%du'\\*(%d\\v'0-%du'\\\n", 
+                       -bi, lp[i], lp[i], hi-bi+gap);
+               continue;
+       case 'C':
+       case '-':
+               printf("\\v'%du'\\h'\\n(%du-\\n(%du/2u'\\*(%d", 
+                       -bi, yyval, lp[i], lp[i]);
+               printf("\\h'-\\n(%du-\\n(%du/2u'\\v'0-%du'\\\n", 
+                       yyval, lp[i], hi-bi+gap);
+               continue;
+               }
+       }
+       printf("\\v'%du'\\h'%du*\\n(%du'\n", eht[yyval]-ebase[yyval]+gap, 
+               type!='R' ? 1 : 0, yyval);
+       for( i=p1; i<p2; i++ )
+               ofree(lp[i]);
+       lfont[yyval] = rfont[yyval] = 0;
+}
diff --git a/usr/src/usr.bin/neqn/shift.c b/usr/src/usr.bin/neqn/shift.c
new file mode 100644 (file)
index 0000000..068cb72
--- /dev/null
@@ -0,0 +1,70 @@
+# include "e.h"
+#include "e.def"
+
+bshiftb(p1, dir, p2) int p1, dir, p2; {
+       int shval, d1, h1, b1, h2, b2;
+       yyval = p1;
+       h1 = eht[p1];
+       b1 = ebase[p1];
+       h2 = eht[p2];
+       b2 = ebase[p2];
+       if( dir == SUB ) {      /* subscript */
+               d1 = VERT(1);
+               shval = - d1 + h2 - b2;
+               if( d1+b1 > h2 ) /* move little sub down */
+                       shval = b1-b2;
+               ebase[yyval] = b1 + max(0, h2-b1-d1);
+               eht[yyval] = h1 + max(0, h2-b1-d1);
+       } else {        /* superscript */
+               d1 = VERT(1);
+               ebase[yyval] = b1;
+               shval = -VERT(1) - b2;
+               if( VERT(1) + h2 < h1-b1 )      /* raise little super */
+                       shval = -(h1-b1) + h2-b2 - d1;
+               eht[yyval] = h1 + max(0, h2 - VERT(1));
+       }
+       if(dbg)printf(".\tb:b shift b: S%d <- S%d vert %d S%d vert %d; b=%d, h=%d\n", 
+               yyval, p1, shval, p2, -shval, ebase[yyval], eht[yyval]);
+       printf(".as %d \\v'%du'\\*(%d\\v'%du'\n", 
+               yyval, shval, p2, -shval);
+       ofree(p2);
+}
+
+shift(p1) int p1; {
+       ps -= deltaps;
+       yyval = p1;
+       if(dbg)printf(".\tshift: %d;ps=%d\n", yyval, ps);
+}
+
+shift2(p1, p2, p3) int p1, p2, p3; {
+       int effps, h1, h2, h3, b1, b2, b3, subsh, d1, d2, supsh;
+       int treg;
+
+       treg = oalloc();
+       yyval = p1;
+       if(dbg)printf(".\tshift2 s%d <- %d %d %d\n", yyval, p1, p2, p3);
+       effps = EFFPS(ps+deltaps);
+       h1 = eht[p1]; b1 = ebase[p1];
+       h2 = eht[p2]; b2 = ebase[p2];
+       h3 = eht[p3]; b3 = ebase[p3];
+       d1 = VERT(1);
+       subsh = -d1+h2-b2;
+       if( d1+b1 > h2 ) /* move little sub down */
+               subsh = b1-b2;
+       supsh = - VERT(1) - b3;
+       d2 = VERT(1);
+       if( VERT(1)+h3 < h1-b1 )
+               supsh = -(h1-b1) + (h3-b3) - d2;
+       eht[yyval] = h1 + max(0, h3-VERT(1)) + max(0, h2-b1-d1);
+       ebase[yyval] = b1+max(0, h2-b1-d1);
+       nrwid(p2, effps, p2);
+       nrwid(p3, effps, p3);
+       printf(".nr %d \\n(%d\n", treg, p3);
+       printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, treg, treg, p2);
+       printf(".as %d \\v'%du'\\*(%d\\h'-\\n(%du'\\v'%du'\\\n", 
+               p1, subsh, p2, p2, -subsh+supsh);
+       printf("\\*(%d\\h'-\\n(%du+\\n(%du'\\v'%du'\n", 
+               p3, p3, treg, -supsh);
+       ps += deltaps;
+       ofree(p2); ofree(p3); ofree(treg);
+}
diff --git a/usr/src/usr.bin/neqn/size.c b/usr/src/usr.bin/neqn/size.c
new file mode 100644 (file)
index 0000000..8f99fa6
--- /dev/null
@@ -0,0 +1,46 @@
+# include "e.h"
+
+setsize(p)     /* set size as found in p */
+char *p;
+{
+       if (*p == '+')
+               ps += atoi(p+1);
+       else if (*p == '-')
+               ps -= atoi(p+1);
+       else
+               ps = atoi(p);
+       if(dbg)printf(".\tsetsize %s; ps = %d\n", p, ps);
+}
+
+size(p1, p2) int p1, p2; {
+               /* old size in p1, new in ps */
+       int effps, effp1;
+
+       yyval = p2;
+       if(dbg)printf(".\tb:sb: S%d <- \\s%d S%d \\s%d; b=%d, h=%d\n", 
+               yyval, ps, p2, p1, ebase[yyval], eht[yyval]);
+       effps = EFFPS(ps);
+       effp1 = EFFPS(p1);
+       printf(".ds %d \\s%d\\*(%d\\s%d\n", 
+               yyval, effps, p2, effp1);
+       ps = p1;
+}
+
+globsize() {
+       char temp[20];
+
+       getstr(temp, 20);
+       if (temp[0] == '+')
+               gsize += atoi(temp+1);
+       else if (temp[0] == '-')
+               gsize -= atoi(temp+1);
+       else
+               gsize = atoi(temp);
+       yyval = eqnreg = 0;
+       setps(gsize);
+       ps = gsize;
+       if (gsize >= 12)        /* sub and sup size change */
+               deltaps = gsize / 4;
+       else
+               deltaps = gsize / 3;
+}
diff --git a/usr/src/usr.bin/neqn/sqrt.c b/usr/src/usr.bin/neqn/sqrt.c
new file mode 100644 (file)
index 0000000..ea20bea
--- /dev/null
@@ -0,0 +1,12 @@
+# include "e.h"
+
+sqrt(p2) int p2; {
+       yyval = p2;
+       nrwid(p2, ps, p2);
+       printf(".ds %d \\v'%du'\\e\\L'%du'\\l'\\n(%du'",
+               p2, ebase[p2], -eht[p2], p2);
+       printf("\\v'%du'\\h'-\\n(%du'\\*(%d\n", eht[p2]-ebase[p2], p2, p2);
+       eht[p2] += VERT(1);
+       if(dbg)printf(".\tsqrt: S%d <- S%d;b=%d, h=%d\n", 
+               p2, p2, ebase[p2], eht[p2]);
+}
diff --git a/usr/src/usr.bin/neqn/text.c b/usr/src/usr.bin/neqn/text.c
new file mode 100644 (file)
index 0000000..0686dca
--- /dev/null
@@ -0,0 +1,170 @@
+# include "e.h"
+# include "e.def"
+
+int    csp;
+int    psp;
+#define        CSSIZE  400
+char   cs[420];
+
+int    lf, rf; /* temporary spots for left and right fonts */
+
+text(t,p1) int t; char *p1; {
+       int c;
+       char *p;
+       tbl *tp, *lookup();
+       extern tbl *restbl;
+
+       yyval = oalloc();
+       ebase[yyval] = 0;
+       eht[yyval] = VERT(2);   /* 2 half-spaces */
+       lfont[yyval] = rfont[yyval] = ROM;
+       if (t == QTEXT)
+               p = p1;
+       else if ( t == SPACE )
+               p = "\\ ";
+       else if ( t == THIN )
+               p = "\\|";
+       else if ( t == TAB )
+               p = "\\t";
+       else if ((tp = lookup(&restbl, p1, NULL)) != NULL)
+               p = tp->defn;
+       else {
+               lf = rf = 0;
+               for (csp=psp=0; (c=p1[psp++])!='\0';) {
+                       rf = trans(c, p1);
+                       if (lf == 0)
+                               lf = rf;        /* save first */
+                       if (csp>CSSIZE)
+                               error(FATAL,"converted token %.25s... too long",p1);
+               }
+               cs[csp] = '\0';
+               p = cs;
+               lfont[yyval] = lf;
+               rfont[yyval] = rf;
+       }
+       if(dbg)printf(".\t%dtext: S%d <- %s; b=%d,h=%d,lf=%c,rf=%c\n",
+               t, yyval, p, ebase[yyval], eht[yyval], lfont[yyval], rfont[yyval]);
+       printf(".ds %d \"%s\n", yyval, p);
+}
+
+trans(c,p1) int c; char *p1; {
+       int f;
+       f = ROM;
+       switch( c) {
+       case '0': case '1': case '2': case '3': case '4':
+       case '5': case '6': case '7': case '8': case '9':
+       case ':': case ';': case '!': case '%':
+       case '(': case '[': case ')': case ']':
+       case ',':
+               if (rf == ITAL)
+                       shim();
+               roman(c); break;
+       case '.':
+               if (rf == ROM)
+                       roman(c);
+               else
+                       cs[csp++] = c;
+               f = rf;
+               break;
+       case '|':
+               if (rf == ITAL)
+                       shim();
+               shim(); roman(c); shim(); break;
+       case '=':
+               if (rf == ITAL)
+                       shim();
+               name4('e','q');
+               break;
+       case '+':
+               if (rf == ITAL)
+                       shim();
+               name4('p', 'l');
+               break;
+       case '>': case '<':
+               if (rf == ITAL)
+                       shim();
+               if (p1[psp]=='=') {     /* look ahead for == <= >= */
+                       name4(c,'=');
+                       psp++;
+               } else {
+                       cs[csp++] = c;  
+               }
+               break;
+       case '-':
+               if (rf == ITAL)
+                       shim();
+               if (p1[psp]=='>') {
+                       name4('-','>'); psp++;
+               } else {
+                       name4('m','i');
+               }
+               break;
+       case '/':
+               if (rf == ITAL)
+                       shim();
+               name4('s','l');
+               break;
+       case '~': case ' ':
+               shim(); shim(); break;
+       case '^':
+               shim(); break;
+       case '\\':      /* troff - pass 2 or 3 more chars */
+               if (rf == ITAL)
+                       shim();
+               cs[csp++] = c; cs[csp++] = c = p1[psp++]; cs[csp++] = p1[psp++];
+               if (c=='(') cs[csp++] = p1[psp++];
+               if (c=='*' && cs[csp-1] == '(') {
+                       cs[csp++] = p1[psp++];
+                       cs[csp++] = p1[psp++];
+               }
+               break;
+       case '\'':
+               cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = rf==ITAL ? ITAL : ROM;
+               name4('f','m');
+               cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = 'P';
+               f = rf==ITAL ? ITAL : ROM;
+               break;
+
+       case 'f':
+               if (ft == ITAL) {
+                       cs[csp++] = '\\'; cs[csp++] = '^';
+                       cs[csp++] = 'f';
+                       cs[csp++] = '\\'; cs[csp++] = '|';      /* trying | instead of ^ */
+                       f = ITAL;
+               }
+               else
+                       cs[csp++] = 'f';
+               break;
+       case 'j':
+               if (ft == ITAL) {
+                       cs[csp++] = '\\'; cs[csp++] = '^';
+                       cs[csp++] = 'j';
+                       f = ITAL;
+               }
+               else
+                       cs[csp++] = 'j';
+               break;
+       default:
+               cs[csp++] = c;
+               f = ft==ITAL ? ITAL : ROM;
+               break;
+       }
+       return(f);
+}
+
+shim() {
+       cs[csp++] = '\\'; cs[csp++] = '|';
+}
+
+roman(c) int c; {
+       cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = ROM;
+       cs[csp++] = c;
+       cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = 'P';
+}
+
+name4(c1,c2) int c1,c2; {
+       cs[csp++] = '\\';
+       cs[csp++] = '(';
+       cs[csp++] = c1;
+       cs[csp++] = c2;
+}