diff options
Diffstat (limited to 'unix/boot/xyacc/y3.c')
-rw-r--r-- | unix/boot/xyacc/y3.c | 606 |
1 files changed, 606 insertions, 0 deletions
diff --git a/unix/boot/xyacc/y3.c b/unix/boot/xyacc/y3.c new file mode 100644 index 00000000..1b6ac149 --- /dev/null +++ b/unix/boot/xyacc/y3.c @@ -0,0 +1,606 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Copyright (c) 1988 AT&T */ +/* All Rights Reserved */ + +//#pragma ident "%Z%%M% %I% %E% SMI" + +#include "dextern.h" + +static void go2gen (int); +static void precftn (int, int, int); +static void wract (int); +static void wrstate (int); +static void wdef (char *, int); +static void wrmbchars (void); + /* important local variables */ +static int lastred; /* number of the last reduction of a state */ +int *defact; +extern int *toklev; +extern int cwp; + +int exca[NSTATES * 2]; /* buffer states for printing with warray */ +int nexca; + + + /* I/O descriptors */ + +extern FILE *finput; /* input file */ +extern FILE *faction; /* file for saving actions */ +extern FILE *fdefine; /* file for #defines */ +extern FILE *fudecl; /* file for user declarations */ +extern FILE *ftable; /* parser tables file */ +extern FILE *fsppout; /* SPP output file */ +extern FILE *ftemp; /* tempfile to pass 2 */ +extern FILE *foutput; /* y.output file */ + + + + +/* print the output for the states */ +void +output () +{ + int i, k, c; + register WSET *u, *v; + + /* + (void) fprintf(fsppout, "static YYCONST yytabelem yyexca[] ={\n"); + */ + + SLOOP (i) { /* output the stuff for state i */ + nolook = !(tystate[i] == MUSTLOOKAHEAD); + closure (i); + /* output actions */ + nolook = 1; + aryfil (temp1, ntoksz + nnontersz + 1, 0); + WSLOOP (wsets, u) { + c = *(u->pitem); + if (c > 1 && c < NTBASE && temp1[c] == 0) { + WSLOOP (u, v) { + if (c == *(v->pitem)) + putitem (v->pitem + 1, (LOOKSETS *) 0); + } + temp1[c] = state (c); + } else if (c > NTBASE && temp1[(c -= NTBASE) + ntokens] == 0) { + temp1[c + ntokens] = amem[indgo[i] + c]; + } + } + if (i == 1) + temp1[1] = ACCEPTCODE; + /* now, we have the shifts; look at the reductions */ + lastred = 0; + WSLOOP (wsets, u) { + c = *(u->pitem); + if (c <= 0) { /* reduction */ + lastred = -c; + TLOOP (k) { + if (BIT (u->ws.lset, k)) { + if (temp1[k] == 0) + temp1[k] = c; + else if (temp1[k] < 0) { + /* + * reduce/reduce + * conflict + */ + /* BEGIN CSTYLED */ + if (foutput != NULL) + (void) fprintf (foutput, + WSFMT + ("\n%d: reduce/reduce conflict" + " (red'ns %d and %d ) on %s"), + i, -temp1[k], lastred, + symnam (k)); + if (-temp1[k] > lastred) + temp1[k] = -lastred; + ++zzrrconf; + /* END CSTYLED */ + } else + /* + * potentia + * shift/reduce + * conflict. + */ + precftn (lastred, k, i); + } + } + } + } + wract (i); + } + + /* + (void) fprintf(fsppout, "\t};\n"); + */ + warray ("yyexca", exca, nexca); + wdef ("YYNPROD", nprod); + if (nmbchars > 0) { + wrmbchars (); + } +} + +static int pkdebug = 0; +int +apack (p, n) + int *p; + int n; +{ + /* pack state i from temp1 into amem */ + int off; + int *pp, *qq; + int *q, *rr; + int diff; + + /* + * we don't need to worry about checking because we + * we will only look up entries known to be there... + */ + + /* eliminate leading and trailing 0's */ + + q = p + n; + for (pp = p, off = 0; *pp == 0 && pp <= q; ++pp, --off) + /* NULL */ ; + if (pp > q) + return (0); /* no actions */ + p = pp; + + /* now, find a place for the elements from p to q, inclusive */ + /* for( rr=amem; rr<=r; ++rr,++off ){ *//* try rr */ + rr = amem; + for (;; ++rr, ++off) { + while (rr >= &amem[new_actsize - 1]) + exp_act (&rr); + qq = rr; + for (pp = p; pp <= q; ++pp, ++qq) { + if (*pp) { + diff = qq - rr; + while (qq >= &amem[new_actsize - 1]) { + exp_act (&rr); + qq = diff + rr; + } + if (*pp != *qq && *qq != 0) + goto nextk; + } + } + + /* we have found an acceptable k */ + + if (pkdebug && foutput != NULL) + (void) fprintf (foutput, + "off = %d, k = %" PRIdPTR "\n", off, rr - amem); + + qq = rr; + for (pp = p; pp <= q; ++pp, ++qq) { + if (*pp) { + diff = qq - rr; + while (qq >= &amem[new_actsize - 1]) { + exp_act (&rr); + qq = diff + rr; + } + if (qq > memp) + memp = qq; + *qq = *pp; + } + } + if (pkdebug && foutput != NULL) { + for (pp = amem; pp <= memp; pp += 10) { + (void) fprintf (foutput, "\t"); + for (qq = pp; qq <= pp + 9; ++qq) + (void) fprintf (foutput, "%d ", *qq); + (void) fprintf (foutput, "\n"); + } + } + return (off); + nextk:; + } + /* error("no space in action table" ); */ + /* NOTREACHED */ +} + +void +go2out () +{ + /* output the gotos for the nontermninals */ + int i, j, k, best, count, cbest, times; + + (void) fprintf (ftemp, "$\n"); /* mark begining of gotos */ + + for (i = 1; i <= nnonter; ++i) { + go2gen (i); + /* find the best one to make default */ + best = -1; + times = 0; + for (j = 0; j < nstate; ++j) { /* is j the most frequent */ + if (tystate[j] == 0) + continue; + if (tystate[j] == best) + continue; + /* is tystate[j] the most frequent */ + count = 0; + cbest = tystate[j]; + for (k = j; k < nstate; ++k) + if (tystate[k] == cbest) + ++count; + if (count > times) { + best = cbest; + times = count; + } + } + + /* best is now the default entry */ + zzgobest += (times - 1); + for (j = 0; j < nstate; ++j) { + if (tystate[j] != 0 && tystate[j] != best) { + (void) fprintf (ftemp, "%d,%d,", j, tystate[j]); + zzgoent += 1; + } + } + + /* now, the default */ + + zzgoent += 1; + (void) fprintf (ftemp, "%d\n", best); + + } +} + +static int g2debug = 0; +static void +go2gen (int c) +{ + /* output the gotos for nonterminal c */ + int i, work, cc; + ITEM *p, *q; + + /* first, find nonterminals with gotos on c */ + aryfil (temp1, nnonter + 1, 0); + temp1[c] = 1; + + work = 1; + while (work) { + work = 0; + PLOOP (0, i) { + if ((cc = prdptr[i][1] - NTBASE) >= 0) { + /* cc is a nonterminal */ + if (temp1[cc] != 0) { + /* + * cc has a goto on c + * thus, the left side of + * production i does too. + */ + cc = *prdptr[i] - NTBASE; + if (temp1[cc] == 0) { + work = 1; + temp1[cc] = 1; + } + } + } + } + } + + /* now, we have temp1[c] = 1 if a goto on c in closure of cc */ + + if (g2debug && foutput != NULL) { + (void) fprintf (foutput, WSFMT ("%s: gotos on "), nontrst[c].name); + NTLOOP (i) if (temp1[i]) + (void) fprintf (foutput, WSFMT ("%s "), nontrst[i].name); + (void) fprintf (foutput, "\n"); + } + + /* now, go through and put gotos into tystate */ + aryfil (tystate, nstate, 0); + SLOOP (i) { + ITMLOOP (i, p, q) { + if ((cc = *p->pitem) >= NTBASE) { + if (temp1[cc -= NTBASE]) { + /* goto on c is possible */ + tystate[i] = amem[indgo[i] + c]; + break; + } + } + } + } +} + +/* decide a shift/reduce conflict by precedence. */ +static void +precftn (int r, int t, int s) +{ + + /* + * r is a rule number, t a token number + * the conflict is in state s + * temp1[t] is changed to reflect the action + */ + + int lp, lt, action; + + lp = levprd[r]; + lt = toklev[t]; + if (PLEVEL (lt) == 0 || PLEVEL (lp) == 0) { + /* conflict */ + if (foutput != NULL) + (void) fprintf (foutput, + WSFMT ("\n%d: shift/reduce conflict" + " (shift %d, red'n %d) on %s"), + s, temp1[t], r, symnam (t)); + ++zzsrconf; + return; + } + if (PLEVEL (lt) == PLEVEL (lp)) + action = ASSOC (lt) & ~04; + else if (PLEVEL (lt) > PLEVEL (lp)) + action = RASC; /* shift */ + else + action = LASC; /* reduce */ + + switch (action) { + case BASC: /* error action */ + temp1[t] = ERRCODE; + return; + case LASC: /* reduce */ + temp1[t] = -r; + return; + } +} + + +/* WRACT -- Output the state I. Modified to save state array in exca + * for later printing by warray. + */ +static void +wract (int i) +{ + /* output state i */ + /* temp1 has the actions, lastred the default */ + int p, p0, p1; + int ntimes, tred, count, j; + int flag; + + /* find the best choice for lastred */ + + lastred = 0; + ntimes = 0; + TLOOP (j) { + if (temp1[j] >= 0) + continue; + if (temp1[j] + lastred == 0) + continue; + /* count the number of appearances of temp1[j] */ + count = 0; + tred = -temp1[j]; + levprd[tred] |= REDFLAG; + TLOOP (p) { + if (temp1[p] + tred == 0) + ++count; + } + if (count > ntimes) { + lastred = tred; + ntimes = count; + } + } + + /* + * for error recovery, arrange that, if there is a shift on the + * error recovery token, `error', that the default be the error action + if (temp1[2] > 0) + */ + if (temp1[1] > 0) + lastred = 0; + + /* clear out entries in temp1 which equal lastred */ + TLOOP (p) { + if (temp1[p] + lastred == 0) + temp1[p] = 0; + } + + wrstate (i); + defact[i] = lastred; + + flag = 0; + TLOOP (p0) { + if ((p1 = temp1[p0]) != 0) { + if (p1 < 0) { + p1 = -p1; + goto exc; + } else if (p1 == ACCEPTCODE) { + p1 = -1; + goto exc; + } else if (p1 == ERRCODE) { + p1 = 0; + goto exc; + exc: + if (flag++ == 0) { + exca[nexca++] = -1; + exca[nexca++] = i; + } + exca[nexca++] = tokset[p0].value; + exca[nexca++] = p1; + ++zzexcp; + if (nexca >= NSTATES * 2) { + error ("state table overflow"); + } + } else { + (void) fprintf (ftemp, "%d,%d,", tokset[p0].value, p1); + ++zzacent; + } + } + } + if (flag) { + defact[i] = -2; + exca[nexca++] = -2; + exca[nexca++] = lastred; + } + (void) fprintf (ftemp, "\n"); +} + +static void +wrstate (int i) +{ + /* writes state i */ + int j0, j1; + register ITEM *pp, *qq; + register WSET *u; + + if (foutput == NULL) + return; + (void) fprintf (foutput, "\nstate %d\n", i); + ITMLOOP (i, pp, qq) { + (void) fprintf (foutput, WSFMT ("\t%s\n"), writem (pp->pitem)); + } + if (tystate[i] == MUSTLOOKAHEAD) { + /* print out empty productions in closure */ + WSLOOP (wsets + (pstate[i + 1] - pstate[i]), u) { + if (*(u->pitem) < 0) + (void) fprintf (foutput, WSFMT ("\t%s\n"), writem (u->pitem)); + } + } + + /* check for state equal to another */ + TLOOP (j0) if ((j1 = temp1[j0]) != 0) { + (void) fprintf (foutput, WSFMT ("\n\t%s "), symnam (j0)); + if (j1 > 0) { /* shift, error, or accept */ + if (j1 == ACCEPTCODE) + (void) fprintf (foutput, "accept"); + else if (j1 == ERRCODE) + (void) fprintf (foutput, "error"); + else + (void) fprintf (foutput, "shift %d", j1); + } else + (void) fprintf (foutput, "reduce %d", -j1); + } + + /* output the final production */ + if (lastred) + (void) fprintf (foutput, "\n\t. reduce %d\n\n", lastred); + else + (void) fprintf (foutput, "\n\t. error\n\n"); + + /* now, output nonterminal actions */ + j1 = ntokens; + for (j0 = 1; j0 <= nnonter; ++j0) { + if (temp1[++j1]) + (void) fprintf (foutput, + WSFMT ("\t%s goto %d\n"), + symnam (j0 + NTBASE), temp1[j1]); + } +} + +static void +wdef (char *s, int n) +{ + /* output a definition of s to the value n */ + (void) fprintf (fsppout, WSFMT ("define\t%s\t\t%d\n"), s, n); +} + +# define NDP_PERLINE 8 + +void +warray (s, v, n) + char *s; + int *v, n; +{ + register int i, j; + + fprintf (ftable, "short\t%s[%d]\n", s, n); + + for (j = 0; j < n; j += NDP_PERLINE) { + fprintf (ftable, "data\t(%s(i),i=%3d,%3d)\t/", + s, j + 1, (j + NDP_PERLINE < n) ? j + NDP_PERLINE : n); + + for (i = j; i < j + NDP_PERLINE && i < n; i++) { + if ((i == j + NDP_PERLINE - 1) || i >= n - 1) + fprintf (ftable, "%4d/\n", v[i]); + else + fprintf (ftable, "%4d,", v[i]); + } + } +} + +void +hideprod () +{ + /* + * in order to free up the mem and amem arrays for the optimizer, + * and still be able to output yyr1, etc., after the sizes of + * the action array is known, we hide the nonterminals + * derived by productions in levprd. + */ + + int i, j; + + j = 0; + levprd[0] = 0; + PLOOP (1, i) { + if (!(levprd[i] & REDFLAG)) { + ++j; + if (foutput != NULL) { + (void) fprintf (foutput, + WSFMT ("Rule not reduced: %s\n"), + writem (prdptr[i])); + } + } + levprd[i] = *prdptr[i] - NTBASE; + } + if (j) +/* + * TRANSLATION_NOTE -- This is a message from yacc. + * Check how 'reduced' is translated in yacc man page/document. + */ + (void) fprintf (stderr, "%d rules never reduced\n", j); +} + + +static int +cmpmbchars (p, q) + MBCLIT *p, *q; +{ + /* Compare two MBLITs. */ + return ((p->character) - (q->character)); +} + +static void +wrmbchars () +{ + int i; + + return wdef ("YYNMBCHARS", nmbchars); + qsort (mbchars, nmbchars, sizeof (*mbchars), + (int (*)(const void *, const void *)) cmpmbchars); + (void) fprintf (ftable, + "static struct{\n\tchar character;" + "\n\tint tvalue;\n}yymbchars[YYNMBCHARS]={\n"); + for (i = 0; i < nmbchars; ++i) { + (void) fprintf (ftable, "\t{%#x,%d}", + (int) mbchars[i].character, mbchars[i].tvalue); + if (i < nmbchars - 1) { + /* Not the last. */ + (void) fprintf (ftable, ",\n"); + } + } + (void) fprintf (ftable, "\n};\n"); +} |