URI:
       tyacc.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tyacc.c (59158B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <bio.h>
            4 #include <ctype.h>
            5 
            6 #define        Bungetrune        Bungetc                /* ok for now. */
            7 
            8 /*
            9  * all these are 32 bit
           10  */
           11 #define TBITSET                ((32+NTERMS)/32)        /* BOTCH?? +31 */
           12 #define BIT(a,i)        ((a)[(i)>>5] & (1<<((i)&037)))
           13 #define SETBIT(a,i)        ((a)[(i)>>5] |= (1<<((i)&037)))
           14 #define NWORDS(n)        (((n)+32)/32)
           15 
           16 char *PARSER = "#9/lib/yaccpar";
           17 char *PARSERS = "#9/lib/yaccpars";
           18 
           19 #define TEMPNAME        "y.tmp.XXXXXX"
           20 #define ACTNAME                "y.acts.XXXXXX"
           21 #define OFILE                "tab.c"
           22 #define FILEU                "output"
           23 #define FILED                "tab.h"
           24 #define FILEDEBUG        "debug"
           25 
           26 enum
           27 {
           28 /*
           29  * the following are adjustable
           30  * according to memory size
           31  */
           32         ACTSIZE                = 40000,
           33         MEMSIZE                = 40000,
           34         NSTATES                = 2000,
           35         NTERMS                = 511,
           36         NPROD                = 1600,
           37         NNONTERM        = 600,
           38         TEMPSIZE        = 2000,
           39         CNAMSZ                = 10000,
           40         LSETSIZE        = 2400,
           41         WSETSIZE        = 350,
           42 
           43         NAMESIZE        = 50,
           44         NTYPES                = 63,
           45         ISIZE                = 400,
           46 
           47         PRIVATE                = 0xE000,        /* unicode private use */
           48 
           49         /* relationships which must hold:
           50                 TBITSET ints must hold NTERMS+1 bits...
           51                 WSETSIZE >= NNONTERM
           52                 LSETSIZE >= NNONTERM
           53                 TEMPSIZE >= NTERMS + NNONTERM + 1
           54                 TEMPSIZE >= NSTATES
           55         */
           56 
           57         NTBASE                = 010000,
           58         ERRCODE                = 8190,
           59         ACCEPTCODE        = 8191,
           60 
           61         NOASC                = 0,        /* no assoc. */
           62         LASC                = 1,        /* left assoc. */
           63         RASC                = 2,        /* right assoc. */
           64         BASC                = 3,        /* binary assoc. */
           65 
           66         /* flags for state generation */
           67 
           68         DONE                = 0,
           69         MUSTDO                = 1,
           70         MUSTLOOKAHEAD        = 2,
           71 
           72         /* flags for a rule having an action, and being reduced */
           73 
           74         ACTFLAG                = 04,
           75         REDFLAG                = 010,
           76 
           77         /* output parser flags */
           78         YYFLAG1                = -1000,
           79 
           80         /* parse tokens */
           81         IDENTIFIER        = PRIVATE,
           82         MARK,
           83         TERM,
           84         LEFT,
           85         RIGHT,
           86         BINARY,
           87         PREC,
           88         LCURLY,
           89         IDENTCOLON,
           90         NUMBER,
           91         START,
           92         TYPEDEF,
           93         TYPENAME,
           94         UNION,
           95 
           96         ENDFILE                = 0,
           97 
           98         EMPTY                = 1,
           99         WHOKNOWS        = 0,
          100         OK                = 1,
          101         NOMORE                = -1000
          102 };
          103 
          104         /* macros for getting associativity and precedence levels */
          105 
          106 #define ASSOC(i)        ((i)&03)
          107 #define PLEVEL(i)        (((i)>>4)&077)
          108 #define TYPE(i)                (((i)>>10)&077)
          109 
          110         /* macros for setting associativity and precedence levels */
          111 
          112 #define SETASC(i,j)        i |= j
          113 #define SETPLEV(i,j)        i |= (j<<4)
          114 #define SETTYPE(i,j)        i |= (j<<10)
          115 
          116         /* looping macros */
          117 
          118 #define TLOOP(i)        for(i=1; i<=ntokens; i++)
          119 #define NTLOOP(i)        for(i=0; i<=nnonter; i++)
          120 #define PLOOP(s,i)        for(i=s; i<nprod; i++)
          121 #define SLOOP(i)        for(i=0; i<nstate; i++)
          122 #define WSBUMP(x)        x++
          123 #define WSLOOP(s,j)        for(j=s; j<cwp; j++)
          124 #define ITMLOOP(i,p,q)        for(q=pstate[i+1], p=pstate[i]; p<q; p++)
          125 #define SETLOOP(i)        for(i=0; i<tbitset; i++)
          126 
          127         /* command to clobber tempfiles after use */
          128 
          129 #define        ZAPFILE(x)        if(x) remove(x)
          130 
          131         /* I/O descriptors */
          132 
          133 Biobuf*        faction;        /* file for saving actions */
          134 Biobuf*        fdefine;        /* file for #defines */
          135 Biobuf*        fdebug;                /* y.debug for strings for debugging */
          136 Biobuf*        ftable;                /* y.tab.c file */
          137 Biobuf*        ftemp;                /* tempfile to pass 2 */
          138 Biobuf*        finput;                /* input file */
          139 Biobuf*        foutput;        /* y.output file */
          140 
          141         /* communication variables between various I/O routines */
          142 
          143 char*        infile;                        /* input file name */
          144 int        numbval;                /* value of an input number */
          145 char        tokname[NAMESIZE+4];        /* input token name, slop for runes and 0 */
          146 
          147         /* structure declarations */
          148 
          149 typedef
          150 struct
          151 {
          152         int        lset[TBITSET];
          153 } Lkset;
          154 
          155 typedef
          156 struct
          157 {
          158         int*        pitem;
          159         Lkset*        look;
          160 } Item;
          161 
          162 typedef
          163 struct
          164 {
          165         char*        name;
          166         int        value;
          167 } Symb;
          168 
          169 typedef
          170 struct
          171 {
          172         int*        pitem;
          173         int        flag;
          174         Lkset        ws;
          175 } Wset;
          176 
          177         /* storage of names */
          178 
          179 char        cnames[CNAMSZ];                /* place where token and nonterminal names are stored */
          180 int        cnamsz = CNAMSZ;        /* size of cnames */
          181 char*        cnamp = cnames;                /* place where next name is to be put in */
          182 int        ndefout = 4;                /* number of defined symbols output */
          183 char*        tempname;
          184 char*        actname;
          185 char        ttempname[] = TEMPNAME;
          186 char        tactname[] = ACTNAME;
          187 char*        parser;
          188 char*        yydebug;
          189 int        yyarg;
          190 int        yyline = 1;
          191 
          192         /* storage of types */
          193 int        ntypes;                        /* number of types defined */
          194 char*        typeset[NTYPES];        /* pointers to type tags */
          195 
          196         /* token information */
          197 
          198 int        ntokens = 0 ;                /* number of tokens */
          199 Symb        tokset[NTERMS];
          200 int        toklev[NTERMS];                /* vector with the precedence of the terminals */
          201 
          202         /* nonterminal information */
          203 
          204 int        nnonter = -1;                /* the number of nonterminals */
          205 Symb        nontrst[NNONTERM];
          206 int        start;                        /* start symbol */
          207 
          208         /* assigned token type values */
          209 int        extval = 0;
          210 
          211 char*        ytabc = OFILE;        /* name of y.tab.c */
          212 
          213         /* grammar rule information */
          214 
          215 int        mem0[MEMSIZE] ;                /* production storage */
          216 int*        mem = mem0;
          217 int        nprod = 1;                /* number of productions */
          218 int*        prdptr[NPROD];                /* pointers to descriptions of productions */
          219 int        levprd[NPROD];                /* precedence levels for the productions */
          220 int        rlines[NPROD];                /* line number for this rule */
          221 
          222         /* state information */
          223 
          224 int        nstate = 0;                /* number of states */
          225 Item*        pstate[NSTATES+2];        /* pointers to the descriptions of the states */
          226 int        tystate[NSTATES];        /* contains type information about the states */
          227 int        defact[NSTATES];        /* the default actions of states */
          228 int        tstates[NTERMS];        /* states generated by terminal gotos */
          229 int        ntstates[NNONTERM];         /* states generated by nonterminal gotos */
          230 int        mstates[NSTATES];        /* chain of overflows of term/nonterm generation lists  */
          231 int        lastred;                 /* the number of the last reduction of a state */
          232 
          233         /* lookahead set information */
          234 
          235 Lkset        lkst[LSETSIZE];
          236 int        nolook;                        /* flag to turn off lookahead computations */
          237 int        tbitset;                /* size of lookahead sets */
          238 int        nlset = 0;                /* next lookahead set index */
          239 int        nolook = 0;                /* flag to suppress lookahead computations */
          240 Lkset        clset;                  /* temporary storage for lookahead computations */
          241 
          242         /* working set information */
          243 
          244 Wset        wsets[WSETSIZE];
          245 Wset*        cwp;
          246 
          247         /* storage for action table */
          248 
          249 int        amem[ACTSIZE];                /* action table storage */
          250 int*        memp = amem;                /* next free action table position */
          251 int        indgo[NSTATES];                /* index to the stored goto table */
          252 
          253         /* temporary vector, indexable by states, terms, or ntokens */
          254 
          255 int        temp1[TEMPSIZE];        /* temporary storage, indexed by terms + ntokens or states */
          256 int        lineno = 1;                /* current input line number */
          257 int        fatfl = 1;                  /* if on, error is fatal */
          258 int        nerrors = 0;                /* number of errors */
          259 
          260         /* statistics collection variables */
          261 
          262 int        zzgoent;
          263 int        zzgobest;
          264 int        zzacent;
          265 int        zzexcp;
          266 int        zzclose;
          267 int        zzrrconf;
          268 int        zzsrconf;
          269 
          270 int*        ggreed = lkst[0].lset;
          271 int*        pgo = wsets[0].ws.lset;
          272 int*        yypgo = &nontrst[0].value;
          273 
          274 int        maxspr = 0;                  /* maximum spread of any entry */
          275 int        maxoff = 0;                  /* maximum offset into a array */
          276 int*        pmem = mem0;
          277 int*        maxa;
          278 int        nxdb = 0;
          279 int        adb = 0;
          280 
          281 
          282         /* storage for information about the nonterminals */
          283 
          284 int**        pres[NNONTERM+2];          /* vector of pointers to productions yielding each nonterminal */
          285 Lkset*        pfirst[NNONTERM+2];        /* vector of pointers to first sets for each nonterminal */
          286 int        pempty[NNONTERM+1];        /* vector of nonterminals nontrivially deriving e */
          287 
          288         /* random stuff picked out from between functions */
          289 
          290 int        indebug = 0;
          291 Wset*        zzcwp = wsets;
          292 int        zzgoent = 0;
          293 int        zzgobest = 0;
          294 int        zzacent = 0;
          295 int        zzexcp = 0;
          296 int        zzclose = 0;
          297 int        zzsrconf = 0;
          298 int*        zzmemsz = mem0;
          299 int        zzrrconf = 0;
          300 int        pidebug = 0;                /* debugging flag for putitem */
          301 int        gsdebug = 0;
          302 int        cldebug = 0;                /* debugging flag for closure */
          303 int        pkdebug = 0;
          304 int        g2debug = 0;
          305 
          306 struct
          307 {
          308         char*        name;
          309         long        value;
          310 } resrv[] =
          311 {
          312         "binary",        BINARY,
          313         "left",                LEFT,
          314         "nonassoc",        BINARY,
          315         "prec",                PREC,
          316         "right",        RIGHT,
          317         "start",        START,
          318         "term",                TERM,
          319         "token",        TERM,
          320         "type",                TYPEDEF,
          321         "union",        UNION,
          322         0,
          323 };
          324 
          325         /* define functions */
          326 
          327 void        main(int, char**);
          328 void        others(void);
          329 char*        chcopy(char*, char*);
          330 char*        writem(int*);
          331 char*        symnam(int);
          332 void        summary(void);
          333 void        error(char*, ...);
          334 void        aryfil(int*, int, int);
          335 int        setunion(int*, int*);
          336 void        prlook(Lkset*);
          337 void        cpres(void);
          338 void        cpfir(void);
          339 int        state(int);
          340 void        putitem(int*, Lkset*);
          341 void        cempty(void);
          342 void        stagen(void);
          343 void        closure(int);
          344 Lkset*        flset(Lkset*);
          345 void        cleantmp(void);
          346 void        intr(void);
          347 void        setup(int, char**);
          348 void        finact(void);
          349 int        defin(int, char*);
          350 void        defout(int);
          351 char*        cstash(char*);
          352 int        isvalidchar(long);
          353 long        gettok(void);
          354 int        fdtype(int);
          355 int        chfind(int, char*);
          356 void        cpyunion(void);
          357 void        cpycode(void);
          358 int        skipcom(void);
          359 void        cpyact(int);
          360 void        openup(char*, int, int, int, char*);
          361 void        output(void);
          362 int        apack(int*, int);
          363 void        go2out(void);
          364 void        go2gen(int);
          365 void        precftn(int, int, int);
          366 void        wract(int);
          367 void        wrstate(int);
          368 void        warray(char*, int*, int);
          369 void        hideprod(void);
          370 void        callopt(void);
          371 void        gin(int);
          372 void        stin(int);
          373 int        nxti(void);
          374 void        osummary(void);
          375 void        aoutput(void);
          376 void        arout(char*, int*, int);
          377 int        gtnm(void);
          378 
          379 void
          380 main(int argc, char *argv[])
          381 {
          382         PARSER = unsharp(PARSER);
          383         PARSERS = unsharp(PARSERS);
          384         parser = PARSER;
          385 
          386         setup(argc, argv);        /* initialize and read productions */
          387         tbitset = NWORDS(ntokens);
          388         cpres();                /* make table of which productions yield a given nonterminal */
          389         cempty();                /* make a table of which nonterminals can match the empty string */
          390         cpfir();                /* make a table of firsts of nonterminals */
          391         stagen();                /* generate the states */
          392         output();                /* write the states and the tables */
          393         go2out();
          394         hideprod();
          395         summary();
          396         callopt();
          397         others();
          398         exits(0);
          399 }
          400 
          401 /*
          402  * put out other arrays, copy the parsers
          403  */
          404 void
          405 others(void)
          406 {
          407         int c, i, j;
          408 
          409         finput = Bopen(parser, OREAD);
          410         if(finput == 0)
          411                 error("cannot open parser %s: %r", parser);
          412         warray("yyr1", levprd, nprod);
          413         aryfil(temp1, nprod, 0);
          414         PLOOP(1, i)
          415                 temp1[i] = prdptr[i+1]-prdptr[i]-2;
          416         warray("yyr2", temp1, nprod);
          417 
          418         aryfil(temp1, nstate, -1000);
          419         TLOOP(i)
          420                 for(j=tstates[i]; j!=0; j=mstates[j])
          421                         temp1[j] = i;
          422         NTLOOP(i)
          423                 for(j=ntstates[i]; j!=0; j=mstates[j])
          424                         temp1[j] = -i;
          425         warray("yychk", temp1, nstate);
          426         warray("yydef", defact, nstate);
          427 
          428         /* put out token translation tables */
          429         /* table 1 has 0-256 */
          430         aryfil(temp1, 256, 0);
          431         c = 0;
          432         TLOOP(i) {
          433                 j = tokset[i].value;
          434                 if(j >= 0 && j < 256) {
          435                         if(temp1[j]) {
          436                                 print("yacc bug -- cant have 2 different Ts with same value\n");
          437                                 print("        %s and %s\n", tokset[i].name, tokset[temp1[j]].name);
          438                                 nerrors++;
          439                         }
          440                         temp1[j] = i;
          441                         if(j > c)
          442                                 c = j;
          443                 }
          444         }
          445         warray("yytok1", temp1, c+1);
          446 
          447         /* table 2 has PRIVATE-PRIVATE+256 */
          448         aryfil(temp1, 256, 0);
          449         c = 0;
          450         TLOOP(i) {
          451                 j = tokset[i].value - PRIVATE;
          452                 if(j >= 0 && j < 256) {
          453                         if(temp1[j]) {
          454                                 print("yacc bug -- cant have 2 different Ts with same value\n");
          455                                 print("        %s and %s\n", tokset[i].name, tokset[temp1[j]].name);
          456                                 nerrors++;
          457                         }
          458                         temp1[j] = i;
          459                         if(j > c)
          460                                 c = j;
          461                 }
          462         }
          463         warray("yytok2", temp1, c+1);
          464 
          465         /* table 3 has everything else */
          466         Bprint(ftable, "static\tconst\tlong        yytok3[] =\n{\n");
          467         c = 0;
          468         TLOOP(i) {
          469                 j = tokset[i].value;
          470                 if(j >= 0 && j < 256)
          471                         continue;
          472                 if(j >= PRIVATE && j < 256+PRIVATE)
          473                         continue;
          474 
          475                 Bprint(ftable, "%4d,%4d,", j, i);
          476                 c++;
          477                 if(c%5 == 0)
          478                         Bprint(ftable, "\n");
          479         }
          480         Bprint(ftable, "%4d\n};\n", 0);
          481 
          482         /* copy parser text */
          483         while((c=Bgetrune(finput)) != Beof) {
          484                 if(c == '$') {
          485                         if((c = Bgetrune(finput)) != 'A')
          486                                 Bputrune(ftable, '$');
          487                         else { /* copy actions */
          488                                 faction = Bopen(actname, OREAD);
          489                                 if(faction == 0)
          490                                         error("cannot reopen action tempfile");
          491                                 while((c=Bgetrune(faction)) != Beof)
          492                                         Bputrune(ftable, c);
          493                                 Bterm(faction);
          494                                 ZAPFILE(actname);
          495                                 c = Bgetrune(finput);
          496                         }
          497                 }
          498                 Bputrune(ftable, c);
          499         }
          500         Bterm(ftable);
          501 }
          502 
          503 /*
          504  * copies string q into p, returning next free char ptr
          505  */
          506 char*
          507 chcopy(char* p, char* q)
          508 {
          509         int c;
          510 
          511         while(c = *q) {
          512                 if(c == '"')
          513                         *p++ = '\\';
          514                 *p++ = c;
          515                 q++;
          516         }
          517         *p = 0;
          518         return p;
          519 }
          520 
          521 /*
          522  * creates output string for item pointed to by pp
          523  */
          524 char*
          525 writem(int *pp)
          526 {
          527         int i,*p;
          528         static char sarr[ISIZE];
          529         char* q;
          530 
          531         for(p=pp; *p>0; p++)
          532                 ;
          533         p = prdptr[-*p];
          534         q = chcopy(sarr, nontrst[*p-NTBASE].name);
          535         q = chcopy(q, ": ");
          536         for(;;) {
          537                 *q = ' ';
          538                 p++;
          539                 if(p == pp)
          540                         *q = '.';
          541                 q++;
          542                 *q = '\0';
          543                 i = *p;
          544                 if(i <= 0)
          545                         break;
          546                 q = chcopy(q, symnam(i));
          547                 if(q > &sarr[ISIZE-30])
          548                         error("item too big");
          549         }
          550 
          551         /* an item calling for a reduction */
          552         i = *pp;
          553         if(i < 0 ) {
          554                 q = chcopy(q, "    (");
          555                 sprint(q, "%d)", -i);
          556         }
          557         return sarr;
          558 }
          559 
          560 /*
          561  * return a pointer to the name of symbol i
          562  */
          563 char*
          564 symnam(int i)
          565 {
          566         char* cp;
          567 
          568         cp = (i >= NTBASE)? nontrst[i-NTBASE].name: tokset[i].name;
          569         if(*cp == ' ')
          570                 cp++;
          571         return cp;
          572 }
          573 
          574 /*
          575  * output the summary on y.output
          576  */
          577 void
          578 summary(void)
          579 {
          580 
          581         if(foutput != 0) {
          582                 Bprint(foutput, "\n%d/%d terminals, %d/%d nonterminals\n",
          583                         ntokens, NTERMS, nnonter, NNONTERM);
          584                 Bprint(foutput, "%d/%d grammar rules, %d/%d states\n",
          585                         nprod, NPROD, nstate, NSTATES);
          586                 Bprint(foutput, "%d shift/reduce, %d reduce/reduce conflicts reported\n",
          587                         zzsrconf, zzrrconf);
          588                 Bprint(foutput, "%d/%d working sets used\n",
          589                         (int)(zzcwp-wsets), WSETSIZE);
          590                 Bprint(foutput, "memory: states,etc. %d/%d, parser %d/%d\n",
          591                         (int)(zzmemsz-mem0), MEMSIZE, (int)(memp-amem), ACTSIZE);
          592                 Bprint(foutput, "%d/%d distinct lookahead sets\n", nlset, LSETSIZE);
          593                 Bprint(foutput, "%d extra closures\n", zzclose - 2*nstate);
          594                 Bprint(foutput, "%d shift entries, %d exceptions\n", zzacent, zzexcp);
          595                 Bprint(foutput, "%d goto entries\n", zzgoent);
          596                 Bprint(foutput, "%d entries saved by goto default\n", zzgobest);
          597         }
          598         if(zzsrconf != 0 || zzrrconf != 0) {
          599                 print("\nconflicts: ");
          600                 if(zzsrconf)
          601                         print("%d shift/reduce", zzsrconf);
          602                 if(zzsrconf && zzrrconf)
          603                         print(", ");
          604                 if(zzrrconf)
          605                         print("%d reduce/reduce", zzrrconf);
          606                 print("\n");
          607         }
          608         if(ftemp != 0) {
          609                 Bterm(ftemp);
          610                 ftemp = 0;
          611         }
          612         if(fdefine != 0) {
          613                 Bterm(fdefine);
          614                 fdefine = 0;
          615         }
          616 }
          617 
          618 /*
          619  * write out error comment -- NEEDS WORK
          620  */
          621 void
          622 error(char *s, ...)
          623 {
          624         va_list arg;
          625 
          626         nerrors++;
          627         fprint(2, "\n fatal error:");
          628         va_start(arg, s);
          629         vfprint(2, s, arg);
          630         va_end(arg);
          631         fprint(2, ", %s:%d\n", infile, lineno);
          632         if(!fatfl)
          633                 return;
          634         summary();
          635         cleantmp();
          636         exits("error");
          637 }
          638 
          639 /*
          640  * set elements 0 through n-1 to c
          641  */
          642 void
          643 aryfil(int *v, int n, int c)
          644 {
          645         int i;
          646 
          647         for(i=0; i<n; i++)
          648                 v[i] = c;
          649 }
          650 
          651 /*
          652  * set a to the union of a and b
          653  * return 1 if b is not a subset of a, 0 otherwise
          654  */
          655 int
          656 setunion(int *a, int *b)
          657 {
          658         int i, x, sub;
          659 
          660         sub = 0;
          661         SETLOOP(i) {
          662                 x = *a;
          663                 *a |= *b;
          664                 if(*a != x)
          665                         sub = 1;
          666                 a++;
          667                 b++;
          668         }
          669         return sub;
          670 }
          671 
          672 void
          673 prlook(Lkset* p)
          674 {
          675         int j, *pp;
          676 
          677         pp = p->lset;
          678         if(pp == 0)
          679                 Bprint(foutput, "\tNULL");
          680         else {
          681                 Bprint(foutput, " { ");
          682                 TLOOP(j)
          683                         if(BIT(pp,j))
          684                                 Bprint(foutput, "%s ", symnam(j));
          685                 Bprint(foutput, "}");
          686         }
          687 }
          688 
          689 /*
          690  * compute an array with the beginnings of  productions yielding given nonterminals
          691  * The array pres points to these lists
          692  * the array pyield has the lists: the total size is only NPROD+1
          693  */
          694 void
          695 cpres(void)
          696 {
          697         int c, j, i, **pmem;
          698         static int *pyield[NPROD];
          699 
          700         pmem = pyield;
          701         NTLOOP(i) {
          702                 c = i+NTBASE;
          703                 pres[i] = pmem;
          704                 fatfl = 0;          /* make undefined  symbols  nonfatal */
          705                 PLOOP(0, j)
          706                         if(*prdptr[j] == c)
          707                                 *pmem++ =  prdptr[j]+1;
          708                 if(pres[i] == pmem)
          709                         error("nonterminal %s not defined!", nontrst[i].name);
          710         }
          711         pres[i] = pmem;
          712         fatfl = 1;
          713         if(nerrors) {
          714                 summary();
          715                 cleantmp();
          716                 exits("error");
          717         }
          718         if(pmem != &pyield[nprod])
          719                 error("internal Yacc error: pyield %d", pmem-&pyield[nprod]);
          720 }
          721 
          722 /*
          723  * compute an array with the first of nonterminals
          724  */
          725 void
          726 cpfir(void)
          727 {
          728         int *p, **s, i, **t, ch, changes;
          729 
          730         zzcwp = &wsets[nnonter];
          731         NTLOOP(i) {
          732                 aryfil(wsets[i].ws.lset, tbitset, 0);
          733                 t = pres[i+1];
          734                 /* initially fill the sets */
          735                 for(s=pres[i]; s<t; ++s)
          736                         for(p = *s; (ch = *p) > 0; ++p) {
          737                                 if(ch < NTBASE) {
          738                                         SETBIT(wsets[i].ws.lset, ch);
          739                                         break;
          740                                 }
          741                                 if(!pempty[ch-NTBASE])
          742                                         break;
          743                         }
          744         }
          745 
          746         /* now, reflect transitivity */
          747         changes = 1;
          748         while(changes) {
          749                 changes = 0;
          750                 NTLOOP(i) {
          751                         t = pres[i+1];
          752                         for(s = pres[i]; s < t; ++s)
          753                                 for(p = *s; (ch = (*p-NTBASE)) >= 0; ++p) {
          754                                         changes |= setunion(wsets[i].ws.lset, wsets[ch].ws.lset);
          755                                         if(!pempty[ch])
          756                                                 break;
          757                                 }
          758                 }
          759         }
          760 
          761         NTLOOP(i)
          762                 pfirst[i] = flset(&wsets[i].ws);
          763         if(!indebug)
          764                 return;
          765         if(foutput != 0)
          766                 NTLOOP(i) {
          767                         Bprint(foutput, "\n%s: ", nontrst[i].name);
          768                         prlook(pfirst[i]);
          769                         Bprint(foutput, " %d\n", pempty[i]);
          770                 }
          771 }
          772 
          773 /*
          774  * sorts last state,and sees if it equals earlier ones. returns state number
          775  */
          776 int
          777 state(int c)
          778 {
          779         Item *p1, *p2, *k, *l, *q1, *q2;
          780         int size1, size2, i;
          781 
          782         p1 = pstate[nstate];
          783         p2 = pstate[nstate+1];
          784         if(p1 == p2)
          785                 return 0;        /* null state */
          786         /* sort the items */
          787         for(k = p2-1; k > p1; k--)        /* make k the biggest */
          788                 for(l = k-1; l >= p1; --l)
          789                         if(l->pitem > k->pitem) {
          790                                 int *s;
          791                                 Lkset *ss;
          792 
          793                                 s = k->pitem;
          794                                 k->pitem = l->pitem;
          795                                 l->pitem = s;
          796                                 ss = k->look;
          797                                 k->look = l->look;
          798                                 l->look = ss;
          799                         }
          800         size1 = p2 - p1;        /* size of state */
          801 
          802         for(i = (c>=NTBASE)? ntstates[c-NTBASE]: tstates[c]; i != 0; i = mstates[i]) {
          803                 /* get ith state */
          804                 q1 = pstate[i];
          805                 q2 = pstate[i+1];
          806                 size2 = q2 - q1;
          807                 if(size1 != size2)
          808                         continue;
          809                 k = p1;
          810                 for(l = q1; l < q2; l++) {
          811                         if(l->pitem != k->pitem)
          812                                 break;
          813                         k++;
          814                 }
          815                 if(l != q2)
          816                         continue;
          817                 /* found it */
          818                 pstate[nstate+1] = pstate[nstate];        /* delete last state */
          819                 /* fix up lookaheads */
          820                 if(nolook)
          821                         return i;
          822                 for(l = q1, k = p1; l < q2; ++l, ++k ) {
          823                         int s;
          824 
          825                         SETLOOP(s)
          826                                 clset.lset[s] = l->look->lset[s];
          827                         if(setunion(clset.lset, k->look->lset)) {
          828                                 tystate[i] = MUSTDO;
          829                                 /* register the new set */
          830                                 l->look = flset( &clset );
          831                         }
          832                 }
          833                 return i;
          834         }
          835         /* state is new */
          836         if(nolook)
          837                 error("yacc state/nolook error");
          838         pstate[nstate+2] = p2;
          839         if(nstate+1 >= NSTATES)
          840                 error("too many states");
          841         if(c >= NTBASE) {
          842                 mstates[nstate] = ntstates[c-NTBASE];
          843                 ntstates[c-NTBASE] = nstate;
          844         } else {
          845                 mstates[nstate] = tstates[c];
          846                 tstates[c] = nstate;
          847         }
          848         tystate[nstate] = MUSTDO;
          849         return nstate++;
          850 }
          851 
          852 void
          853 putitem(int *ptr, Lkset *lptr)
          854 {
          855         Item *j;
          856 
          857         if(pidebug && foutput != 0)
          858                 Bprint(foutput, "putitem(%s), state %d\n", writem(ptr), nstate);
          859         j = pstate[nstate+1];
          860         j->pitem = ptr;
          861         if(!nolook)
          862                 j->look = flset(lptr);
          863         pstate[nstate+1] = ++j;
          864         if((int*)j > zzmemsz) {
          865                 zzmemsz = (int*)j;
          866                 if(zzmemsz >=  &mem0[MEMSIZE])
          867                         error("out of state space");
          868         }
          869 }
          870 
          871 /*
          872  * mark nonterminals which derive the empty string
          873  * also, look for nonterminals which don't derive any token strings
          874  */
          875 void
          876 cempty(void)
          877 {
          878 
          879         int i, *p;
          880 
          881         /* first, use the array pempty to detect productions that can never be reduced */
          882         /* set pempty to WHONOWS */
          883         aryfil(pempty, nnonter+1, WHOKNOWS);
          884 
          885         /* now, look at productions, marking nonterminals which derive something */
          886 more:
          887         PLOOP(0, i) {
          888                 if(pempty[*prdptr[i] - NTBASE])
          889                         continue;
          890                 for(p = prdptr[i]+1; *p >= 0; ++p)
          891                         if(*p >= NTBASE && pempty[*p-NTBASE] == WHOKNOWS)
          892                                 break;
          893                 /* production can be derived */
          894                 if(*p < 0) {
          895                         pempty[*prdptr[i]-NTBASE] = OK;
          896                         goto more;
          897                 }
          898         }
          899 
          900         /* now, look at the nonterminals, to see if they are all OK */
          901         NTLOOP(i) {
          902                 /* the added production rises or falls as the start symbol ... */
          903                 if(i == 0)
          904                         continue;
          905                 if(pempty[i] != OK) {
          906                         fatfl = 0;
          907                         error("nonterminal %s never derives any token string", nontrst[i].name);
          908                 }
          909         }
          910 
          911         if(nerrors) {
          912                 summary();
          913                 cleantmp();
          914                 exits("error");
          915         }
          916 
          917         /* now, compute the pempty array, to see which nonterminals derive the empty string */
          918         /* set pempty to WHOKNOWS */
          919         aryfil( pempty, nnonter+1, WHOKNOWS);
          920 
          921         /* loop as long as we keep finding empty nonterminals */
          922 
          923 again:
          924         PLOOP(1, i) {
          925                 /* not known to be empty */
          926                 if(pempty[*prdptr[i]-NTBASE] == WHOKNOWS) {
          927                         for(p = prdptr[i]+1; *p >= NTBASE && pempty[*p-NTBASE] == EMPTY ; ++p)
          928                                 ;
          929                         /* we have a nontrivially empty nonterminal */
          930                         if(*p < 0) {
          931                                 pempty[*prdptr[i]-NTBASE] = EMPTY;
          932                                 /* got one ... try for another */
          933                                 goto again;
          934                         }
          935                 }
          936         }
          937 }
          938 
          939 /*
          940  * generate the states
          941  */
          942 void
          943 stagen(void)
          944 {
          945 
          946         int c, i, j, more;
          947         Wset *p, *q;
          948 
          949         /* initialize */
          950         nstate = 0;
          951 
          952         /* THIS IS FUNNY from the standpoint of portability
          953          * it represents the magic moment when the mem0 array, which has
          954          * been holding the productions, starts to hold item pointers, of a
          955          * different type...
          956          * someday, alloc should be used to allocate all this stuff... for now, we
          957          * accept that if pointers don't fit in integers, there is a problem...
          958          */
          959 
          960         pstate[0] = pstate[1] = (Item*)mem;
          961         aryfil(clset.lset, tbitset, 0);
          962         putitem(prdptr[0]+1, &clset);
          963         tystate[0] = MUSTDO;
          964         nstate = 1;
          965         pstate[2] = pstate[1];
          966 
          967         aryfil(amem, ACTSIZE, 0);
          968 
          969         /* now, the main state generation loop */
          970         for(more=1; more;) {
          971                 more = 0;
          972                 SLOOP(i) {
          973                         if(tystate[i] != MUSTDO)
          974                                 continue;
          975                         tystate[i] = DONE;
          976                         aryfil(temp1, nnonter+1, 0);
          977                         /* take state i, close it, and do gotos */
          978                         closure(i);
          979                         /* generate goto's */
          980                         WSLOOP(wsets, p) {
          981                                 if(p->flag)
          982                                         continue;
          983                                 p->flag = 1;
          984                                 c = *(p->pitem);
          985                                 if(c <= 1) {
          986                                         if(pstate[i+1]-pstate[i] <= p-wsets)
          987                                                 tystate[i] = MUSTLOOKAHEAD;
          988                                         continue;
          989                                 }
          990                                 /* do a goto on c */
          991                                 WSLOOP(p, q)
          992                                         /* this item contributes to the goto */
          993                                         if(c == *(q->pitem)) {
          994                                                 putitem(q->pitem+1, &q->ws);
          995                                                 q->flag = 1;
          996                                         }
          997                                 if(c < NTBASE)
          998                                         state(c);        /* register new state */
          999                                 else
         1000                                         temp1[c-NTBASE] = state(c);
         1001                         }
         1002                         if(gsdebug && foutput != 0) {
         1003                                 Bprint(foutput, "%d: ", i);
         1004                                 NTLOOP(j)
         1005                                         if(temp1[j])
         1006                                                 Bprint(foutput, "%s %d, ",
         1007                                                 nontrst[j].name, temp1[j]);
         1008                                 Bprint(foutput, "\n");
         1009                         }
         1010                         indgo[i] = apack(&temp1[1], nnonter-1) - 1;
         1011                         /* do some more */
         1012                         more = 1;
         1013                 }
         1014         }
         1015 }
         1016 
         1017 /*
         1018  * generate the closure of state i
         1019  */
         1020 void
         1021 closure(int i)
         1022 {
         1023 
         1024         Wset *u, *v;
         1025         Item *p, *q;
         1026         int c, ch, work, k, *pi, **s, **t;
         1027 
         1028         zzclose++;
         1029 
         1030         /* first, copy kernel of state i to wsets */
         1031         cwp = wsets;
         1032         ITMLOOP(i, p, q) {
         1033                 cwp->pitem = p->pitem;
         1034                 cwp->flag = 1;                        /* this item must get closed */
         1035                 SETLOOP(k)
         1036                         cwp->ws.lset[k] = p->look->lset[k];
         1037                 WSBUMP(cwp);
         1038         }
         1039 
         1040         /* now, go through the loop, closing each item */
         1041         work = 1;
         1042         while(work) {
         1043                 work = 0;
         1044                 WSLOOP(wsets, u) {
         1045                         if(u->flag == 0)
         1046                                 continue;
         1047                         /* dot is before c */
         1048                         c = *(u->pitem);
         1049                         if(c < NTBASE) {
         1050                                 u->flag = 0;
         1051                                 /* only interesting case is where . is before nonterminal */
         1052                                 continue;
         1053                         }
         1054 
         1055                         /* compute the lookahead */
         1056                         aryfil(clset.lset, tbitset, 0);
         1057 
         1058                         /* find items involving c */
         1059                         WSLOOP(u, v)
         1060                                 if(v->flag == 1 && *(pi=v->pitem) == c) {
         1061                                         v->flag = 0;
         1062                                         if(nolook)
         1063                                                 continue;
         1064                                         while((ch = *++pi) > 0) {
         1065                                                 /* terminal symbol */
         1066                                                 if(ch < NTBASE) {
         1067                                                         SETBIT(clset.lset, ch);
         1068                                                         break;
         1069                                                 }
         1070                                                 /* nonterminal symbol */
         1071                                                 setunion(clset.lset, pfirst[ch-NTBASE]->lset);
         1072                                                 if(!pempty[ch-NTBASE])
         1073                                                         break;
         1074                                         }
         1075                                         if(ch <= 0)
         1076                                                 setunion(clset.lset, v->ws.lset);
         1077                                 }
         1078 
         1079                         /*
         1080                          * now loop over productions derived from c
         1081                          * c is now nonterminal number
         1082                          */
         1083                         c -= NTBASE;
         1084                         t = pres[c+1];
         1085                         for(s = pres[c]; s < t; ++s) {
         1086                                 /*
         1087                                  * put these items into the closure
         1088                                  * is the item there
         1089                                  */
         1090                                 WSLOOP(wsets, v)
         1091                                         /* yes, it is there */
         1092                                         if(v->pitem == *s) {
         1093                                                 if(nolook)
         1094                                                         goto nexts;
         1095                                                 if(setunion(v->ws.lset, clset.lset))
         1096                                                         v->flag = work = 1;
         1097                                                 goto nexts;
         1098                                         }
         1099 
         1100                                 /*  not there; make a new entry */
         1101                                 if(cwp-wsets+1 >= WSETSIZE)
         1102                                         error( "working set overflow");
         1103                                 cwp->pitem = *s;
         1104                                 cwp->flag = 1;
         1105                                 if(!nolook) {
         1106                                         work = 1;
         1107                                         SETLOOP(k) cwp->ws.lset[k] = clset.lset[k];
         1108                                 }
         1109                                 WSBUMP(cwp);
         1110 
         1111                         nexts:;
         1112                         }
         1113                 }
         1114         }
         1115 
         1116         /* have computed closure; flags are reset; return */
         1117         if(cwp > zzcwp)
         1118                 zzcwp = cwp;
         1119         if(cldebug && foutput != 0) {
         1120                 Bprint(foutput, "\nState %d, nolook = %d\n", i, nolook);
         1121                 WSLOOP(wsets, u) {
         1122                         if(u->flag)
         1123                                 Bprint(foutput, "flag set!\n");
         1124                         u->flag = 0;
         1125                         Bprint(foutput, "\t%s", writem(u->pitem));
         1126                         prlook(&u->ws);
         1127                         Bprint(foutput, "\n");
         1128                 }
         1129         }
         1130 }
         1131 
         1132 /*
         1133  * decide if the lookahead set pointed to by p is known
         1134  * return pointer to a perminent location for the set
         1135  */
         1136 Lkset*
         1137 flset(Lkset *p)
         1138 {
         1139         Lkset *q;
         1140         int *u, *v, *w, j;
         1141 
         1142         for(q = &lkst[nlset]; q-- > lkst;) {
         1143                 u = p->lset;
         1144                 v = q->lset;
         1145                 w = &v[tbitset];
         1146                 while(v < w)
         1147                         if(*u++ != *v++)
         1148                                 goto more;
         1149                 /* we have matched */
         1150                 return q;
         1151         more:;
         1152         }
         1153         /* add a new one */
         1154         q = &lkst[nlset++];
         1155         if(nlset >= LSETSIZE)
         1156                 error("too many lookahead sets");
         1157         SETLOOP(j)
         1158                 q->lset[j] = p->lset[j];
         1159         return q;
         1160 }
         1161 
         1162 void
         1163 cleantmp(void)
         1164 {
         1165         ZAPFILE(actname);
         1166         ZAPFILE(tempname);
         1167 }
         1168 
         1169 void
         1170 intr(void)
         1171 {
         1172         cleantmp();
         1173         exits("interrupted");
         1174 }
         1175 
         1176 void
         1177 setup(int argc, char *argv[])
         1178 {
         1179         long c, t;
         1180         int i, j, fd, lev, ty, ytab, *p;
         1181         int vflag, dflag, stem;
         1182         char actnm[8], *stemc, *s, dirbuf[128];
         1183         Biobuf *fout;
         1184 
         1185         ytab = 0;
         1186         vflag = 0;
         1187         dflag = 0;
         1188         stem = 0;
         1189         stemc = "y";
         1190         foutput = 0;
         1191         fdefine = 0;
         1192         fdebug = 0;
         1193         ARGBEGIN{
         1194         case 'v':
         1195         case 'V':
         1196                 vflag++;
         1197                 break;
         1198         case 'D':
         1199                 yydebug = ARGF();
         1200                 break;
         1201         case 'a':
         1202                 yyarg = 1;
         1203                 break;
         1204         case 'd':
         1205                 dflag++;
         1206                 break;
         1207         case 'l':
         1208                 yyline = 0;
         1209                 break;
         1210         case 'o':
         1211                 ytab++;
         1212                 ytabc = ARGF();
         1213                 break;
         1214         case 's':
         1215                 stem++;
         1216                 stemc = ARGF();
         1217                 break;
         1218         case 'S':
         1219                 parser = PARSERS;
         1220                 break;
         1221         default:
         1222                 error("illegal option: %c", ARGC());
         1223         }ARGEND
         1224         openup(stemc, dflag, vflag, ytab, ytabc);
         1225         fout = dflag?fdefine:ftable;
         1226         if(yyarg){
         1227                 Bprint(ftable, "#define\tYYARG\t1\n\n");
         1228         }
         1229         if((fd = mkstemp(ttempname)) >= 0){
         1230                 tempname = ttempname;
         1231                 ftemp = Bfdopen(fd, OWRITE);
         1232         }
         1233         if((fd = mkstemp(tactname)) >= 0){
         1234                 actname = tactname;
         1235                 faction = Bfdopen(fd, OWRITE);
         1236         }
         1237         if(ftemp == 0 || faction == 0)
         1238                 error("cannot open temp file");
         1239         if(argc < 1)
         1240                 error("no input file");
         1241         infile = argv[0];
         1242         if(infile[0] != '/' && getwd(dirbuf, sizeof dirbuf)!=nil){
         1243                 i = strlen(infile)+1+strlen(dirbuf)+1+10;
         1244                 s = malloc(i);
         1245                 if(s != nil){
         1246                         snprint(s, i, "%s/%s", dirbuf, infile);
         1247                         cleanname(s);
         1248                         infile = s;
         1249                 }
         1250         }
         1251         finput = Bopen(infile, OREAD);
         1252         if(finput == 0)
         1253                 error("cannot open '%s'", argv[0]);
         1254         cnamp = cnames;
         1255 
         1256         defin(0, "$end");
         1257         extval = PRIVATE;        /* tokens start in unicode 'private use' */
         1258         defin(0, "error");
         1259         defin(1, "$accept");
         1260         defin(0, "$unk");
         1261         mem = mem0;
         1262         i = 0;
         1263 
         1264         for(t = gettok(); t != MARK && t != ENDFILE;)
         1265         switch(t) {
         1266         case ';':
         1267                 t = gettok();
         1268                 break;
         1269 
         1270         case START:
         1271                 if(gettok() != IDENTIFIER)
         1272                         error("bad %%start construction");
         1273                 start = chfind(1, tokname);
         1274                 t = gettok();
         1275                 continue;
         1276 
         1277         case TYPEDEF:
         1278                 if(gettok() != TYPENAME)
         1279                         error("bad syntax in %%type");
         1280                 ty = numbval;
         1281                 for(;;) {
         1282                         t = gettok();
         1283                         switch(t) {
         1284                         case IDENTIFIER:
         1285                                 if((t=chfind(1, tokname)) < NTBASE) {
         1286                                         j = TYPE(toklev[t]);
         1287                                         if(j != 0 && j != ty)
         1288                                                 error("type redeclaration of token %s",
         1289                                                         tokset[t].name);
         1290                                         else
         1291                                                 SETTYPE(toklev[t], ty);
         1292                                 } else {
         1293                                         j = nontrst[t-NTBASE].value;
         1294                                         if(j != 0 && j != ty)
         1295                                                 error("type redeclaration of nonterminal %s",
         1296                                                         nontrst[t-NTBASE].name );
         1297                                         else
         1298                                                 nontrst[t-NTBASE].value = ty;
         1299                                 }
         1300                         case ',':
         1301                                 continue;
         1302                         case ';':
         1303                                 t = gettok();
         1304                         default:
         1305                                 break;
         1306                         }
         1307                         break;
         1308                 }
         1309                 continue;
         1310 
         1311         case UNION:
         1312                 /* copy the union declaration to the output */
         1313                 cpyunion();
         1314                 t = gettok();
         1315                 continue;
         1316 
         1317         case LEFT:
         1318         case BINARY:
         1319         case RIGHT:
         1320                 i++;
         1321 
         1322         case TERM:
         1323                 /* nonzero means new prec. and assoc. */
         1324                 lev = t-TERM;
         1325                 ty = 0;
         1326 
         1327                 /* get identifiers so defined */
         1328                 t = gettok();
         1329 
         1330                 /* there is a type defined */
         1331                 if(t == TYPENAME) {
         1332                         ty = numbval;
         1333                         t = gettok();
         1334                 }
         1335                 for(;;) {
         1336                         switch(t) {
         1337                         case ',':
         1338                                 t = gettok();
         1339                                 continue;
         1340 
         1341                         case ';':
         1342                                 break;
         1343 
         1344                         case IDENTIFIER:
         1345                                 j = chfind(0, tokname);
         1346                                 if(j >= NTBASE)
         1347                                         error("%s defined earlier as nonterminal", tokname);
         1348                                 if(lev) {
         1349                                         if(ASSOC(toklev[j]))
         1350                                                 error("redeclaration of precedence of %s", tokname);
         1351                                         SETASC(toklev[j], lev);
         1352                                         SETPLEV(toklev[j], i);
         1353                                 }
         1354                                 if(ty) {
         1355                                         if(TYPE(toklev[j]))
         1356                                                 error("redeclaration of type of %s", tokname);
         1357                                         SETTYPE(toklev[j],ty);
         1358                                 }
         1359                                 t = gettok();
         1360                                 if(t == NUMBER) {
         1361                                         tokset[j].value = numbval;
         1362                                         if(j < ndefout && j > 3)
         1363                                                 error("please define type number of %s earlier",
         1364                                                         tokset[j].name);
         1365                                         t = gettok();
         1366                                 }
         1367                                 continue;
         1368                         }
         1369                         break;
         1370                 }
         1371                 continue;
         1372 
         1373         case LCURLY:
         1374                 defout(0);
         1375                 cpycode();
         1376                 t = gettok();
         1377                 continue;
         1378 
         1379         default:
         1380                 error("syntax error");
         1381         }
         1382         if(t == ENDFILE)
         1383                 error("unexpected EOF before %%");
         1384 
         1385         /* t is MARK */
         1386         if(!yyarg)
         1387                 Bprint(ftable, "extern        int        yyerrflag;\n");
         1388         Bprint(ftable, "#ifndef        YYMAXDEPTH\n");
         1389         Bprint(ftable, "#define        YYMAXDEPTH        150\n");
         1390         Bprint(ftable, "#endif\n" );
         1391         if(!ntypes) {
         1392                 Bprint(ftable, "#ifndef        YYSTYPE\n");
         1393                 Bprint(ftable, "#define        YYSTYPE        int\n");
         1394                 Bprint(ftable, "#endif\n");
         1395         }
         1396         if(!yyarg){
         1397                 Bprint(ftable, "YYSTYPE        yylval;\n");
         1398                 Bprint(ftable, "YYSTYPE        yyval;\n");
         1399         }else{
         1400                 if(dflag)
         1401                         Bprint(ftable, "#include \"%s.%s\"\n\n", stemc, FILED);
         1402                 Bprint(fout, "struct Yyarg {\n");
         1403                 Bprint(fout, "\tint\tyynerrs;\n");
         1404                 Bprint(fout, "\tint\tyyerrflag;\n");
         1405                 Bprint(fout, "\tvoid*\targ;\n");
         1406                 Bprint(fout, "\tYYSTYPE\tyyval;\n");
         1407                 Bprint(fout, "\tYYSTYPE\tyylval;\n");
         1408                 Bprint(fout, "};\n\n");
         1409         }
         1410         prdptr[0] = mem;
         1411 
         1412         /* added production */
         1413         *mem++ = NTBASE;
         1414 
         1415         /* if start is 0, we will overwrite with the lhs of the first rule */
         1416         *mem++ = start;
         1417         *mem++ = 1;
         1418         *mem++ = 0;
         1419         prdptr[1] = mem;
         1420         while((t=gettok()) == LCURLY)
         1421                 cpycode();
         1422         if(t != IDENTCOLON)
         1423                 error("bad syntax on first rule");
         1424 
         1425         if(!start)
         1426                 prdptr[0][1] = chfind(1, tokname);
         1427 
         1428         /* read rules */
         1429         while(t != MARK && t != ENDFILE) {
         1430                 /* process a rule */
         1431                 rlines[nprod] = lineno;
         1432                 if(t == '|')
         1433                         *mem++ = *prdptr[nprod-1];
         1434                 else
         1435                         if(t == IDENTCOLON) {
         1436                                 *mem = chfind(1, tokname);
         1437                                 if(*mem < NTBASE)
         1438                                         error("token illegal on LHS of grammar rule");
         1439                                 mem++;
         1440                         } else
         1441                                 error("illegal rule: missing semicolon or | ?");
         1442                 /* read rule body */
         1443                 t = gettok();
         1444 
         1445         more_rule:
         1446                 while(t == IDENTIFIER) {
         1447                         *mem = chfind(1, tokname);
         1448                         if(*mem < NTBASE)
         1449                                 levprd[nprod] = toklev[*mem];
         1450                         mem++;
         1451                         t = gettok();
         1452                 }
         1453                 if(t == PREC) {
         1454                         if(gettok() != IDENTIFIER)
         1455                                 error("illegal %%prec syntax");
         1456                         j = chfind(2, tokname);
         1457                         if(j >= NTBASE)
         1458                                 error("nonterminal %s illegal after %%prec",
         1459                                         nontrst[j-NTBASE].name);
         1460                         levprd[nprod] = toklev[j];
         1461                         t = gettok();
         1462                 }
         1463                 if(t == '=') {
         1464                         levprd[nprod] |= ACTFLAG;
         1465                         Bprint(faction, "\ncase %d:", nprod);
         1466                         cpyact(mem-prdptr[nprod]-1);
         1467                         Bprint(faction, " break;");
         1468                         if((t=gettok()) == IDENTIFIER) {
         1469 
         1470                                 /* action within rule... */
         1471                                 sprint(actnm, "$$%d", nprod);
         1472 
         1473                                 /* make it a nonterminal */
         1474                                 j = chfind(1, actnm);
         1475 
         1476                                 /*
         1477                                  * the current rule will become rule number nprod+1
         1478                                  * move the contents down, and make room for the null
         1479                                  */
         1480                                 for(p = mem; p >= prdptr[nprod]; --p)
         1481                                         p[2] = *p;
         1482                                 mem += 2;
         1483 
         1484                                 /* enter null production for action */
         1485                                 p = prdptr[nprod];
         1486                                 *p++ = j;
         1487                                 *p++ = -nprod;
         1488 
         1489                                 /* update the production information */
         1490                                 levprd[nprod+1] = levprd[nprod] & ~ACTFLAG;
         1491                                 levprd[nprod] = ACTFLAG;
         1492                                 if(++nprod >= NPROD)
         1493                                         error("more than %d rules", NPROD);
         1494                                 prdptr[nprod] = p;
         1495 
         1496                                 /* make the action appear in the original rule */
         1497                                 *mem++ = j;
         1498 
         1499                                 /* get some more of the rule */
         1500                                 goto more_rule;
         1501                         }
         1502                 }
         1503 
         1504                 while(t == ';')
         1505                         t = gettok();
         1506                 *mem++ = -nprod;
         1507 
         1508                 /* check that default action is reasonable */
         1509                 if(ntypes && !(levprd[nprod]&ACTFLAG) && nontrst[*prdptr[nprod]-NTBASE].value) {
         1510 
         1511                         /* no explicit action, LHS has value */
         1512                         int tempty;
         1513 
         1514                         tempty = prdptr[nprod][1];
         1515                         if(tempty < 0)
         1516                                 error("must return a value, since LHS has a type");
         1517                         else
         1518                                 if(tempty >= NTBASE)
         1519                                         tempty = nontrst[tempty-NTBASE].value;
         1520                                 else
         1521                                         tempty = TYPE(toklev[tempty]);
         1522                         if(tempty != nontrst[*prdptr[nprod]-NTBASE].value)
         1523                                 error("default action causes potential type clash");
         1524                 }
         1525                 nprod++;
         1526                 if(nprod >= NPROD)
         1527                         error("more than %d rules", NPROD);
         1528                 prdptr[nprod] = mem;
         1529                 levprd[nprod] = 0;
         1530         }
         1531 
         1532         /* end of all rules */
         1533         defout(1);
         1534 
         1535         finact();
         1536         if(t == MARK) {
         1537                 Bprint(ftable, "\n");
         1538                 if(yyline)
         1539                         Bprint(ftable, "#line\t%d\t\"%s\"\n", lineno, infile);
         1540                 while((c=Bgetrune(finput)) != Beof)
         1541                         Bputrune(ftable, c);
         1542         }
         1543         Bterm(finput);
         1544 }
         1545 
         1546 /*
         1547  * finish action routine
         1548  */
         1549 void
         1550 finact(void)
         1551 {
         1552 
         1553         Bterm(faction);
         1554         Bprint(ftable, "#define YYEOFCODE %d\n", 1);
         1555         Bprint(ftable, "#define YYERRCODE %d\n", 2);
         1556 }
         1557 
         1558 /*
         1559  * define s to be a terminal if t=0
         1560  * or a nonterminal if t=1
         1561  */
         1562 int
         1563 defin(int nt, char *s)
         1564 {
         1565         int val;
         1566         Rune rune;
         1567 
         1568         val = 0;
         1569         if(nt) {
         1570                 nnonter++;
         1571                 if(nnonter >= NNONTERM)
         1572                         error("too many nonterminals, limit %d",NNONTERM);
         1573                 nontrst[nnonter].name = cstash(s);
         1574                 return NTBASE + nnonter;
         1575         }
         1576 
         1577         /* must be a token */
         1578         ntokens++;
         1579         if(ntokens >= NTERMS)
         1580                 error("too many terminals, limit %d", NTERMS);
         1581         tokset[ntokens].name = cstash(s);
         1582 
         1583         /* establish value for token */
         1584         /* single character literal */
         1585         if(s[0] == ' ') {
         1586                 val = chartorune(&rune, &s[1]);
         1587                 if(s[val+1] == 0) {
         1588                         val = rune;
         1589                         goto out;
         1590                 }
         1591         }
         1592 
         1593         /* escape sequence */
         1594         if(s[0] == ' ' && s[1] == '\\') {
         1595                 if(s[3] == 0) {
         1596                         /* single character escape sequence */
         1597                         switch(s[2]) {
         1598                         case 'n':        val = '\n'; break;
         1599                         case 'r':        val = '\r'; break;
         1600                         case 'b':        val = '\b'; break;
         1601                         case 't':        val = '\t'; break;
         1602                         case 'f':        val = '\f'; break;
         1603                         case '\'':        val = '\''; break;
         1604                         case '"':        val = '"'; break;
         1605                         case '\\':        val = '\\'; break;
         1606                         default:        error("invalid escape");
         1607                         }
         1608                         goto out;
         1609                 }
         1610 
         1611                 /* \nnn sequence */
         1612                 if(s[2] >= '0' && s[2] <= '7') {
         1613                         if(s[3] < '0' ||
         1614                            s[3] > '7' ||
         1615                            s[4] < '0' ||
         1616                            s[4] > '7' ||
         1617                            s[5] != 0)
         1618                                 error("illegal \\nnn construction");
         1619                         val = 64*s[2] + 8*s[3] + s[4] - 73*'0';
         1620                         if(val == 0)
         1621                                 error("'\\000' is illegal");
         1622                         goto out;
         1623                 }
         1624                 error("unknown escape");
         1625         }
         1626         val = extval++;
         1627 
         1628 out:
         1629         tokset[ntokens].value = val;
         1630         toklev[ntokens] = 0;
         1631         return ntokens;
         1632 }
         1633 
         1634 /*
         1635  * write out the defines (at the end of the declaration section)
         1636  */
         1637 void
         1638 defout(int last)
         1639 {
         1640         int i, c;
         1641         char sar[NAMESIZE+10];
         1642 
         1643         for(i=ndefout; i<=ntokens; i++) {
         1644                 /* non-literals */
         1645                 c = tokset[i].name[0];
         1646                 if(c != ' ' && c != '$') {
         1647                         Bprint(ftable, "#define        %s        %d\n",
         1648                                 tokset[i].name, tokset[i].value);
         1649                         if(fdefine)
         1650                                 Bprint(fdefine, "#define\t%s\t%d\n",
         1651                                         tokset[i].name, tokset[i].value);
         1652                 }
         1653         }
         1654         ndefout = ntokens+1;
         1655         if(last && fdebug) {
         1656                 Bprint(fdebug, "static        char*        yytoknames[] =\n{\n");
         1657                 TLOOP(i) {
         1658                         if(tokset[i].name) {
         1659                                 chcopy(sar, tokset[i].name);
         1660                                 Bprint(fdebug, "\t\"%s\",\n", sar);
         1661                                 continue;
         1662                         }
         1663                         Bprint(fdebug, "\t0,\n");
         1664                 }
         1665                 Bprint(fdebug, "};\n");
         1666         }
         1667 }
         1668 
         1669 char*
         1670 cstash(char *s)
         1671 {
         1672         char *temp;
         1673 
         1674         temp = cnamp;
         1675         do {
         1676                 if(cnamp >= &cnames[cnamsz])
         1677                         error("too many characters in id's and literals");
         1678                 else
         1679                         *cnamp++ = *s;
         1680         } while(*s++);
         1681         return temp;
         1682 }
         1683 
         1684 int
         1685 isvalidchar(long i)
         1686 {
         1687         return (i & ~0xffUL) == 0;
         1688 }
         1689 
         1690 long
         1691 gettok(void)
         1692 {
         1693         long c;
         1694         Rune rune;
         1695         int i, base, match, reserve;
         1696         static int peekline;
         1697 
         1698 begin:
         1699         reserve = 0;
         1700         lineno += peekline;
         1701         peekline = 0;
         1702         c = Bgetrune(finput);
         1703         while(c == ' ' || c == '\n' || c == '\t' || c == '\f') {
         1704                 if(c == '\n')
         1705                         lineno++;
         1706                 c = Bgetrune(finput);
         1707         }
         1708 
         1709         /* skip comment */
         1710         if(c == '/') {
         1711                 lineno += skipcom();
         1712                 goto begin;
         1713         }
         1714         switch(c) {
         1715         case Beof:
         1716                 return ENDFILE;
         1717 
         1718         case '{':
         1719                 Bungetrune(finput);
         1720                 return '=';
         1721 
         1722         case '<':
         1723                 /* get, and look up, a type name (union member name) */
         1724                 i = 0;
         1725                 while((c=Bgetrune(finput)) != '>' && c >= 0 && c != '\n') {
         1726                         rune = c;
         1727                         c = runetochar(&tokname[i], &rune);
         1728                         if(i < NAMESIZE)
         1729                                 i += c;
         1730                 }
         1731                 if(c != '>')
         1732                         error("unterminated < ... > clause");
         1733                 tokname[i] = 0;
         1734                 for(i=1; i<=ntypes; i++)
         1735                         if(!strcmp(typeset[i], tokname)) {
         1736                                 numbval = i;
         1737                                 return TYPENAME;
         1738                         }
         1739                 ntypes++;
         1740                 numbval = ntypes;
         1741                 typeset[numbval] = cstash(tokname);
         1742                 return TYPENAME;
         1743 
         1744         case '"':
         1745         case '\'':
         1746                 match = c;
         1747                 tokname[0] = ' ';
         1748                 i = 1;
         1749                 for(;;) {
         1750                         c = Bgetrune(finput);
         1751                         if(c == '\n' || c <= 0)
         1752                                 error("illegal or missing ' or \"" );
         1753                         if(c == '\\') {
         1754                                 tokname[i] = '\\';
         1755                                 if(i < NAMESIZE)
         1756                                         i++;
         1757                                 c = Bgetrune(finput);
         1758                         } else
         1759                                 if(c == match)
         1760                                         break;
         1761                         rune = c;
         1762                         c = runetochar(&tokname[i], &rune);
         1763                         if(i < NAMESIZE)
         1764                                 i += c;
         1765                 }
         1766                 break;
         1767 
         1768         case '%':
         1769         case '\\':
         1770                 switch(c = Bgetrune(finput)) {
         1771                 case '0':        return TERM;
         1772                 case '<':        return LEFT;
         1773                 case '2':        return BINARY;
         1774                 case '>':        return RIGHT;
         1775                 case '%':
         1776                 case '\\':        return MARK;
         1777                 case '=':        return PREC;
         1778                 case '{':        return LCURLY;
         1779                 default:        reserve = 1;
         1780                 }
         1781 
         1782         default:
         1783                 /* number */
         1784                 if(!isvalidchar(c))
         1785                         return c;
         1786                 if(isdigit(c)) {
         1787                         numbval = c-'0';
         1788                         base = (c=='0')? 8: 10;
         1789                         for(c = Bgetrune(finput); isdigit(c); c = Bgetrune(finput))
         1790                                 numbval = numbval*base + (c-'0');
         1791                         Bungetrune(finput);
         1792                         return NUMBER;
         1793                 }
         1794                 if(islower(c) || isupper(c) || c=='_' || c=='.' || c=='$')  {
         1795                         i = 0;
         1796                         while(isvalidchar(c) && (islower(c) || isupper(c) || isdigit(c) ||
         1797                             c == '-' || c=='_' || c=='.' || c=='$')) {
         1798                                 if(reserve && isupper(c))
         1799                                         c += 'a'-'A';
         1800                                 rune = c;
         1801                                 c = runetochar(&tokname[i], &rune);
         1802                                 if(i < NAMESIZE)
         1803                                         i += c;
         1804                                 c = Bgetrune(finput);
         1805                         }
         1806                 } else
         1807                         return c;
         1808                 if(c == Beof)
         1809                         return ENDFILE;
         1810                 Bungetrune(finput);
         1811         }
         1812         tokname[i] = 0;
         1813 
         1814         /* find a reserved word */
         1815         if(reserve) {
         1816                 for(c=0; resrv[c].name; c++)
         1817                         if(strcmp(tokname, resrv[c].name) == 0)
         1818                                 return resrv[c].value;
         1819                 error("invalid escape, or illegal reserved word: %s", tokname);
         1820         }
         1821 
         1822         /* look ahead to distinguish IDENTIFIER from IDENTCOLON */
         1823         c = Bgetrune(finput);
         1824         while(c == ' ' || c == '\t'|| c == '\n' || c == '\f' || c == '/') {
         1825                 if(c == '\n')
         1826                         peekline++;
         1827                 /* look for comments */
         1828                 if(c == '/')
         1829                         peekline += skipcom();
         1830                 c = Bgetrune(finput);
         1831         }
         1832         if(c == ':')
         1833                 return IDENTCOLON;
         1834         Bungetrune(finput);
         1835         return IDENTIFIER;
         1836 }
         1837 
         1838 /*
         1839  * determine the type of a symbol
         1840  */
         1841 int
         1842 fdtype(int t)
         1843 {
         1844         int v;
         1845 
         1846         if(t >= NTBASE)
         1847                 v = nontrst[t-NTBASE].value;
         1848         else
         1849                 v = TYPE(toklev[t]);
         1850         if(v <= 0)
         1851                 error("must specify type for %s", (t>=NTBASE)?
         1852                         nontrst[t-NTBASE].name: tokset[t].name);
         1853         return v;
         1854 }
         1855 
         1856 int
         1857 chfind(int t, char *s)
         1858 {
         1859         int i;
         1860 
         1861         if(s[0] == ' ')
         1862                 t = 0;
         1863         TLOOP(i)
         1864                 if(!strcmp(s, tokset[i].name))
         1865                         return i;
         1866         NTLOOP(i)
         1867                 if(!strcmp(s, nontrst[i].name))
         1868                         return NTBASE+i;
         1869 
         1870         /* cannot find name */
         1871         if(t > 1)
         1872                 error("%s should have been defined earlier", s);
         1873         return defin(t, s);
         1874 }
         1875 
         1876 /*
         1877  * copy the union declaration to the output, and the define file if present
         1878  */
         1879 void
         1880 cpyunion(void)
         1881 {
         1882         long c;
         1883         int level;
         1884 
         1885         Bprint(ftable, "\n");
         1886         if(yyline)
         1887                 Bprint(ftable, "#line\t%d\t\"%s\"\n", lineno, infile);
         1888         Bprint(ftable, "typedef union ");
         1889         if(fdefine != 0)
         1890                 Bprint(fdefine, "\ntypedef union ");
         1891 
         1892         level = 0;
         1893         for(;;) {
         1894                 if((c=Bgetrune(finput)) == Beof)
         1895                         error("EOF encountered while processing %%union");
         1896                 Bputrune(ftable, c);
         1897                 if(fdefine != 0)
         1898                         Bputrune(fdefine, c);
         1899                 switch(c) {
         1900                 case '\n':
         1901                         lineno++;
         1902                         break;
         1903                 case '{':
         1904                         level++;
         1905                         break;
         1906                 case '}':
         1907                         level--;
         1908 
         1909                         /* we are finished copying */
         1910                         if(level == 0) {
         1911                                 Bprint(ftable, " YYSTYPE;\n");
         1912                                 if(fdefine != 0){
         1913                                         Bprint(fdefine, "\tYYSTYPE;\n");
         1914                                         if(!yyarg)
         1915                                                 Bprint(fdefine, "extern\tYYSTYPE\tyylval;\n");
         1916                                 }
         1917                                 return;
         1918                         }
         1919                 }
         1920         }
         1921 }
         1922 
         1923 /*
         1924  * copies code between \{ and \}
         1925  */
         1926 void
         1927 cpycode(void)
         1928 {
         1929         long c;
         1930 
         1931         c = Bgetrune(finput);
         1932         if(c == '\n') {
         1933                 c = Bgetrune(finput);
         1934                 lineno++;
         1935         }
         1936         Bprint(ftable, "\n");
         1937         if(yyline)
         1938                 Bprint(ftable, "#line\t%d\t\"%s\"\n", lineno, infile);
         1939         while(c != Beof) {
         1940                 if(c == '\\') {
         1941                         if((c=Bgetrune(finput)) == '}')
         1942                                 return;
         1943                         Bputc(ftable, '\\');
         1944                 }
         1945                 if(c == '%') {
         1946                         if((c=Bgetrune(finput)) == '}')
         1947                                 return;
         1948                         Bputc(ftable, '%');
         1949                 }
         1950                 Bputrune(ftable, c);
         1951                 if(c == '\n')
         1952                         lineno++;
         1953                 c = Bgetrune(finput);
         1954         }
         1955         error("eof before %%}");
         1956 }
         1957 
         1958 /*
         1959  * skip over comments
         1960  * skipcom is called after reading a '/'
         1961  */
         1962 int
         1963 skipcom(void)
         1964 {
         1965         long c;
         1966         int i;
         1967 
         1968         /* i is the number of lines skipped */
         1969         i = 0;
         1970         if(Bgetrune(finput) != '*')
         1971                 error("illegal comment");
         1972         c = Bgetrune(finput);
         1973         while(c != Beof) {
         1974                 while(c == '*')
         1975                         if((c=Bgetrune(finput)) == '/')
         1976                                 return i;
         1977                 if(c == '\n')
         1978                         i++;
         1979                 c = Bgetrune(finput);
         1980         }
         1981         error("EOF inside comment");
         1982         return 0;
         1983 }
         1984 
         1985 /*
         1986  * copy C action to the next ; or closing }
         1987  */
         1988 void
         1989 cpyact(int offset)
         1990 {
         1991         long c;
         1992         int brac, match, j, s, fnd, tok;
         1993 
         1994         Bprint(faction, "\n");
         1995         if(yyline)
         1996                 Bprint(faction, "#line\t%d\t\"%s\"\n", lineno, infile);
         1997         brac = 0;
         1998 
         1999 loop:
         2000         c = Bgetrune(finput);
         2001 swt:
         2002         switch(c) {
         2003         case ';':
         2004                 if(brac == 0) {
         2005                         Bputrune(faction, c);
         2006                         return;
         2007                 }
         2008                 goto lcopy;
         2009 
         2010         case '{':
         2011                 brac++;
         2012                 goto lcopy;
         2013 
         2014         case '$':
         2015                 s = 1;
         2016                 tok = -1;
         2017                 c = Bgetrune(finput);
         2018 
         2019                 /* type description */
         2020                 if(c == '<') {
         2021                         Bungetrune(finput);
         2022                         if(gettok() != TYPENAME)
         2023                                 error("bad syntax on $<ident> clause");
         2024                         tok = numbval;
         2025                         c = Bgetrune(finput);
         2026                 }
         2027                 if(c == '$') {
         2028                         Bprint(faction, "yyval");
         2029 
         2030                         /* put out the proper tag... */
         2031                         if(ntypes) {
         2032                                 if(tok < 0)
         2033                                         tok = fdtype(*prdptr[nprod]);
         2034                                 Bprint(faction, ".%s", typeset[tok]);
         2035                         }
         2036                         goto loop;
         2037                 }
         2038                 if(c == '-') {
         2039                         s = -s;
         2040                         c = Bgetrune(finput);
         2041                 }
         2042                 if(isvalidchar(c) && isdigit(c)) {
         2043                         j = 0;
         2044                         while(isdigit(c)) {
         2045                                 j = j*10 + (c-'0');
         2046                                 c = Bgetrune(finput);
         2047                         }
         2048                         Bungetrune(finput);
         2049                         j = j*s - offset;
         2050                         if(j > 0)
         2051                                 error("Illegal use of $%d", j+offset);
         2052 
         2053                 dollar:
         2054                         Bprint(faction, "yypt[-%d].yyv", -j);
         2055 
         2056                         /* put out the proper tag */
         2057                         if(ntypes) {
         2058                                 if(j+offset <= 0 && tok < 0)
         2059                                         error("must specify type of $%d", j+offset);
         2060                                 if(tok < 0)
         2061                                         tok = fdtype(prdptr[nprod][j+offset]);
         2062                                 Bprint(faction, ".%s", typeset[tok]);
         2063                         }
         2064                         goto loop;
         2065                 }
         2066                 if(isvalidchar(c) && (isupper(c) || islower(c) || c == '_' || c == '.')) {
         2067                         int tok; /* tok used oustide for type info */
         2068 
         2069                         /* look for $name */
         2070                         Bungetrune(finput);
         2071                         if(gettok() != IDENTIFIER)
         2072                                 error("$ must be followed by an identifier");
         2073                         tok = chfind(2, tokname);
         2074                         if((c = Bgetrune(finput)) != '#') {
         2075                                 Bungetrune(finput);
         2076                                 fnd = -1;
         2077                         } else
         2078                                 if(gettok() != NUMBER) {
         2079                                         error("# must be followed by number");
         2080                                         fnd = -1;
         2081                                 } else
         2082                                         fnd = numbval;
         2083                         for(j=1; j<=offset; ++j)
         2084                                 if(tok == prdptr[nprod][j]) {
         2085                                         if(--fnd <= 0) {
         2086                                                 j -= offset;
         2087                                                 goto dollar;
         2088                                         }
         2089                                 }
         2090                         error("$name or $name#number not found");
         2091                 }
         2092                 Bputc(faction, '$');
         2093                 if(s < 0 )
         2094                         Bputc(faction, '-');
         2095                 goto swt;
         2096 
         2097         case '}':
         2098                 brac--;
         2099                 if(brac)
         2100                         goto lcopy;
         2101                 Bputrune(faction, c);
         2102                 return;
         2103 
         2104         case '/':
         2105                 /* look for comments */
         2106                 Bputrune(faction, c);
         2107                 c = Bgetrune(finput);
         2108                 if(c != '*')
         2109                         goto swt;
         2110 
         2111                 /* it really is a comment */
         2112                 Bputrune(faction, c);
         2113                 c = Bgetrune(finput);
         2114                 while(c >= 0) {
         2115                         while(c == '*') {
         2116                                 Bputrune(faction, c);
         2117                                 if((c=Bgetrune(finput)) == '/')
         2118                                         goto lcopy;
         2119                         }
         2120                         Bputrune(faction, c);
         2121                         if(c == '\n')
         2122                                 lineno++;
         2123                         c = Bgetrune(finput);
         2124                 }
         2125                 error("EOF inside comment");
         2126 
         2127         case '\'':
         2128                 /* character constant */
         2129                 match = '\'';
         2130                 goto string;
         2131 
         2132         case '"':
         2133                 /* character string */
         2134                 match = '"';
         2135 
         2136         string:
         2137                 Bputrune(faction, c);
         2138                 while((c = Bgetrune(finput)) >= 0) {
         2139                         if(c == '\\') {
         2140                                 Bputrune(faction, c);
         2141                                 c = Bgetrune(finput);
         2142                                 if(c == '\n')
         2143                                         lineno++;
         2144                         } else {
         2145                                 if(c == match)
         2146                                         goto lcopy;
         2147                                 if(c == '\n')
         2148                                         error("newline in string or char. const.");
         2149                         }
         2150                         Bputrune(faction, c);
         2151                 }
         2152                 error("EOF in string or character constant");
         2153 
         2154         case Beof:
         2155                 error("action does not terminate");
         2156 
         2157         case '\n':
         2158                 lineno++;
         2159                 goto lcopy;
         2160         }
         2161 
         2162 lcopy:
         2163         Bputrune(faction, c);
         2164         goto loop;
         2165 }
         2166 
         2167 void
         2168 openup(char *stem, int dflag, int vflag, int ytab, char *ytabc)
         2169 {
         2170         char buf[256];
         2171 
         2172         if(vflag) {
         2173                 sprint(buf, "%s.%s", stem, FILEU);
         2174                 foutput = Bopen(buf, OWRITE);
         2175                 if(foutput == 0)
         2176                         error("cannot open %s", buf);
         2177         }
         2178         if(yydebug) {
         2179                 sprint(buf, "%s.%s", stem, FILEDEBUG);
         2180                 if((fdebug = Bopen(buf, OWRITE)) == 0)
         2181                         error("can't open %s", buf);
         2182         }
         2183         if(dflag) {
         2184                 sprint(buf, "%s.%s", stem, FILED);
         2185                 fdefine = Bopen(buf, OWRITE);
         2186                 if(fdefine == 0)
         2187                         error("can't create %s", buf);
         2188         }
         2189         if(ytab == 0)
         2190                 sprint(buf, "%s.%s", stem, OFILE);
         2191         else
         2192                 strcpy(buf, ytabc);
         2193         ftable = Bopen(buf, OWRITE);
         2194         if(ftable == 0)
         2195                 error("cannot open table file %s", buf);
         2196 }
         2197 
         2198 /*
         2199  * print the output for the states
         2200  */
         2201 void
         2202 output(void)
         2203 {
         2204         int i, k, c;
         2205         Wset *u, *v;
         2206 
         2207         Bprint(ftable, "static\tconst\tshort        yyexca[] =\n{");
         2208         if(fdebug)
         2209                 Bprint(fdebug, "static\tconst\tchar*        yystates[] =\n{\n");
         2210 
         2211         /* output the stuff for state i */
         2212         SLOOP(i) {
         2213                 nolook = tystate[i]!=MUSTLOOKAHEAD;
         2214                 closure(i);
         2215 
         2216                 /* output actions */
         2217                 nolook = 1;
         2218                 aryfil(temp1, ntokens+nnonter+1, 0);
         2219                 WSLOOP(wsets, u) {
         2220                         c = *(u->pitem);
         2221                         if(c > 1 && c < NTBASE && temp1[c] == 0) {
         2222                                 WSLOOP(u, v)
         2223                                         if(c == *(v->pitem))
         2224                                                 putitem(v->pitem+1, (Lkset*)0);
         2225                                 temp1[c] = state(c);
         2226                         } else
         2227                                 if(c > NTBASE && temp1[(c -= NTBASE) + ntokens] == 0)
         2228                                         temp1[c+ntokens] = amem[indgo[i]+c];
         2229                 }
         2230                 if(i == 1)
         2231                         temp1[1] = ACCEPTCODE;
         2232 
         2233                 /* now, we have the shifts; look at the reductions */
         2234                 lastred = 0;
         2235                 WSLOOP(wsets, u) {
         2236                         c = *u->pitem;
         2237 
         2238                         /* reduction */
         2239                         if(c <= 0) {
         2240                                 lastred = -c;
         2241                                 TLOOP(k)
         2242                                         if(BIT(u->ws.lset, k)) {
         2243                                                 if(temp1[k] == 0)
         2244                                                         temp1[k] = c;
         2245                                                 else
         2246                                                 if(temp1[k] < 0) { /* reduce/reduce conflict */
         2247                                                         if(foutput)
         2248                                                                 Bprint(foutput,
         2249                                                                         "\n%d: reduce/reduce conflict"
         2250                                                                         " (red'ns %d and %d ) on %s",
         2251                                                                         i, -temp1[k], lastred,
         2252                                                                         symnam(k));
         2253                                                         if(-temp1[k] > lastred)
         2254                                                                 temp1[k] = -lastred;
         2255                                                         zzrrconf++;
         2256                                                 } else
         2257                                                         /* potential shift/reduce conflict */
         2258                                                         precftn( lastred, k, i );
         2259                                         }
         2260                                 }
         2261                 }
         2262                 wract(i);
         2263         }
         2264 
         2265         if(fdebug)
         2266                 Bprint(fdebug, "};\n");
         2267         Bprint(ftable, "};\n");
         2268         Bprint(ftable, "#define        YYNPROD        %d\n", nprod);
         2269         Bprint(ftable, "#define        YYPRIVATE %d\n", PRIVATE);
         2270         if(yydebug)
         2271                 Bprint(ftable, "#define        yydebug        %s\n", yydebug);
         2272 }
         2273 
         2274 /*
         2275  * pack state i from temp1 into amem
         2276  */
         2277 int
         2278 apack(int *p, int n)
         2279 {
         2280         int *pp, *qq, *rr, off, *q, *r;
         2281 
         2282         /* we don't need to worry about checking because
         2283          * we will only look at entries known to be there...
         2284          * eliminate leading and trailing 0's
         2285          */
         2286 
         2287         q = p+n;
         2288         for(pp = p, off = 0; *pp == 0 && pp <= q; ++pp, --off)
         2289                 ;
         2290          /* no actions */
         2291         if(pp > q)
         2292                 return 0;
         2293         p = pp;
         2294 
         2295         /* now, find a place for the elements from p to q, inclusive */
         2296         r = &amem[ACTSIZE-1];
         2297         for(rr = amem; rr <= r; rr++, off++) {
         2298                 for(qq = rr, pp = p; pp <= q; pp++, qq++)
         2299                         if(*pp != 0)
         2300                                 if(*pp != *qq && *qq != 0)
         2301                                         goto nextk;
         2302 
         2303                 /* we have found an acceptable k */
         2304                 if(pkdebug && foutput != 0)
         2305                         Bprint(foutput, "off = %d, k = %d\n", off, (int)(rr-amem));
         2306                 for(qq = rr, pp = p; pp <= q; pp++, qq++)
         2307                         if(*pp) {
         2308                                 if(qq > r)
         2309                                         error("action table overflow");
         2310                                 if(qq > memp)
         2311                                         memp = qq;
         2312                                 *qq = *pp;
         2313                         }
         2314                 if(pkdebug && foutput != 0)
         2315                         for(pp = amem; pp <= memp; pp += 10) {
         2316                                 Bprint(foutput, "\t");
         2317                                 for(qq = pp; qq <= pp+9; qq++)
         2318                                         Bprint(foutput, "%d ", *qq);
         2319                                 Bprint(foutput, "\n");
         2320                         }
         2321                 return(off);
         2322         nextk:;
         2323         }
         2324         error("no space in action table");
         2325         return 0;
         2326 }
         2327 
         2328 /*
         2329  * output the gotos for the nontermninals
         2330  */
         2331 void
         2332 go2out(void)
         2333 {
         2334         int i, j, k, best, count, cbest, times;
         2335 
         2336         /* mark begining of gotos */
         2337         Bprint(ftemp, "$\n");
         2338         for(i = 1; i <= nnonter; i++) {
         2339                 go2gen(i);
         2340 
         2341                 /* find the best one to make default */
         2342                 best = -1;
         2343                 times = 0;
         2344 
         2345                 /* is j the most frequent */
         2346                 for(j = 0; j <= nstate; j++) {
         2347                         if(tystate[j] == 0)
         2348                                 continue;
         2349                         if(tystate[j] == best)
         2350                                 continue;
         2351 
         2352                         /* is tystate[j] the most frequent */
         2353                         count = 0;
         2354                         cbest = tystate[j];
         2355                         for(k = j; k <= nstate; k++)
         2356                                 if(tystate[k] == cbest)
         2357                                         count++;
         2358                         if(count > times) {
         2359                                 best = cbest;
         2360                                 times = count;
         2361                         }
         2362                 }
         2363 
         2364                 /* best is now the default entry */
         2365                 zzgobest += times-1;
         2366                 for(j = 0; j <= nstate; j++)
         2367                         if(tystate[j] != 0 && tystate[j] != best) {
         2368                                 Bprint(ftemp, "%d,%d,", j, tystate[j]);
         2369                                 zzgoent++;
         2370                         }
         2371 
         2372                 /* now, the default */
         2373                 if(best == -1)
         2374                         best = 0;
         2375                 zzgoent++;
         2376                 Bprint(ftemp, "%d\n", best);
         2377         }
         2378 }
         2379 
         2380 /*
         2381  * output the gotos for nonterminal c
         2382  */
         2383 void
         2384 go2gen(int c)
         2385 {
         2386         int i, work, cc;
         2387         Item *p, *q;
         2388 
         2389 
         2390         /* first, find nonterminals with gotos on c */
         2391         aryfil(temp1, nnonter+1, 0);
         2392         temp1[c] = 1;
         2393         work = 1;
         2394         while(work) {
         2395                 work = 0;
         2396                 PLOOP(0, i)
         2397 
         2398                         /* cc is a nonterminal */
         2399                         if((cc=prdptr[i][1]-NTBASE) >= 0)
         2400                                 /* cc has a goto on c */
         2401                                 if(temp1[cc] != 0) {
         2402 
         2403                                         /* thus, the left side of production i does too */
         2404                                         cc = *prdptr[i]-NTBASE;
         2405                                         if(temp1[cc] == 0) {
         2406                                                   work = 1;
         2407                                                   temp1[cc] = 1;
         2408                                         }
         2409                                 }
         2410         }
         2411 
         2412         /* now, we have temp1[c] = 1 if a goto on c in closure of cc */
         2413         if(g2debug && foutput != 0) {
         2414                 Bprint(foutput, "%s: gotos on ", nontrst[c].name);
         2415                 NTLOOP(i)
         2416                         if(temp1[i])
         2417                                 Bprint(foutput, "%s ", nontrst[i].name);
         2418                 Bprint(foutput, "\n");
         2419         }
         2420 
         2421         /* now, go through and put gotos into tystate */
         2422         aryfil(tystate, nstate, 0);
         2423         SLOOP(i)
         2424                 ITMLOOP(i, p, q)
         2425                         if((cc = *p->pitem) >= NTBASE)
         2426                                 /* goto on c is possible */
         2427                                 if(temp1[cc-NTBASE]) {
         2428                                         tystate[i] = amem[indgo[i]+c];
         2429                                         break;
         2430                                 }
         2431 }
         2432 
         2433 /*
         2434  * decide a shift/reduce conflict by precedence.
         2435  * r is a rule number, t a token number
         2436  * the conflict is in state s
         2437  * temp1[t] is changed to reflect the action
         2438  */
         2439 void
         2440 precftn(int r, int t, int s)
         2441 {
         2442         int lp, lt, action;
         2443 
         2444         lp = levprd[r];
         2445         lt = toklev[t];
         2446         if(PLEVEL(lt) == 0 || PLEVEL(lp) == 0) {
         2447 
         2448                 /* conflict */
         2449                 if(foutput != 0)
         2450                         Bprint(foutput,
         2451                                 "\n%d: shift/reduce conflict (shift %d(%d), red'n %d(%d)) on %s",
         2452                                 s, temp1[t], PLEVEL(lt), r, PLEVEL(lp), symnam(t));
         2453                 zzsrconf++;
         2454                 return;
         2455         }
         2456         if(PLEVEL(lt) == PLEVEL(lp))
         2457                 action = ASSOC(lt);
         2458         else
         2459                 if(PLEVEL(lt) > PLEVEL(lp))
         2460                         action = RASC;  /* shift */
         2461                 else
         2462                         action = LASC;  /* reduce */
         2463         switch(action) {
         2464         case BASC:  /* error action */
         2465                 temp1[t] = ERRCODE;
         2466                 break;
         2467         case LASC:  /* reduce */
         2468                 temp1[t] = -r;
         2469                 break;
         2470         }
         2471 }
         2472 
         2473 /*
         2474  * output state i
         2475  * temp1 has the actions, lastred the default
         2476  */
         2477 void
         2478 wract(int i)
         2479 {
         2480         int p, p0, p1, ntimes, tred, count, j, flag;
         2481 
         2482         /* find the best choice for lastred */
         2483         lastred = 0;
         2484         ntimes = 0;
         2485         TLOOP(j) {
         2486                 if(temp1[j] >= 0)
         2487                         continue;
         2488                 if(temp1[j]+lastred == 0)
         2489                         continue;
         2490                 /* count the number of appearances of temp1[j] */
         2491                 count = 0;
         2492                 tred = -temp1[j];
         2493                 levprd[tred] |= REDFLAG;
         2494                 TLOOP(p)
         2495                         if(temp1[p]+tred == 0)
         2496                                 count++;
         2497                 if(count > ntimes) {
         2498                         lastred = tred;
         2499                         ntimes = count;
         2500                 }
         2501         }
         2502 
         2503         /*
         2504          * for error recovery, arrange that, if there is a shift on the
         2505          * error recovery token, `error', that the default be the error action
         2506          */
         2507         if(temp1[2] > 0)
         2508                 lastred = 0;
         2509 
         2510         /* clear out entries in temp1 which equal lastred */
         2511         TLOOP(p)
         2512                 if(temp1[p]+lastred == 0)
         2513                         temp1[p] = 0;
         2514 
         2515         wrstate(i);
         2516         defact[i] = lastred;
         2517         flag = 0;
         2518         TLOOP(p0)
         2519                 if((p1=temp1[p0]) != 0) {
         2520                         if(p1 < 0) {
         2521                                 p1 = -p1;
         2522                                 goto exc;
         2523                         }
         2524                         if(p1 == ACCEPTCODE) {
         2525                                 p1 = -1;
         2526                                 goto exc;
         2527                         }
         2528                         if(p1 == ERRCODE) {
         2529                                 p1 = 0;
         2530                         exc:
         2531                                 if(flag++ == 0)
         2532                                         Bprint(ftable, "-1, %d,\n", i);
         2533                                 Bprint(ftable, "\t%d, %d,\n", p0, p1);
         2534                                 zzexcp++;
         2535                                 continue;
         2536                         }
         2537                         Bprint(ftemp, "%d,%d,", p0, p1);
         2538                         zzacent++;
         2539                 }
         2540         if(flag) {
         2541                 defact[i] = -2;
         2542                 Bprint(ftable, "\t-2, %d,\n", lastred);
         2543         }
         2544         Bprint(ftemp, "\n");
         2545 }
         2546 
         2547 /*
         2548  * writes state i
         2549  */
         2550 void
         2551 wrstate(int i)
         2552 {
         2553         int j0, j1;
         2554         Item *pp, *qq;
         2555         Wset *u;
         2556 
         2557         if(fdebug) {
         2558                 if(lastred) {
         2559                         Bprint(fdebug, "        0, /*%d*/\n", i);
         2560                 } else {
         2561                         Bprint(fdebug, "        \"");
         2562                         ITMLOOP(i, pp, qq)
         2563                                 Bprint(fdebug, "%s\\n", writem(pp->pitem));
         2564                         if(tystate[i] == MUSTLOOKAHEAD)
         2565                                 WSLOOP(wsets + (pstate[i+1] - pstate[i]), u)
         2566                                         if(*u->pitem < 0)
         2567                                                 Bprint(fdebug, "%s\\n", writem(u->pitem));
         2568                         Bprint(fdebug, "\", /*%d*/\n", i);
         2569                 }
         2570         }
         2571         if(foutput == 0)
         2572                 return;
         2573         Bprint(foutput, "\nstate %d\n", i);
         2574         ITMLOOP(i, pp, qq)
         2575                 Bprint(foutput, "\t%s\n", writem(pp->pitem));
         2576         if(tystate[i] == MUSTLOOKAHEAD)
         2577                 /* print out empty productions in closure */
         2578                 WSLOOP(wsets+(pstate[i+1]-pstate[i]), u)
         2579                         if(*u->pitem < 0)
         2580                                 Bprint(foutput, "\t%s\n", writem(u->pitem));
         2581 
         2582         /* check for state equal to another */
         2583         TLOOP(j0)
         2584                 if((j1=temp1[j0]) != 0) {
         2585                         Bprint(foutput, "\n\t%s  ", symnam(j0));
         2586                         /* shift, error, or accept */
         2587                         if(j1 > 0) {
         2588                                 if(j1 == ACCEPTCODE)
         2589                                         Bprint(foutput,  "accept");
         2590                                 else
         2591                                         if(j1 == ERRCODE)
         2592                                                 Bprint(foutput, "error");
         2593                                         else
         2594                                                 Bprint(foutput, "shift %d", j1);
         2595                         } else
         2596                                 Bprint(foutput, "reduce %d (src line %d)", -j1, rlines[-j1]);
         2597                 }
         2598 
         2599         /* output the final production */
         2600         if(lastred)
         2601                 Bprint(foutput, "\n\t.  reduce %d (src line %d)\n\n",
         2602                         lastred, rlines[lastred]);
         2603         else
         2604                 Bprint(foutput, "\n\t.  error\n\n");
         2605 
         2606         /* now, output nonterminal actions */
         2607         j1 = ntokens;
         2608         for(j0 = 1; j0 <= nnonter; j0++) {
         2609                 j1++;
         2610                 if(temp1[j1])
         2611                         Bprint(foutput, "\t%s  goto %d\n", symnam(j0+NTBASE), temp1[j1]);
         2612         }
         2613 }
         2614 
         2615 void
         2616 warray(char *s, int *v, int n)
         2617 {
         2618         int i;
         2619 
         2620         Bprint(ftable, "static\tconst\tshort        %s[] =\n{", s);
         2621         for(i=0;;) {
         2622                 if(i%10 == 0)
         2623                         Bprint(ftable, "\n");
         2624                 Bprint(ftable, "%4d", v[i]);
         2625                 i++;
         2626                 if(i >= n) {
         2627                         Bprint(ftable, "\n};\n");
         2628                         break;
         2629                 }
         2630                 Bprint(ftable, ",");
         2631         }
         2632 }
         2633 
         2634 /*
         2635  * in order to free up the mem and amem arrays for the optimizer,
         2636  * and still be able to output yyr1, etc., after the sizes of
         2637  * the action array is known, we hide the nonterminals
         2638  * derived by productions in levprd.
         2639  */
         2640 
         2641 void
         2642 hideprod(void)
         2643 {
         2644         int i, j;
         2645 
         2646         j = 0;
         2647         levprd[0] = 0;
         2648         PLOOP(1, i) {
         2649                 if(!(levprd[i] & REDFLAG)) {
         2650                         j++;
         2651                         if(foutput != 0)
         2652                                 Bprint(foutput, "Rule not reduced:   %s\n", writem(prdptr[i]));
         2653                 }
         2654                 levprd[i] = *prdptr[i] - NTBASE;
         2655         }
         2656         if(j)
         2657                 print("%d rules never reduced\n", j);
         2658 }
         2659 
         2660 void
         2661 callopt(void)
         2662 {
         2663         int i, *p, j, k, *q;
         2664 
         2665         /* read the arrays from tempfile and set parameters */
         2666         finput = Bopen(tempname, OREAD);
         2667         if(finput == 0)
         2668                 error("optimizer cannot open tempfile");
         2669 
         2670         pgo[0] = 0;
         2671         temp1[0] = 0;
         2672         nstate = 0;
         2673         nnonter = 0;
         2674         for(;;) {
         2675                 switch(gtnm()) {
         2676                 case '\n':
         2677                         nstate++;
         2678                         pmem--;
         2679                         temp1[nstate] = pmem - mem0;
         2680                 case ',':
         2681                         continue;
         2682                 case '$':
         2683                         break;
         2684                 default:
         2685                         error("bad tempfile %s", tempname);
         2686                 }
         2687                 break;
         2688         }
         2689 
         2690         pmem--;
         2691         temp1[nstate] = yypgo[0] = pmem - mem0;
         2692         for(;;) {
         2693                 switch(gtnm()) {
         2694                 case '\n':
         2695                         nnonter++;
         2696                         yypgo[nnonter] = pmem-mem0;
         2697                 case ',':
         2698                         continue;
         2699                 case -1:
         2700                         break;
         2701                 default:
         2702                         error("bad tempfile");
         2703                 }
         2704                 break;
         2705         }
         2706         pmem--;
         2707         yypgo[nnonter--] = pmem - mem0;
         2708         for(i = 0; i < nstate; i++) {
         2709                 k = 32000;
         2710                 j = 0;
         2711                 q = mem0 + temp1[i+1];
         2712                 for(p = mem0 + temp1[i]; p < q ; p += 2) {
         2713                         if(*p > j)
         2714                                 j = *p;
         2715                         if(*p < k)
         2716                                 k = *p;
         2717                 }
         2718                 /* nontrivial situation */
         2719                 if(k <= j) {
         2720                         /* j is now the range */
         2721 /*                        j -= k;                        *//* call scj */
         2722                         if(k > maxoff)
         2723                                 maxoff = k;
         2724                 }
         2725                 tystate[i] = (temp1[i+1]-temp1[i]) + 2*j;
         2726                 if(j > maxspr)
         2727                         maxspr = j;
         2728         }
         2729 
         2730         /* initialize ggreed table */
         2731         for(i = 1; i <= nnonter; i++) {
         2732                 ggreed[i] = 1;
         2733                 j = 0;
         2734 
         2735                 /* minimum entry index is always 0 */
         2736                 q = mem0 + yypgo[i+1] - 1;
         2737                 for(p = mem0+yypgo[i]; p < q ; p += 2) {
         2738                         ggreed[i] += 2;
         2739                         if(*p > j)
         2740                                 j = *p;
         2741                 }
         2742                 ggreed[i] = ggreed[i] + 2*j;
         2743                 if(j > maxoff)
         2744                         maxoff = j;
         2745         }
         2746 
         2747         /* now, prepare to put the shift actions into the amem array */
         2748         for(i = 0; i < ACTSIZE; i++)
         2749                 amem[i] = 0;
         2750         maxa = amem;
         2751         for(i = 0; i < nstate; i++) {
         2752                 if(tystate[i] == 0 && adb > 1)
         2753                         Bprint(ftable, "State %d: null\n", i);
         2754                 indgo[i] = YYFLAG1;
         2755         }
         2756         while((i = nxti()) != NOMORE)
         2757                 if(i >= 0)
         2758                         stin(i);
         2759                 else
         2760                         gin(-i);
         2761 
         2762         /* print amem array */
         2763         if(adb > 2 )
         2764                 for(p = amem; p <= maxa; p += 10) {
         2765                         Bprint(ftable, "%4d  ", (int)(p-amem));
         2766                         for(i = 0; i < 10; ++i)
         2767                                 Bprint(ftable, "%4d  ", p[i]);
         2768                         Bprint(ftable, "\n");
         2769                 }
         2770 
         2771         /* write out the output appropriate to the language */
         2772         aoutput();
         2773         osummary();
         2774         ZAPFILE(tempname);
         2775 }
         2776 
         2777 void
         2778 gin(int i)
         2779 {
         2780         int *p, *r, *s, *q1, *q2;
         2781 
         2782         /* enter gotos on nonterminal i into array amem */
         2783         ggreed[i] = 0;
         2784 
         2785         q2 = mem0+ yypgo[i+1] - 1;
         2786         q1 = mem0 + yypgo[i];
         2787 
         2788         /* now, find amem place for it */
         2789         for(p = amem; p < &amem[ACTSIZE]; p++) {
         2790                 if(*p)
         2791                         continue;
         2792                 for(r = q1; r < q2; r += 2) {
         2793                         s = p + *r + 1;
         2794                         if(*s)
         2795                                 goto nextgp;
         2796                         if(s > maxa)
         2797                                 if((maxa = s) > &amem[ACTSIZE])
         2798                                         error("a array overflow");
         2799                 }
         2800                 /* we have found amem spot */
         2801                 *p = *q2;
         2802                 if(p > maxa)
         2803                         if((maxa = p) > &amem[ACTSIZE])
         2804                                 error("a array overflow");
         2805                 for(r = q1; r < q2; r += 2) {
         2806                         s = p + *r + 1;
         2807                         *s = r[1];
         2808                 }
         2809                 pgo[i] = p-amem;
         2810                 if(adb > 1)
         2811                         Bprint(ftable, "Nonterminal %d, entry at %d\n", i, pgo[i]);
         2812                 return;
         2813 
         2814         nextgp:;
         2815         }
         2816         error("cannot place goto %d\n", i);
         2817 }
         2818 
         2819 void
         2820 stin(int i)
         2821 {
         2822         int *r, *s, n, flag, j, *q1, *q2;
         2823 
         2824         tystate[i] = 0;
         2825 
         2826         /* enter state i into the amem array */
         2827         q2 = mem0+temp1[i+1];
         2828         q1 = mem0+temp1[i];
         2829         /* find an acceptable place */
         2830         for(n = -maxoff; n < ACTSIZE; n++) {
         2831                 flag = 0;
         2832                 for(r = q1; r < q2; r += 2) {
         2833                         if(*r + n < 0)
         2834                                 goto nextn;
         2835                         s = *r + n + amem;
         2836                         if(*s == 0)
         2837                                 flag++;
         2838                         else
         2839                                 if(*s != r[1])
         2840                                         goto nextn;
         2841                 }
         2842 
         2843                 /* check that the position equals another only if the states are identical */
         2844                 for(j=0; j<nstate; j++) {
         2845                         if(indgo[j] == n) {
         2846 
         2847                                 /* we have some disagreement */
         2848                                 if(flag)
         2849                                         goto nextn;
         2850                                 if(temp1[j+1]+temp1[i] == temp1[j]+temp1[i+1]) {
         2851 
         2852                                         /* states are equal */
         2853                                         indgo[i] = n;
         2854                                         if(adb > 1)
         2855                                                 Bprint(ftable,
         2856                                                 "State %d: entry at %d equals state %d\n",
         2857                                                 i, n, j);
         2858                                         return;
         2859                                 }
         2860 
         2861                                 /* we have some disagreement */
         2862                                 goto nextn;
         2863                         }
         2864                 }
         2865 
         2866                 for(r = q1; r < q2; r += 2) {
         2867                         if((s = *r+n+amem) >= &amem[ACTSIZE])
         2868                                 error("out of space in optimizer a array");
         2869                         if(s > maxa)
         2870                                 maxa = s;
         2871                         if(*s != 0 && *s != r[1])
         2872                                 error("clobber of a array, pos'n %d, by %d", s-amem, r[1]);
         2873                         *s = r[1];
         2874                 }
         2875                 indgo[i] = n;
         2876                 if(adb > 1)
         2877                         Bprint(ftable, "State %d: entry at %d\n", i, indgo[i]);
         2878                 return;
         2879         nextn:;
         2880         }
         2881         error("Error; failure to place state %d\n", i);
         2882 }
         2883 
         2884 /*
         2885  * finds the next i
         2886  */
         2887 int
         2888 nxti(void)
         2889 {
         2890         int i, max, maxi;
         2891 
         2892         max = 0;
         2893         maxi = 0;
         2894         for(i = 1; i <= nnonter; i++)
         2895                 if(ggreed[i] >= max) {
         2896                         max = ggreed[i];
         2897                         maxi = -i;
         2898                 }
         2899         for(i = 0; i < nstate; ++i)
         2900                 if(tystate[i] >= max) {
         2901                         max = tystate[i];
         2902                         maxi = i;
         2903                 }
         2904         if(nxdb)
         2905                 Bprint(ftable, "nxti = %d, max = %d\n", maxi, max);
         2906         if(max == 0)
         2907                 return NOMORE;
         2908         return maxi;
         2909 }
         2910 
         2911 /*
         2912  * write summary
         2913  */
         2914 void
         2915 osummary(void)
         2916 {
         2917 
         2918         int i, *p;
         2919 
         2920         if(foutput == 0)
         2921                 return;
         2922         i = 0;
         2923         for(p = maxa; p >= amem; p--)
         2924                 if(*p == 0)
         2925                         i++;
         2926 
         2927         Bprint(foutput, "Optimizer space used: input %d/%d, output %d/%d\n",
         2928                 (int)(pmem-mem0+1), MEMSIZE, (int)(maxa-amem+1), ACTSIZE);
         2929         Bprint(foutput, "%d table entries, %d zero\n", (int)(maxa-amem+1), i);
         2930         Bprint(foutput, "maximum spread: %d, maximum offset: %d\n", maxspr, maxoff);
         2931 }
         2932 
         2933 /*
         2934  * this version is for C
         2935  * write out the optimized parser
         2936  */
         2937 void
         2938 aoutput(void)
         2939 {
         2940         Bprint(ftable, "#define\tYYLAST\t%d\n", (int)(maxa-amem+1));
         2941         arout("yyact", amem, (maxa-amem)+1);
         2942         arout("yypact", indgo, nstate);
         2943         arout("yypgo", pgo, nnonter+1);
         2944 }
         2945 
         2946 void
         2947 arout(char *s, int *v, int n)
         2948 {
         2949         int i;
         2950 
         2951         Bprint(ftable, "static\tconst\tshort        %s[] =\n{", s);
         2952         for(i = 0; i < n;) {
         2953                 if(i%10 == 0)
         2954                         Bprint(ftable, "\n");
         2955                 Bprint(ftable, "%4d", v[i]);
         2956                 i++;
         2957                 if(i == n)
         2958                         Bprint(ftable, "\n};\n");
         2959                 else
         2960                         Bprint(ftable, ",");
         2961         }
         2962 }
         2963 
         2964 /*
         2965  * read and convert an integer from the standard input
         2966  * return the terminating character
         2967  * blanks, tabs, and newlines are ignored
         2968  */
         2969 int
         2970 gtnm(void)
         2971 {
         2972         int sign, val, c;
         2973 
         2974         sign = 0;
         2975         val = 0;
         2976         while((c=Bgetrune(finput)) != Beof) {
         2977                 if(isvalidchar(c) && isdigit(c)) {
         2978                         val = val*10 + c-'0';
         2979                         continue;
         2980                 }
         2981                 if(c == '-') {
         2982                         sign = 1;
         2983                         continue;
         2984                 }
         2985                 break;
         2986         }
         2987         if(sign)
         2988                 val = -val;
         2989         *pmem++ = val;
         2990         if(pmem >= &mem0[MEMSIZE])
         2991                 error("out of space");
         2992         return c;
         2993 }