tPlan 9 lex (to be installed as lex.9, if at all). - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit e37302c4b99f147f1fd85ca27a2dbd2aa7a4eb41
 (DIR) parent 7d3bbe16529792999d0627256748f9b780c084f3
 (HTM) Author: wkj <devnull@localhost>
       Date:   Wed, 21 Apr 2004 01:22:09 +0000
       
       Plan 9 lex (to be installed as lex.9, if at all).
       
       Diffstat:
         A src/cmd/lex/header.c                |     115 +++++++++++++++++++++++++++++++
         A src/cmd/lex/ldefs.h                 |     180 +++++++++++++++++++++++++++++++
         A src/cmd/lex/lmain.c                 |     292 +++++++++++++++++++++++++++++++
         A src/cmd/lex/mkfile                  |      30 ++++++++++++++++++++++++++++++
         A src/cmd/lex/ncform                  |     188 +++++++++++++++++++++++++++++++
         A src/cmd/lex/parser.y                |     651 +++++++++++++++++++++++++++++++
         A src/cmd/lex/sub1.c                  |     591 +++++++++++++++++++++++++++++++
         A src/cmd/lex/sub2.c                  |     856 +++++++++++++++++++++++++++++++
       
       8 files changed, 2903 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/lex/header.c b/src/cmd/lex/header.c
       t@@ -0,0 +1,115 @@
       +# include "ldefs.h"
       +
       +extern int nine;
       +
       +void
       +phead1(void)
       +{
       +        Bprint(&fout,"typedef unsigned char Uchar;\n");
       +        if (nine) {
       +                Bprint(&fout,"# include <u.h>\n");
       +                Bprint(&fout,"# include <libc.h>\n");
       +        }
       +        Bprint(&fout,"# include <stdio.h>\n");
       +        Bprint(&fout, "# define U(x) x\n");
       +        Bprint(&fout, "# define NLSTATE yyprevious=YYNEWLINE\n");
       +        Bprint(&fout,"# define BEGIN yybgin = yysvec + 1 +\n");
       +        Bprint(&fout,"# define INITIAL 0\n");
       +        Bprint(&fout,"# define YYLERR yysvec\n");
       +        Bprint(&fout,"# define YYSTATE (yyestate-yysvec-1)\n");
       +        Bprint(&fout,"# define YYOPTIM 1\n");
       +# ifdef DEBUG
       +        Bprint(&fout,"# define LEXDEBUG 1\n");
       +# endif
       +        Bprint(&fout,"# define YYLMAX 200\n");
       +        Bprint(&fout,
       +"# define unput(c) {yytchar= (c);if(yytchar=='\\n')yylineno--;*yysptr++=yytchar;}\n");
       +        Bprint(&fout,"# define yymore() (yymorfg=1)\n");
       +        Bprint(&fout,"# define ECHO fprintf(yyout, \"%%s\",yytext)\n");
       +        Bprint(&fout,"# define REJECT { nstr = yyreject(); goto yyfussy;}\n");
       +        Bprint(&fout,"int yyleng; extern char yytext[];\n");
       +        Bprint(&fout,"int yymorfg;\n");
       +        Bprint(&fout,"extern Uchar *yysptr, yysbuf[];\n");
       +        Bprint(&fout,"int yytchar;\n");
       +//        Bprint(&fout,"FILE *yyin = stdin, *yyout = stdout;\n");
       +        Bprint(&fout,"FILE *yyin, *yyout;\n");
       +        Bprint(&fout,"extern int yylineno;\n");
       +        Bprint(&fout,"struct yysvf { \n");
       +        Bprint(&fout,"\tstruct yywork *yystoff;\n");
       +        Bprint(&fout,"\tstruct yysvf *yyother;\n");
       +        Bprint(&fout,"\tint *yystops;};\n");
       +        Bprint(&fout,"struct yysvf *yyestate;\n");
       +        Bprint(&fout,"extern struct yysvf yysvec[], *yybgin;\n");
       +        Bprint(&fout,"int yylook(void), yywrap(void), yyback(int *, int);\n");
       +        if(nine) {
       +                Bprint(&fout,
       +                                "int infd, outfd;\n"
       +                                "\n"
       +                                "void\n"
       +                                "output(char c)\n"
       +                                "{\n"
       +                                "        int rv;\n"
       +                                "        if ((rv = write(outfd, &c, 1)) < 0)\n"
       +                                "                sysfatal(\"output: %%r\");\n"
       +                                "        if (rv == 0)\n"
       +                                "                sysfatal(\"output: EOF?\");\n"
       +                                "}\n"
       +                                "\n"
       +                                "int\n"
       +                                "input(void)\n"
       +                                "{\n"
       +                                "        if(yysptr > yysbuf)\n"
       +                                "                yytchar = U(*--yysptr);\n"
       +                                "        else {\n"
       +                                "                int rv;\n"
       +                                "                if ((rv = read(infd, &yytchar, 1)) < 0)\n"
       +                                "                        sysfatal(\"input: %%r\");\n"
       +                                "                if (rv == 0)\n"
       +                                "                        return 0;\n"
       +                                "        }\n"
       +                                "        if (yytchar == '\\n')\n"
       +                                "                yylineno++;\n"
       +                                "        return yytchar;\n"
       +                                "}\n");
       +        }
       +        else {
       +                Bprint(&fout,"# define output(c) putc(c,yyout)\n");
       +                Bprint(&fout, "%s%d%s\n",
       +                  "# define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==",
       +                '\n',
       +                 "?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)");
       +        }
       +}
       +
       +void
       +phead2(void)
       +{
       +        Bprint(&fout,"while((nstr = yylook()) >= 0)\n");
       +        Bprint(&fout,"yyfussy: switch(nstr){\n");
       +        Bprint(&fout,"case 0:\n");
       +        Bprint(&fout,"if(yywrap()) return(0); break;\n");
       +}
       +
       +void
       +ptail(void)
       +{
       +        if(!pflag){
       +                Bprint(&fout,"case -1:\nbreak;\n");                /* for reject */
       +                Bprint(&fout,"default:\n");
       +                Bprint(&fout,"fprintf(yyout,\"bad switch yylook %%d\",nstr);\n");
       +                Bprint(&fout,"} return(0); }\n");
       +                Bprint(&fout,"/* end of yylex */\n");
       +        }
       +        pflag = 1;
       +}
       +
       +void
       +statistics(void)
       +{
       +        fprint(errorf,"%d/%d nodes(%%e), %d/%d positions(%%p), %d/%d (%%n), %ld transitions\n",
       +                tptr, treesize, (int)(nxtpos-positions), maxpos, stnum+1, nstates, rcount);
       +        fprint(errorf, ", %d/%d packed char classes(%%k)", (int)(pcptr-pchar), pchlen);
       +        fprint(errorf,", %d/%d packed transitions(%%a)",nptr, ntrans);
       +        fprint(errorf, ", %d/%d output slots(%%o)", yytop, outsize);
       +        fprint(errorf,"\n");
       +}
 (DIR) diff --git a/src/cmd/lex/ldefs.h b/src/cmd/lex/ldefs.h
       t@@ -0,0 +1,180 @@
       +# include <u.h>
       +# include <libc.h>
       +# include <ctype.h>
       +# include <bio.h>
       +# define PP 1
       +
       +#ifdef NOTDEF
       +# define CWIDTH 8
       +# define CMASK 0377
       +#endif
       +# define NCH 256
       +
       +
       +# define TOKENSIZE 1000
       +# define DEFSIZE 40
       +# define DEFCHAR 1000
       +# define STARTCHAR 100
       +# define STARTSIZE 256
       +# define CCLSIZE 1000
       +
       +# define TREESIZE 1000
       +# define NSTATES 500
       +# define MAXPOS 2500
       +# define NTRANS 2000
       +# define NOUTPUT 5000
       +
       +# 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
       +
       +# ifdef DEBUG
       +extern int        freturn(int);
       +# else
       +# define freturn(s) s
       +# endif
       +
       +extern int sargc;
       +extern char **sargv;
       +extern uchar buf[520];
       +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 Biobuf *fin, fout, *fother;
       +extern int foutopen;
       +extern int errorf;
       +extern int fptr;
       +extern char *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 uchar *nullstr;
       +extern int tptr;
       +extern uchar pushc[TOKENSIZE];
       +extern uchar *pushptr;
       +extern uchar slist[STARTSIZE];
       +extern uchar *slptr;
       +extern uchar **def, **subs, *dchar;
       +extern uchar **sname, *stchar;
       +extern uchar *ccl;
       +extern uchar *ccptr;
       +extern uchar *dp, *sp;
       +extern int dptr, sptr;
       +extern uchar *bptr;                /* store input position */
       +extern uchar *tmpstat;
       +extern int count;
       +extern int **foll;
       +extern int *nxtpos;
       +extern int *positions;
       +extern int *gotof;
       +extern int *nexts;
       +extern uchar *nchar;
       +extern int **state;
       +extern int *sfall;                /* fallback state num */
       +extern uchar *cpackflg;                /* true if state has been character packed */
       +extern int *atable, aptr;
       +extern int nptr;
       +extern uchar symbol[NCH];
       +extern uchar cindex[NCH];
       +extern int xstate;
       +extern int stnum;
       +extern int ccount;
       +extern uchar match[NCH];
       +extern uchar extra[NACTIONS];
       +extern uchar *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 *verify, *advance, *stoff;
       +extern int scon;
       +extern uchar *psave;
       +
       +extern void        acompute(int);
       +extern void        add(int **, int);
       +extern void        allprint(int);
       +extern void        cclinter(int);
       +extern void        cgoto(void);
       +extern void        cfoll(int);
       +extern int        cpyact(void);
       +extern int        dupl(int);
       +extern void        error(char *,...);
       +extern void        first(int);
       +extern void        follow(int);
       +extern int        gch(void);
       +extern uchar        *getl(uchar *);
       +extern void        layout(void);
       +extern void        lgate(void);
       +extern int        lookup(uchar *, uchar **);
       +extern int        member(int, uchar *);
       +extern void        mkmatch(void);
       +extern int        mn0(int);
       +extern int        mn1(int, int);
       +extern int        mn2(int, int, int);
       +extern void        munputc(int);
       +extern void        munputs(uchar *);
       +extern void        *myalloc(int, int);
       +extern void        nextstate(int, int);
       +extern int        notin(int);
       +extern void        packtrans(int, uchar *, int *, int, int);
       +extern void        padd(int **, int);
       +extern void        pccl(void);
       +extern void        pfoll(void);
       +extern void        phead1(void);
       +extern void        phead2(void);
       +extern void        pstate(int);
       +extern void        ptail(void);
       +extern void        sect1dump(void);
       +extern void        sect2dump(void);
       +extern void        statistics(void);
       +extern void        stprt(int);
       +extern void        strpt(uchar *);
       +extern void        treedump(void);
       +extern int        usescape(int);
       +extern void        warning(char *,...);
       +extern int        yyparse(void);
       +extern void        yyerror(char *);
 (DIR) diff --git a/src/cmd/lex/lmain.c b/src/cmd/lex/lmain.c
       t@@ -0,0 +1,292 @@
       +/* lex [-[dynvt]] [file] ... [file] */
       +
       +/* Copyright 1976, Bell Telephone Laboratories, Inc.,
       +   written by Eric Schmidt, August 27, 1976   */
       +
       +# include "ldefs.h"
       +Biobuf        fout;
       +int        foutopen;
       +int        errorf = 1;
       +int        sect = DEFSECTION;
       +int        prev = '\n';        /* previous input character */
       +int        pres = '\n';        /* present input character */
       +int        peek = '\n';        /* next input character */
       +uchar        *pushptr = pushc;
       +uchar        *slptr = slist;
       +
       +char        *cname = SYS9 "/sys/lib/lex/ncform";
       +
       +int nine;
       +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 report = 2;
       +int debug;                /* 1 = on */
       +int charc;
       +int sargc;
       +char **sargv;
       +uchar buf[520];
       +int yyline;                /* line number of file */
       +int eof;
       +int lgatflg;
       +int divflg;
       +int funcflag;
       +int pflag;
       +int chset;        /* 1 = char set modified */
       +Biobuf *fin, *fother;
       +int fptr;
       +int *name;
       +int *left;
       +int *right;
       +int *parent;
       +uchar *nullstr;
       +int tptr;
       +uchar pushc[TOKENSIZE];
       +uchar slist[STARTSIZE];
       +uchar **def, **subs, *dchar;
       +uchar **sname, *stchar;
       +uchar *ccl;
       +uchar *ccptr;
       +uchar *dp, *sp;
       +int dptr;
       +uchar *bptr;                /* store input position */
       +uchar *tmpstat;
       +int count;
       +int **foll;
       +int *nxtpos;
       +int *positions;
       +int *gotof;
       +int *nexts;
       +uchar *nchar;
       +int **state;
       +int *sfall;                /* fallback state num */
       +uchar *cpackflg;                /* true if state has been character packed */
       +int *atable;
       +int nptr;
       +uchar symbol[NCH];
       +uchar cindex[NCH];
       +int xstate;
       +int stnum;
       +uchar match[NCH];
       +uchar extra[NACTIONS];
       +uchar *pchar, *pcptr;
       +int pchlen = TOKENSIZE;
       + long rcount;
       +int *verify, *advance, *stoff;
       +int scon;
       +uchar *psave;
       +
       +static void        free1core(void);
       +static void        free2core(void);
       +#ifdef DEBUG
       +static void        free3core(void);
       +#endif
       +static void        get1core(void);
       +static void        get2core(void);
       +static void        get3core(void);
       +
       +void
       +main(int argc, char **argv)
       +{
       +        int i;
       +
       +        ARGBEGIN {
       +# ifdef DEBUG
       +                case 'd': debug++; break;
       +                case 'y': yydebug = TRUE; break;
       +# endif
       +                case 't': case 'T':
       +                        Binit(&fout, 1, OWRITE);
       +                        errorf= 2;
       +                        foutopen = 1;
       +                        break;
       +                case 'v': case 'V':
       +                        report = 1;
       +                        break;
       +                case 'n': case 'N':
       +                        report = 0;
       +                        break;
       +                case '9':
       +                        nine = 1;
       +                        break;
       +                default:
       +                        warning("Unknown option %c", ARGC());
       +        } ARGEND
       +        sargc = argc;
       +        sargv = argv;
       +        if (argc > 0){
       +                fin = Bopen(argv[fptr++], OREAD);
       +                if(fin == 0)
       +                        error ("Can't read input file %s",argv[0]);
       +                sargc--;
       +                sargv++;
       +        }
       +        else {
       +                fin = myalloc(sizeof(Biobuf), 1);
       +                if(fin == 0)
       +                        exits("core");
       +                Binit(fin, 0, OREAD);
       +        }
       +        if(Bgetc(fin) == Beof)                /* no input */
       +                exits(0);
       +        Bseek(fin, 0, 0);
       +        gch();
       +                /* may be gotten: def, subs, sname, stchar, ccl, dchar */
       +        get1core();
       +                /* may be gotten: name, left, right, nullstr, parent */
       +        strcpy((char*)sp, "INITIAL");
       +        sname[0] = sp;
       +        sp += strlen("INITIAL") + 1;
       +        sname[1] = 0;
       +        if(yyparse()) exits("error");        /* 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){
       +                print("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, stchar, 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
       +        fother = Bopen(cname,OREAD);
       +        if(fother == 0)
       +                error("Lex driver missing, file %s",cname);
       +        while ( (i=Bgetc(fother)) != Beof)
       +                Bputc(&fout, i);
       +
       +        Bterm(fother);
       +        Bterm(&fout);
       +        if(
       +# ifdef DEBUG
       +                debug   ||
       +# endif
       +                        report == 1)statistics();
       +        Bterm(fin);
       +        exits(0);        /* success return code */
       +}
       +
       +static void
       +get1core(void)
       +{
       +        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 = stchar = myalloc(STARTCHAR,sizeof(*stchar));
       +        if(ccl == 0 || def == 0 || subs == 0 || dchar == 0 || sname == 0 || stchar == 0)
       +                error("Too little core to begin");
       +}
       +
       +static void
       +free1core(void)
       +{
       +        free(def);
       +        free(subs);
       +        free(dchar);
       +}
       +
       +static void
       +get2core(void)
       +{
       +        int i;
       +
       +        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;
       +}
       +
       +static void
       +free2core(void)
       +{
       +        free(positions);
       +        free(tmpstat);
       +        free(foll);
       +        free(name);
       +        free(left);
       +        free(right);
       +        free(parent);
       +        free(nullstr);
       +        free(state);
       +        free(sname);
       +        free(stchar);
       +        free(ccl);
       +}
       +
       +static void
       +get3core(void)
       +{
       +        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
       +static void
       +free3core(void){
       +        free(advance);
       +        free(verify);
       +        free(stoff);
       +        free(gotof);
       +        free(nexts);
       +        free(nchar);
       +        free(atable);
       +        free(sfall);
       +        free(cpackflg);
       +}
       +# endif
       +void *
       +myalloc(int a, int b)
       +{
       +        void *i;
       +        i = calloc(a, b);
       +        if(i==0)
       +                warning("OOPS - calloc returns a 0");
       +        return(i);
       +}
       +
       +void
       +yyerror(char *s)
       +{
       +        fprint(2, "line %d: %s\n", yyline, s);
       +}
 (DIR) diff --git a/src/cmd/lex/mkfile b/src/cmd/lex/mkfile
       t@@ -0,0 +1,30 @@
       +<$PLAN9/src/mkhdr
       +
       +#TARG=lex
       +TARG=lex.9
       +OFILES=lmain.$O\
       +        y.tab.$O\
       +        sub1.$O\
       +        sub2.$O\
       +        header.$O\
       +
       +HFILES=ldefs.h\
       +
       +YFILES=parser.y\
       +
       +SHORTLIB=bio 9
       +UPDATE=\
       +        mkfile\
       +        $HFILES\
       +        lmain.c\
       +        sub1.c\
       +        sub2.c\
       +        header.c
       +
       +<$PLAN9/src/mkone
       +
       +installall:V:
       +        for objtype in $CPUS ; do
       +                mk install
       +        done
       +        cp ncform $SYS9/lib/lex
 (DIR) diff --git a/src/cmd/lex/ncform b/src/cmd/lex/ncform
       t@@ -0,0 +1,188 @@
       +#pragma lib        "libl.a"
       +int yylineno =1;
       +# define YYU(x) x
       +char yytext[YYLMAX];
       +struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp;
       +Uchar yysbuf[YYLMAX];
       +Uchar *yysptr = yysbuf;
       +int *yyfnd;
       +extern struct yysvf *yyestate;
       +int yyprevious = YYNEWLINE;
       +# ifdef LEXDEBUG
       +extern void allprint(char);
       +# endif
       +yylook(void){
       +        struct yysvf *yystate, **lsp;
       +        struct yywork *yyt;
       +        struct yysvf *yyz;
       +        int yych;
       +        struct yywork *yyr;
       +# ifdef LEXDEBUG
       +        int debug;
       +# endif
       +        Uchar *yylastch;
       +        /* start off machines */
       +# ifdef LEXDEBUG
       +        debug = 0;
       +# endif
       +        if (!yymorfg)
       +                yylastch = (Uchar*)yytext;
       +        else {
       +                yymorfg=0;
       +                yylastch = (Uchar*)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-(Uchar*)yytext+1;
       +                                yytext[yyleng] = 0;
       +# ifdef LEXDEBUG
       +                                if(debug){
       +                                        fprintf(yyout,"\nmatch '%s'", yytext);
       +                                        fprintf(yyout," action %d\n",*yyfnd);
       +                                        }
       +# endif
       +                                return(*yyfnd++);
       +                                }
       +                        unput(*yylastch);
       +                        }
       +                if (yytext[0] == 0  /* && feof(yyin) */)
       +                        {
       +                        yysptr=yysbuf;
       +                        return(0);
       +                        }
       +                yyprevious = input();
       +                yytext[0] = yyprevious;
       +                if (yyprevious>0)
       +                        output(yyprevious);
       +                yylastch = (Uchar*)yytext;
       +# ifdef LEXDEBUG
       +                if(debug)putchar('\n');
       +# endif
       +                }
       +        return(0);        /* shut up the compiler; i have no idea what should be returned */
       +        }
       +yyback(int *p, int m)
       +{
       +if (p==0) return(0);
       +while (*p)
       +        {
       +        if (*p++ == m)
       +                return(1);
       +        }
       +return(0);
       +}
       +        /* the following are only used in the lex library */
       +yyinput(void){
       +        if(yyin == ((void*)0))
       +                yyin = stdin;
       +        return(input());
       +}
       +void
       +yyoutput(int c)
       +{
       +        if(yyout == ((void*)0))
       +                yyout = stdin;
       +        output(c);
       +}
       +void
       +yyunput(int c)
       +{
       +        unput(c);
       +}
 (DIR) diff --git a/src/cmd/lex/parser.y b/src/cmd/lex/parser.y
       t@@ -0,0 +1,651 @@
       +%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.h"
       +#define YYSTYPE union _yystype_
       +union _yystype_
       +{
       +        int        i;
       +        uchar        *cp;
       +};
       +%}
       +%%
       +%{
       +int i;
       +int j,k;
       +int g;
       +uchar *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
       +        ={        strcpy((char*)dp,(char*)$2.cp);
       +                def[dptr] = dp;
       +                dp += strlen((char*)$2.cp) + 1;
       +                strcpy((char*)dp,(char*)$3.cp);
       +                subs[dptr++] = dp;
       +                if(dptr >= DEFSIZE)
       +                        error("Too many definitions");
       +                dp += strlen((char*)$3.cp) + 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
       +        ={        $$.i = mn2(RNEWE,$1.i,$2.i);
       +                }
       +        |        pr
       +        ={        $$.i = $1.i;}
       +        ;
       +pr:        r NEWE
       +        ={
       +                if(divflg == TRUE)
       +                        i = mn1(S1FINAL,casecount);
       +                else i = mn1(FINAL,casecount);
       +                $$.i = mn2(RCAT,$1.i,i);
       +                divflg = FALSE;
       +                casecount++;
       +                }
       +        | error NEWE
       +        ={
       +# ifdef DEBUG
       +                if(debug) sect2dump();
       +# endif
       +                }
       +r:        CHAR
       +        ={        $$.i = mn0($1.i); }
       +        | STR
       +        ={
       +                p = $1.cp;
       +                i = mn0(*p++);
       +                while(*p)
       +                        i = mn2(RSTR,i,*p++);
       +                $$.i = 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;
       +                $$.i = mn1(RCCL,(int)p);
       +                cclinter(1);
       +                }
       +        | CCL
       +        ={        $$.i = mn1(RCCL,$1.i); }
       +        | NCCL
       +        ={        $$.i = mn1(RNCCL,$1.i); }
       +        | r '*'
       +        ={        $$.i = mn1(STAR,$1.i); }
       +        | r '+'
       +        ={        $$.i = mn1(PLUS,$1.i); }
       +        | r '?'
       +        ={        $$.i = mn1(QUEST,$1.i); }
       +        | r '|' r
       +        ={        $$.i = mn2(BAR,$1.i,$3.i); }
       +        | r r %prec CAT
       +        ={        $$.i = mn2(RCAT,$1.i,$2.i); }
       +        | r '/' r
       +        ={        if(!divflg){
       +                        j = mn1(S2FINAL,-casecount);
       +                        i = mn2(RCAT,$1.i,j);
       +                        $$.i = mn2(DIV,i,$3.i);
       +                        }
       +                else {
       +                        $$.i = mn2(RCAT,$1.i,$3.i);
       +                        warning("Extra slash removed");
       +                        }
       +                divflg = TRUE;
       +                }
       +        | r ITER ',' ITER '}'
       +        ={        if($2.i > $4.i){
       +                        i = $2.i;
       +                        $2.i = $4.i;
       +                        $4.i = i;
       +                        }
       +                if($4.i <= 0)
       +                        warning("Iteration range must be positive");
       +                else {
       +                        j = $1.i;
       +                        for(k = 2; k<=$2.i;k++)
       +                                j = mn2(RCAT,j,dupl($1.i));
       +                        for(i = $2.i+1; i<=$4.i; i++){
       +                                g = dupl($1.i);
       +                                for(k=2;k<=i;k++)
       +                                        g = mn2(RCAT,g,dupl($1.i));
       +                                j = mn2(BAR,j,g);
       +                                }
       +                        $$.i = j;
       +                        }
       +        }
       +        | r ITER '}'
       +        ={
       +                if($2.i < 0)warning("Can't have negative iteration");
       +                else if($2.i == 0) $$.i = mn0(RNULLS);
       +                else {
       +                        j = $1.i;
       +                        for(k=2;k<=$2.i;k++)
       +                                j = mn2(RCAT,j,dupl($1.i));
       +                        $$.i = j;
       +                        }
       +                }
       +        | r ITER ',' '}'
       +        ={
       +                                /* from n to infinity */
       +                if($2.i < 0)warning("Can't have negative iteration");
       +                else if($2.i == 0) $$.i = mn1(STAR,$1.i);
       +                else if($2.i == 1)$$.i = mn1(PLUS,$1.i);
       +                else {                /* >= 2 iterations minimum */
       +                        j = $1.i;
       +                        for(k=2;k<$2.i;k++)
       +                                j = mn2(RCAT,j,dupl($1.i));
       +                        k = mn1(PLUS,dupl($1.i));
       +                        $$.i = mn2(RCAT,j,k);
       +                        }
       +                }
       +        | SCON r
       +        ={        $$.i = mn2(RSCON,$2.i,$1.i); }
       +        | '^' r
       +        ={        $$.i = mn1(CARAT,$2.i); }
       +        | r '$'
       +        ={        i = mn0('\n');
       +                if(!divflg){
       +                        j = mn1(S2FINAL,-casecount);
       +                        k = mn2(RCAT,$1.i,j);
       +                        $$.i = mn2(DIV,k,i);
       +                        }
       +                else $$.i = mn2(RCAT,$1.i,i);
       +                divflg = TRUE;
       +                }
       +        | '(' r ')'
       +        ={        $$.i = $2.i; }
       +        |        NULLS
       +        ={        $$.i = mn0(RNULLS); }
       +        ;
       +%%
       +int
       +yylex(void)
       +{
       +        uchar *p;
       +        int c, i;
       +        uchar  *t, *xp;
       +        int n, j, k, x;
       +        static int sectbegin;
       +        static uchar token[TOKENSIZE];
       +        static int iter;
       +
       +# ifdef DEBUG
       +        yylval.i = 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(*(p+1)){
       +                                        case '%':
       +                                                lgate();
       +                                                Bprint(&fout,"#define YYNEWLINE %d\n",'\n');
       +                                                Bprint(&fout,"yylex(void){\nint nstr; extern int yyprevious;\n");
       +                                                sectbegin = TRUE;
       +                                                i = treesize*(sizeof(*name)+sizeof(*left)+
       +                                                        sizeof(*right)+sizeof(*nullstr)+sizeof(*parent))+ALITTLEEXTRA;
       +                                                p = myalloc(i,1);
       +                                                if(p == 0)
       +                                                        error("Too little core for parse tree");
       +                                                free(p);
       +                                                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 && !isdigit(*p))p++;
       +                                                maxpos = atol((char*)p);
       +# ifdef DEBUG
       +                                                if (debug) print("positions (%%p) now %d\n",maxpos);
       +# endif
       +                                                if(report == 2)report = 1;
       +                                                continue;
       +                                        case 'n': case 'N':        /* has overridden number of states */
       +                                                while(*p && !isdigit(*p))p++;
       +                                                nstates = atol((char*)p);
       +# ifdef DEBUG
       +                                                if(debug)print( " 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 && !isdigit(*p))p++;
       +                                                treesize = atol((char*)p);
       +# ifdef DEBUG
       +                                                if (debug) print("treesize (%%e) now %d\n",treesize);
       +# endif
       +                                                if(report == 2)report = 1;
       +                                                continue;
       +                                        case 'o': case 'O':
       +                                                while (*p && !isdigit(*p))p++;
       +                                                outsize = atol((char*)p);
       +                                                if (report ==2) report=1;
       +                                                continue;
       +                                        case 'a': case 'A':                /* has overridden number of transitions */
       +                                                while(*p && !isdigit(*p))p++;
       +                                                if(report == 2)report = 1;
       +                                                ntrans = atol((char*)p);
       +# ifdef DEBUG
       +                                                if (debug)print("N. trans (%%a) now %d\n",ntrans);
       +# endif
       +                                                continue;
       +                                        case 'k': case 'K': /* overriden packed char classes */
       +                                                while (*p && !isdigit(*p))p++;
       +                                                if (report==2) report=1;
       +                                                free(pchar);
       +                                                pchlen = atol((char*)p);
       +# ifdef DEBUG
       +                                                if (debug) print( "Size classes (%%k) now %d\n",pchlen);
       +# endif
       +                                                pchar=pcptr=myalloc(pchlen, sizeof(*pchar));
       +                                                continue;
       +                                        case '{':
       +                                                lgate();
       +                                                while(getl(p) && strcmp((char*)p,"%}") != 0)
       +                                                        Bprint(&fout, "%s\n",(char*)p);
       +                                                if(p[0] == '%') continue;
       +                                                error("Premature eof");
       +                                        case 's': case 'S':                /* start conditions */
       +                                                lgate();
       +                                                while(*p && strchr(" \t,", *p) == 0) p++;
       +                                                n = TRUE;
       +                                                while(n){
       +                                                        while(*p && strchr(" \t,", *p)) p++;
       +                                                        t = p;
       +                                                        while(*p && strchr(" \t,", *p) == 0)p++;
       +                                                        if(!*p) n = FALSE;
       +                                                        *p++ = 0;
       +                                                        if (*t == 0) continue;
       +                                                        i = sptr*2;
       +                                                        Bprint(&fout,"#define %s %d\n",(char*)t,i);
       +                                                        strcpy((char*)sp, (char*)t);
       +                                                        sname[sptr++] = sp;
       +                                                        sname[sptr] = 0;        /* required by lookup */
       +                                                        if(sptr >= STARTSIZE)
       +                                                                error("Too many start conditions");
       +                                                        sp += strlen((char*)sp) + 1;
       +                                                        if(sp >= stchar+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();
       +                                        Bprint(&fout, "%s\n",(char*)p);
       +                                        continue;
       +                                default:                /* definition */
       +                                        while(*p && !isspace(*p)) p++;
       +                                        if(*p == 0)
       +                                                continue;
       +                                        prev = *p;
       +                                        *p = 0;
       +                                        bptr = p+1;
       +                                        yylval.cp = buf;
       +                                        if(isdigit(buf[0]))
       +                                                warning("Substitution strings may not begin with digits");
       +                                        return(freturn(STR));
       +                                }
       +                        }
       +                        /* still sect 1, but prev != '\n' */
       +                        else {
       +                                p = bptr;
       +                                while(*p && isspace(*p)) p++;
       +                                if(*p == 0)
       +                                        warning("No translation given - null string assumed");
       +                                strcpy((char*)token, (char*)p);
       +                                yylval.cp = 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;
       +                                Bprint(&fout,"case %d:\n",casecount);
       +                                if(cpyact())
       +                                        Bprint(&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) && strcmp("%}",(char*)buf) != 0)
       +                                                Bprint(&fout,"%s\n",(char*)buf);
       +                                        continue;
       +                                }
       +                                if(peek == '%'){
       +                                        gch();
       +                                        gch();
       +                                        x = DELIM;
       +                                        break;
       +                                }
       +                                goto character;
       +                        case '|':
       +                                if(peek == ' ' || peek == '\t' || peek == '\n'){
       +                                        Bprint(&fout,"%d\n",30000+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(isdigit(c=gch())){        /* iteration */
       +                                        iter = TRUE;
       +                                ieval:
       +                                        i = 0;
       +                                        while(isdigit(c)){
       +                                                token[i++] = c;
       +                                                c = gch();
       +                                        }
       +                                        token[i] = 0;
       +                                        yylval.i = atol((char*)token);
       +                                        munputc(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
       +                                                munputs(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((char*)xp, (char*)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.cp = t;
       +                                x = SCON;
       +                                break;
       +                        case '"':
       +                                i = 0;
       +                                while((c=gch()) && c != '"' && c != '\n'){
       +                                        if(c == '\\') c = usescape(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.i = token[0];
       +                                        x = CHAR;
       +                                } else {
       +                                        yylval.cp = 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(gch());
       +                                        symbol[c] = 1;
       +                                        j = c;
       +                                        if((c=gch()) == '-' && peek != ']'){                /* range specified */
       +                                                c = gch();
       +                                                if(c == '\\') c = usescape(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 = ccl;
       +                                while(p <ccptr && strcmp((char*)token,(char*)p) != 0)p++;
       +                                if(p < ccptr)        /* found it */
       +                                        yylval.cp = p;
       +                                else {
       +                                        yylval.cp = ccptr;
       +                                        strcpy((char*)ccptr,(char*)token);
       +                                        ccptr += strlen((char*)token) + 1;
       +                                        if(ccptr >= ccl+CCLSIZE)
       +                                                error("Too many large character classes");
       +                                }
       +                                cclinter(x==CCL);
       +                                break;
       +                        case '\\':
       +                                c = usescape(gch());
       +                        default:
       +                        character:
       +                                if(iter){        /* second part of an iteration */
       +                                        iter = FALSE;
       +                                        if('0' <= c && c <= '9')
       +                                                goto ieval;
       +                                }
       +                                if(isalpha(peek)){
       +                                        i = 0;
       +                                        yylval.cp = token;
       +                                        token[i++] = c;
       +                                        while(isalpha(peek))
       +                                                token[i++] = gch();
       +                                        if(peek == '?' || peek == '*' || peek == '+')
       +                                                munputc(token[--i]);
       +                                        token[i] = 0;
       +                                        if(i == 1){
       +                                                yylval.i = token[0];
       +                                                x = CHAR;
       +                                        }
       +                                        else x = STR;
       +                                } else {
       +                                        yylval.i = c;
       +                                        x = CHAR;
       +                                }
       +                        }
       +                        scon = FALSE;
       +                        if(x == SCON)scon = TRUE;
       +                        sectbegin = FALSE;
       +                        return(freturn(x));
       +                }
       +        }
       +        /* section three */
       +        ptail();
       +# ifdef DEBUG
       +        if(debug)
       +                Bprint(&fout,"\n/*this comes from section three - debug */\n");
       +# endif
       +        while(getl(buf) && !eof)
       +                Bprint(&fout,"%s\n",(char*)buf);
       +        return(freturn(0));
       +}
       +/* end of yylex */
       +# ifdef DEBUG
       +int
       +freturn(int i)
       +{
       +        if(yydebug) {
       +                print("now return ");
       +                if(i < NCH) allprint(i);
       +                else print("%d",i);
       +                printf("   yylval = ");
       +                switch(i){
       +                        case STR: case CCL: case NCCL:
       +                                strpt(yylval.cp);
       +                                break;
       +                        case CHAR:
       +                                allprint(yylval.i);
       +                                break;
       +                        default:
       +                                print("%d",yylval.i);
       +                                break;
       +                }
       +                print("\n");
       +        }
       +        return(i);
       +}
       +# endif
 (DIR) diff --git a/src/cmd/lex/sub1.c b/src/cmd/lex/sub1.c
       t@@ -0,0 +1,591 @@
       +# include "ldefs.h"
       +uchar *
       +getl(uchar *p)        /* return next line of input, throw away trailing '\n' */
       +        /* returns 0 if eof is had immediately */
       +{
       +        int c;
       +        uchar *s, *t;
       +
       +        t = s = p;
       +        while(((c = gch()) != 0) && c != '\n')
       +                *t++ = c;
       +        *t = 0;
       +        if(c == 0 && s == t) return((uchar *)0);
       +        prev = '\n';
       +        pres = '\n';
       +        return(s);
       +}
       +
       +void
       +printerr(char *type, char *fmt, va_list argl)
       +{
       +        char buf[1024];
       +
       +        if(!eof)fprint(errorf,"%d: ",yyline);
       +        fprint(errorf,"(%s) ", type);
       +        vseprint(buf, buf+sizeof(buf), fmt, argl);
       +        fprint(errorf, "%s\n", buf);
       +}
       +
       +
       +void
       +error(char *s,...)
       +{
       +        va_list argl;
       +
       +        va_start(argl, s);
       +        printerr("Error", s, argl);
       +        va_end(argl);
       +# ifdef DEBUG
       +        if(debug && sect != ENDSECTION) {
       +                sect1dump();
       +                sect2dump();
       +        }
       +# endif
       +        if(
       +# ifdef DEBUG
       +                debug ||
       +# endif
       +                report == 1) statistics();
       +        exits("error");        /* error return code */
       +}
       +
       +void
       +warning(char *s,...)
       +{
       +        va_list argl;
       +
       +        va_start(argl, s);
       +        printerr("Warning", s, argl);
       +        va_end(argl);
       +        Bflush(&fout);
       +}
       +
       +void
       +lgate(void)
       +{
       +        int fd;
       +
       +        if (lgatflg) return;
       +        lgatflg=1;
       +        if(foutopen == 0){
       +                fd = create("lex.yy.c", OWRITE, 0666);
       +                if(fd < 0)
       +                        error("Can't open lex.yy.c");
       +                Binit(&fout, fd, OWRITE);
       +                foutopen = 1;
       +                }
       +        phead1();
       +}
       +
       +void
       +cclinter(int sw)
       +{
       +                /* sw = 1 ==> ccl */
       +        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++;
       +                }
       +        }
       +}
       +
       +int
       +usescape(int c)
       +{
       +        int 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);
       +}
       +
       +int
       +lookup(uchar *s, uchar **t)
       +{
       +        int i;
       +        i = 0;
       +        while(*t){
       +                if(strcmp((char *)s, *(char **)t) == 0)
       +                        return(i);
       +                i++;
       +                t++;
       +        }
       +        return(-1);
       +}
       +
       +int
       +cpyact(void)
       +{ /* copy C action to the next ; or closing } */
       +        int brac, c, mth;
       +        int savline, sw;
       +
       +        brac = 0;
       +        sw = TRUE;
       +        savline = 0;
       +
       +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 ){
       +                        Bputc(&fout, c);
       +                        Bputc(&fout, '\n');
       +                        return(1);
       +                }
       +                break;
       +
       +case '{':
       +                brac++;
       +                savline=yyline;
       +                break;
       +
       +case '}':
       +                brac--;
       +                if( brac == 0 ){
       +                        Bputc(&fout, c);
       +                        Bputc(&fout, '\n');
       +                        return(1);
       +                }
       +                break;
       +
       +case '/':        /* look for comments */
       +                Bputc(&fout, c);
       +                c = gch();
       +                if( c != '*' ) goto swt;
       +
       +                /* it really is a comment */
       +
       +                Bputc(&fout, c);
       +                savline=yyline;
       +                while( c=gch() ){
       +                        if( c=='*' ){
       +                                Bputc(&fout, c);
       +                                if( (c=gch()) == '/' ) goto loop;
       +                        }
       +                        Bputc(&fout, c);
       +                }
       +                yyline=savline;
       +                error( "EOF inside comment" );
       +
       +case '\'':        /* character constant */
       +                mth = '\'';
       +                goto string;
       +
       +case '"':        /* character string */
       +                mth = '"';
       +
       +        string:
       +
       +                Bputc(&fout, c);
       +                while( c=gch() ){
       +                        if( c=='\\' ){
       +                                Bputc(&fout, c);
       +                                c=gch();
       +                        }
       +                        else if( c==mth ) goto loop;
       +                        Bputc(&fout, c);
       +                        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;
       +        Bputc(&fout, c);
       +        }
       +        error("Premature EOF");
       +        return(0);
       +}
       +
       +int
       +gch(void){
       +        int c;
       +        prev = pres;
       +        c = pres = peek;
       +        peek = pushptr > pushc ? *--pushptr : Bgetc(fin);
       +        if(peek == Beof && sargc > 1){
       +                Bterm(fin);
       +                fin = Bopen(sargv[fptr++],OREAD);
       +                if(fin == 0)
       +                        error("Cannot open file %s",sargv[fptr-1]);
       +                peek = Bgetc(fin);
       +                sargc--;
       +                sargv++;
       +        }
       +        if(c == Beof) {
       +                eof = TRUE;
       +                Bterm(fin);
       +                return(0);
       +        }
       +        if(c == '\n')yyline++;
       +        return(c);
       +}
       +
       +int
       +mn2(int a, int d, int 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++);
       +}
       +
       +int
       +mn1(int a, int d)
       +{
       +        name[tptr] = a;
       +        left[tptr] = d;
       +        parent[tptr] = 0;
       +        nullstr[tptr] = 0;
       +        switch(a){
       +        case RCCL:
       +        case RNCCL:
       +                if(strlen((char *)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++);
       +}
       +
       +int
       +mn0(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++);
       +}
       +
       +void
       +munputc(int p)
       +{
       +        *pushptr++ = peek;                /* watch out for this */
       +        peek = p;
       +        if(pushptr >= pushc+TOKENSIZE)
       +                error("Too many characters pushed");
       +}
       +
       +void
       +munputs(uchar *p)
       +{
       +        int i,j;
       +        *pushptr++ = peek;
       +        peek = p[0];
       +        i = strlen((char*)p);
       +        for(j = i-1; j>=1; j--)
       +                *pushptr++ = p[j];
       +        if(pushptr >= pushc+TOKENSIZE)
       +                error("Too many characters pushed");
       +}
       +
       +int
       +dupl(int n)
       +{
       +        /* duplicate the subtree whose root is n, return ptr to it */
       +        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
       +void
       +allprint(int c)
       +{
       +        switch(c){
       +                case 014:
       +                        print("\\f");
       +                        charc++;
       +                        break;
       +                case '\n':
       +                        print("\\n");
       +                        charc++;
       +                        break;
       +                case '\t':
       +                        print("\\t");
       +                        charc++;
       +                        break;
       +                case '\b':
       +                        print("\\b");
       +                        charc++;
       +                        break;
       +                case ' ':
       +                        print("\\\bb");
       +                        break;
       +                default:
       +                        if(!isprint(c)){
       +                                print("\\%-3o",c);
       +                                charc += 3;
       +                        } else 
       +                                print("%c", c);
       +                        break;
       +        }
       +        charc++;
       +}
       +
       +void
       +strpt(uchar *s)
       +{
       +        charc = 0;
       +        while(*s){
       +                allprint(*s++);
       +                if(charc > LINESIZE){
       +                        charc = 0;
       +                        print("\n\t");
       +                }
       +        }
       +}
       +
       +void
       +sect1dump(void)
       +{
       +        int i;
       +
       +        print("Sect 1:\n");
       +        if(def[0]){
       +                print("str        trans\n");
       +                i = -1;
       +                while(def[++i])
       +                        print("%s\t%s\n",def[i],subs[i]);
       +        }
       +        if(sname[0]){
       +                print("start names\n");
       +                i = -1;
       +                while(sname[++i])
       +                        print("%s\n",sname[i]);
       +        }
       +}
       +
       +void
       +sect2dump(void)
       +{
       +        print("Sect 2:\n");
       +        treedump();
       +}
       +
       +void
       +treedump(void)
       +{
       +        int t;
       +        uchar *p;
       +        print("treedump %d nodes:\n",tptr);
       +        for(t=0;t<tptr;t++){
       +                print("%4d ",t);
       +                parent[t] ? print("p=%4d",parent[t]) : print("      ");
       +                print("  ");
       +                if(name[t] < NCH)
       +                                allprint(name[t]);
       +                else switch(name[t]){
       +                        case RSTR:
       +                                print("%d ",left[t]);
       +                                allprint(right[t]);
       +                                break;
       +                        case RCCL:
       +                                print("ccl ");
       +                                strpt(left[t]);
       +                                break;
       +                        case RNCCL:
       +                                print("nccl ");
       +                                strpt(left[t]);
       +                                break;
       +                        case DIV:
       +                                print("/ %d %d",left[t],right[t]);
       +                                break;
       +                        case BAR:
       +                                print("| %d %d",left[t],right[t]);
       +                                break;
       +                        case RCAT:
       +                                print("cat %d %d",left[t],right[t]);
       +                                break;
       +                        case PLUS:
       +                                print("+ %d",left[t]);
       +                                break;
       +                        case STAR:
       +                                print("* %d",left[t]);
       +                                break;
       +                        case CARAT:
       +                                print("^ %d",left[t]);
       +                                break;
       +                        case QUEST:
       +                                print("? %d",left[t]);
       +                                break;
       +                        case RNULLS:
       +                                print("nullstring");
       +                                break;
       +                        case FINAL:
       +                                print("final %d",left[t]);
       +                                break;
       +                        case S1FINAL:
       +                                print("s1final %d",left[t]);        
       +                                break;
       +                        case S2FINAL:
       +                                print("s2final %d",left[t]);
       +                                break;
       +                        case RNEWE:
       +                                print("new %d %d",left[t],right[t]);
       +                                break;
       +                        case RSCON:
       +                                p = (uchar *)right[t];
       +                                print("start %s",sname[*p++-1]);
       +                                while(*p)
       +                                        print(", %s",sname[*p++-1]);
       +                                print(" %d",left[t]);
       +                                break;
       +                        default:
       +                                print("unknown %d %d %d",name[t],left[t],right[t]);
       +                                break;
       +                }
       +                if(nullstr[t])print("\t(null poss.)");
       +                print("\n");
       +        }
       +}
       +# endif
 (DIR) diff --git a/src/cmd/lex/sub2.c b/src/cmd/lex/sub2.c
       t@@ -0,0 +1,856 @@
       +# include "ldefs.h"
       +void
       +cfoll(int v)
       +{
       +        int i,j,k;
       +        uchar *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 = (uchar *)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] = (int)p;
       +                                name[v] = RCCL;        /* RNCCL eliminated */
       +# ifdef DEBUG
       +                                if(debug && *p){
       +                                        print("ccl %d: %d",v,*p++);
       +                                        while(*p)
       +                                                print(", %d",*p++);
       +                                        print("\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
       +        }
       +}
       +
       +# ifdef DEBUG
       +void
       +pfoll(void)
       +        {
       +        int i,k,*p;
       +        int j;
       +        /* print sets of chars which may follow positions */
       +        print("pos\tchars\n");
       +        for(i=0;i<tptr;i++)
       +                if(p=foll[i]){
       +                        j = *p++;
       +                        if(j >= 1){
       +                                print("%d:\t%d",i,*p++);
       +                                for(k=2;k<=j;k++)
       +                                        print(", %d",*p++);
       +                                print("\n");
       +                        }
       +                }
       +}
       +# endif
       +
       +void
       +add(int **array, int n)
       +{
       +        int i, *temp;
       +        uchar *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;
       +}
       +
       +void
       +follow(int v)
       +{
       +        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
       +        }
       +}
       +
       +void
       +first(int v)        /* calculate set of positions with v as root which can be active initially */
       +{
       +        int i;
       +        uchar *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 = (uchar *)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
       +        }
       +}
       +
       +void
       +cgoto(void)
       +{
       +        int i, j, s;
       +        int npos, curpos, n;
       +        int tryit;
       +        uchar tch[NCH];
       +        int tst[NCH];
       +        uchar *q;
       +
       +        /* generate initial state, for each start condition */
       +        Bprint(&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)
       +                                print("%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 = (uchar *)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){
       +                        print("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;
       +                                        print("\n\t");
       +                                }
       +                        }
       +                        print("\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;
       +        }
       +        Bprint(&fout,"0};\n");
       +}
       +
       +/*        Beware -- 70% of total CPU time is spent in this subroutine -
       +        if you don't believe me - try it yourself ! */
       +void
       +nextstate(int s, int c)
       +{
       +        int j, *newpos;
       +        uchar *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, (uchar *)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;
       +}
       +
       +int
       +notin(int n)
       +{        /* see if tmpstat occurs previously */
       +        int *j,k;
       +        uchar *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);
       +}
       +
       +void
       +packtrans(int st, uchar *tch, int *tst, int cnt, int tryit)
       +{
       +        /* 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 i,j,k;
       +        int cmin, cval, tcnt, diff, p, *ast;
       +        uchar *ach;
       +        int go[NCH], temp[NCH], c;
       +        int swork[NCH];
       +        uchar cwork[NCH];
       +        int upper;
       +
       +        rcount += cnt;
       +        cmin = -1;
       +        cval = NCH;
       +        ast = tst;
       +        ach = tch;
       +        /* try to pack transitions using ccl's */
       +        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) print("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;
       +                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)print("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":""));
       +}
       +
       +# ifdef DEBUG
       +void
       +pstate(int s)
       +{
       +        int *p,i,j;
       +        print("State %d:\n",s);
       +        p = state[s];
       +        i = *p++;
       +        if(i == 0) return;
       +        print("%4d",*p++);
       +        for(j = 1; j<i; j++){
       +                print(", %4d",*p++);
       +                if(j%30 == 0)print("\n");
       +        }
       +        print("\n");
       +        return;
       +}
       +# endif
       +
       +int
       +member(int d, uchar *t)
       +{
       +        int c;
       +        uchar *s;
       +
       +        c = d;
       +        s = t;
       +        c = cindex[c];
       +        while(*s)
       +                if(*s++ == c) return(1);
       +        return(0);
       +}
       +
       +# ifdef DEBUG
       +void
       +stprt(int i)
       +{
       +        int p, t;
       +
       +        print("State %d:",i);
       +        /* print actions, if any */
       +        t = atable[i];
       +        if(t != -1)print(" final");
       +        print("\n");
       +        if(cpackflg[i] == TRUE)print("backup char in use\n");
       +        if(sfall[i] != -1)print("fall back state %d\n",sfall[i]);
       +        p = gotof[i];
       +        if(p == -1) return;
       +        print("(%d transitions)\n",nexts[p]);
       +        while(nchar[p]){
       +                charc = 0;
       +                if(nexts[p+1] >= 0)
       +                        print("%d\t",nexts[p+1]);
       +                else print("err\t");
       +                allprint(nchar[p++]);
       +                while(nexts[p] == nexts[p+1] && nchar[p]){
       +                        if(charc > LINESIZE){
       +                                charc = 0;
       +                                print("\n\t");
       +                        }
       +                        allprint(nchar[p++]);
       +                }
       +                print("\n");
       +        }
       +        print("\n");
       +}
       +# endif
       +
       +void
       +acompute(int s)        /* compute action list = set of poss. actions */
       +{
       +        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) print("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
       +        Bprint(&fout,"/* actions for state %d */",s);
       +# endif
       +        Bputc(&fout, '\n');
       +        for(i=0;i<k;i++)
       +                if(temp[i] != 0){
       +                        Bprint(&fout,"%d,\n",temp[i]);
       +# ifdef DEBUG
       +                        if(debug)
       +                                print("%d ",temp[i]);
       +# endif
       +                        aptr++;
       +                }
       +        for(i=0;i<n;i++){                /* copy fall back actions - all neg */
       +                Bprint(&fout,"%d,\n",neg[i]);
       +                aptr++;
       +# ifdef DEBUG
       +                if(debug)print("%d ",neg[i]);
       +# endif
       +        }
       +# ifdef DEBUG
       +        if(debug)print("\n");
       +# endif
       +        Bprint(&fout,"0,\n");
       +        aptr++;
       +        return;
       +}
       +
       +# ifdef DEBUG
       +void
       +pccl(void) {
       +        /* print character class sets */
       +        int i, j;
       +
       +        print("char class intersection\n");
       +        for(i=0; i< ccount; i++){
       +                charc = 0;
       +                print("class %d:\n\t",i);
       +                for(j=1;j<NCH;j++)
       +                        if(cindex[j] == i){
       +                                allprint(j);
       +                                if(charc > LINESIZE){
       +                                        print("\n\t");
       +                                        charc = 0;
       +                                }
       +                        }
       +                print("\n");
       +        }
       +        charc = 0;
       +        print("match:\n");
       +        for(i=0;i<NCH;i++){
       +                allprint(match[i]);
       +                if(charc > LINESIZE){
       +                        print("\n");
       +                        charc = 0;
       +                }
       +        }
       +        print("\n");
       +        return;
       +}
       +# endif
       +
       +void
       +mkmatch(void)
       +{
       +        int i;
       +        uchar 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;
       +}
       +
       +void
       +layout(void)
       +{
       +        /* format and output final program's tables */
       +        int i, j, k;
       +        int  top, bot, startup, omin;
       +
       +        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;
       +# ifdef DEBUG
       +                if (debug) {
       +                        print("State %d: (layout)\n", i);
       +                        for(j=bot; j<=top;j++) {
       +                                print("  %o", nchar[j]);
       +                                if (j%10==0) print("\n");
       +                        }
       +                        print("\n");
       +                }
       +# endif
       +                while(verify[omin+NCH]) omin++;
       +                startup = omin;
       +# ifdef DEBUG
       +                if (debug) print("bot,top %d, %d startup begins %d\n",bot,top,startup);
       +# endif
       +                do {
       +                        startup += 1;
       +                        if(startup > outsize - NCH)
       +                                error("output table overflow");
       +                        for(j = bot; j<= top; j++){
       +                                k = startup + nchar[j];
       +                                if(verify[k])break;
       +                        }
       +                } while (j <= top);
       +                /* have found place */
       +# ifdef DEBUG
       +                if (debug) print(" 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 */
       +        Bprint(&fout,"# define YYTYPE %s\n",stnum+1 >= NCH ? "int" : "Uchar");
       +        Bprint(&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])
       +                                Bprint(&fout,"%d,%d,\t",verify[k],advance[k]);
       +                        else
       +                                Bprint(&fout,"0,0,\t");
       +                }
       +                Bputc(&fout, '\n');
       +        }
       +        Bprint(&fout,"0,0};\n");
       +
       +        /* put out yysvec */
       +
       +        Bprint(&fout,"struct yysvf yysvec[] = {\n");
       +        Bprint(&fout,"0,\t0,\t0,\n");
       +        for(i=0;i<=stnum;i++){        /* for each state */
       +                if(cpackflg[i])stoff[i] = -stoff[i];
       +                Bprint(&fout,"yycrank+%d,\t",stoff[i]);
       +                if(sfall[i] != -1)
       +                        Bprint(&fout,"yysvec+%d,\t", sfall[i]+1);        /* state + 1 */
       +                else Bprint(&fout,"0,\t\t");
       +                if(atable[i] != -1)
       +                        Bprint(&fout,"yyvstop+%d,",atable[i]);
       +                else Bprint(&fout,"0,\t");
       +# ifdef DEBUG
       +                Bprint(&fout,"\t\t/* state %d */",i);
       +# endif
       +                Bputc(&fout, '\n');
       +        }
       +        Bprint(&fout,"0,\t0,\t0};\n");
       +
       +        /* put out yymatch */
       +        
       +        Bprint(&fout,"struct yywork *yytop = yycrank+%d;\n",yytop);
       +        Bprint(&fout,"struct yysvf *yybgin = yysvec+1;\n");
       +        Bprint(&fout,"Uchar yymatch[] = {\n");
       +        for(i=0; i<NCH; i+=8){
       +                for(j=0; j<8; j++){
       +                        int fbch;
       +                        fbch = match[i+j];
       +                        if(isprint(fbch) && fbch != '\'' && fbch != '\\')
       +                                Bprint(&fout,"'%c' ,",fbch);
       +                        else Bprint(&fout,"0%-3o,",fbch);
       +                }
       +                Bputc(&fout, '\n');
       +        }
       +        Bprint(&fout,"0};\n");
       +        /* put out yyextra */
       +        Bprint(&fout,"Uchar yyextra[] = {\n");
       +        for(i=0;i<casecount;i+=8){
       +                for(j=0;j<8;j++)
       +                        Bprint(&fout, "%d,", i+j<NACTIONS ?
       +                                extra[i+j] : 0);
       +                Bputc(&fout, '\n');
       +        }
       +        Bprint(&fout,"0};\n");
       +}
       +
       +# ifdef PP
       +void
       +padd(int **array, int n)
       +{
       +        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);
       +}
       +# endif