Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!cs.utexas.edu!uunet!murtoa.cs.mu.oz.au!mulga!munnari.oz.au!otc!metro!extro!glenn From: glenn@extro.ucc.su.oz (G. Geers [ext 3241]) Newsgroups: comp.os.minix Subject: yacc for minix (2 of 4) Message-ID: <488@extro.ucc.su.oz> Date: 28 Jun 89 10:41:01 GMT Reply-To: glenn@extro.ucc.su.oz (G. Geers [ext 3241]) Organization: University Computing Service, Uni. of Sydney, Australia. Lines: 2049 --- cut here --- cut here --- cut here --- cut here --- cut here --- #!/bin/sh # This is a shell archive. Remove anything before the /bin/sh line # then unpack it by saving it in a file and typing "sh file" # (Files unpacked will be owned by you and have default permissions). # Don't worry about trailing garbage - the archive ends with exit # This archive contains the following files: # ./yarout.c # ./yaryfl.c # ./ycemty.c # ./ychcpy.c # ./ychfnd.c # ./yclopt.c # ./yclsur.c # ./ycpact.c # ./ycpfir.c # ./ycpres.c # ./ycpuni.c # ./ycpycd.c # ./ycstsh.c # ./ydefin.c # ./ydfout.c # ./yerror.c # ./yfdtyp.c # ./yflset.c # ./yfnact.c # ./yg2gen.c # ./yg2out.c # ./ygin.c # ./ygtnm.c # ./ygttok.c # ./yhdprd.c # ./ymain.c # ./ymkfil # ./ynxti.c # ./yosmry.c # ./yothrs.c # ./youtpt.c # if `test ! -s ./yarout.c` then echo "writing ./yarout.c" cat > ./yarout.c << '\EOF\' /* * yarout.c - * * HISTORY */ #include "y4.h" int arout(s, v, n) char *s; int *v, n; { register i; fprintf(ftable, "short %s[]={\n", s); for (i = 0; i < n; ) { if (i % 10 == 0) fprintf(ftable, "\n"); fprintf(ftable, "%4d", v[i]); if (++i == n) fprintf(ftable, " };\n"); else fprintf(ftable, ","); } } \EOF\ else echo "will not over write ./yarout.c" fi if `test ! -s ./yaryfl.c` then echo "writing ./yaryfl.c" cat > ./yaryfl.c << '\EOF\' /* * yaryfl.c - set elements 0 through n-1 to c * * HISTORY */ #include "y1.h" int aryfil(v, n, c) int *v, n, c; { register int i; for (i = 0; i < n; ++i) v[i] = c; } \EOF\ else echo "will not over write ./yaryfl.c" fi if `test ! -s ./ycemty.c` then echo "writing ./ycemty.c" cat > ./ycemty.c << '\EOF\' /* * ycemty.c - mark nonterminals which derive the empty string * * In addition to looking for empty nonterminals, look for nonterminals * which don't derive any token strings. Both of these should be optimized * away. * * HISTORY * {1} 12-Apr-83 Bob Denny * Add symbolic exit status. * */ #include "y1.h" #define EMPTY 1 #define WHOKNOWS 0 #define OK 1 int cempty() { register i, *p; /* * first, use the array pempty to detect productions that can * never be reduced */ /* set pempty to WHONOWS */ aryfil(pempty, nnonter + 1, WHOKNOWS); /* * now, look at productions, marking nonterminals which derive * something */ more: PLOOP(0, i) { if (pempty[*prdptr[i] - NTBASE]) continue; for (p = prdptr[i] + 1; *p >= 0; ++p) { if (*p >= NTBASE && pempty[*p - NTBASE] == WHOKNOWS) break; } if (*p < 0) { /* production can be derived */ pempty[*prdptr[i] - NTBASE] = OK; goto more; } } /* now, look at the nonterminals, to see if they are all OK */ NTLOOP(i) { /* * the added production rises or falls as the start symbol * ... */ if (i == 0) continue; if (pempty[i] != OK) { fatfl = 0; error("nonterminal %s never derives any token string", nontrst[i].name); } } if (nerrors) { summary(); exit(EX_ERR); } /* * now, compute the pempty array, to see which nonterminals derive * the empty string */ /* set pempty to WHOKNOWS */ aryfil(pempty, nnonter + 1, WHOKNOWS); /* loop as long as we keep finding empty nonterminals */ again: PLOOP(1, i) { if (pempty[*prdptr[i] - NTBASE] == WHOKNOWS) { /* not known to be empty */ for (p = prdptr[i] + 1; *p >= NTBASE && pempty[*p - NTBASE] == EMPTY; ++p) ; if (*p < 0) { /* * we have a nontrivially empty * nonterminal */ pempty[*prdptr[i] - NTBASE] = EMPTY; goto again; /* got one ... try for * another */ } } } } \EOF\ else echo "will not over write ./ycemty.c" fi if `test ! -s ./ychcpy.c` then echo "writing ./ychcpy.c" cat > ./ychcpy.c << '\EOF\' /* * ychcpy.c - copies string q into p, return next free char ptr * * HISTORY */ #include "y1.h" char *chcopy(p, q) char *p, *q; { while (*p = *q++) ++p; return (p); } \EOF\ else echo "will not over write ./ychcpy.c" fi if `test ! -s ./ychfnd.c` then echo "writing ./ychfnd.c" cat > ./ychfnd.c << '\EOF\' /* * ychfnd.c - * * HISTORY */ #include "y2.h" int chfind( t, s ) register char *s; { int i; if (s[0] == ' ') t = 0; TLOOP(i) { if (!strcmp(s, tokset[i].name)) { return (i); } } NTLOOP(i) { if (!strcmp(s, nontrst[i].name)) { return (i + NTBASE); } } /* cannot find name */ if (t > 1) error("%s should have been defined earlier", s); return (defin(t, s)); } \EOF\ else echo "will not over write ./ychfnd.c" fi if `test ! -s ./yclopt.c` then echo "writing ./yclopt.c" cat > ./yclopt.c << '\EOF\' /* * yclopt.c - * * HISTORY */ #include "y4.h" int callopt() { register i, *p, j, k, *q; /* read the arrays from tempfile and set parameters */ if ((finput = fopen(TEMPNAME, "r")) == NULL) error("optimizer cannot open tempfile"); pgo[0] = 0; yypact[0] = 0; nstate = 0; nnonter = 0; for (; ; ) { switch (gtnm()) { case '\n': yypact[++nstate] = (--pmem) - mem0; case ',': continue; case '$': break; default: error("bad tempfile"); } break; } yypact[nstate] = yypgo[0] = (--pmem) - mem0; for (; ; ) { switch (gtnm()) { case '\n': yypgo[++nnonter] = pmem - mem0; case '\r': case ',': continue; case -1: /* EOF */ break; default: error("bad tempfile"); } break; } yypgo[nnonter--] = (--pmem) - mem0; for (i = 0; i < nstate; ++i) { k = 32000; j = 0; q = mem0 + yypact[i + 1]; for (p = mem0 + yypact[i]; p < q; p += 2) { if (*p > j) j = *p; if (*p < k) k = *p; } if (k <= j) { /* nontrivial situation */ /* * temporarily, kill this for compatibility j -= * k; j is now the range */ if (k > maxoff) maxoff = k; } greed[i] = (yypact[i + 1] - yypact[i]) + 2 * j; if (j > maxspr) maxspr = j; } /* initialize ggreed table */ for (i = 1; i <= nnonter; ++i) { ggreed[i] = 1; j = 0; /* minimum entry index is always 0 */ q = mem0 + yypgo[i + 1] - 1; for (p = mem0 + yypgo[i]; p < q; p += 2) { ggreed[i] += 2; if (*p > j) j = *p; } ggreed[i] = ggreed[i] + 2 * j; if (j > maxoff) maxoff = j; } /* now, prepare to put the shift actions into the a array */ for (i = 0; i < ACTSIZE; ++i) a[i] = 0; maxa = a; for (i = 0; i < nstate; ++i) { if (greed[i] == 0 && adb > 1) fprintf(ftable, "State %d: null\n", i); pa[i] = YYFLAG1; } while ((i = nxti()) != NOMORE) { if (i >= 0) stin(i); else gin(-i); } if (adb > 2) { /* print a array */ for (p = a; p <= maxa; p += 10) { fprintf(ftable, "%4d ", p - a); for (i = 0; i < 10; ++i) fprintf(ftable, "%4d ", p[i]); fprintf(ftable, "\n"); } } /* write out the output appropriate to the language */ aoutput(); osummary(); fclose(finput); ZAPFILE(TEMPNAME); } \EOF\ else echo "will not over write ./yclopt.c" fi if `test ! -s ./yclsur.c` then echo "writing ./yclsur.c" cat > ./yclsur.c << '\EOF\' /* * yclsur.c - generate closure of state i * * HISTORY * {1} 28-Aug-81 Bob Denny * Modified to make debug code conditionally compile. * */ #include "y1.h" int closure(i) { int c, ch, work, k; register struct wset *u, *v; int *pi; int **s, **t; struct item *q; register struct item *p; ++zzclose; /* first, copy kernel of state i to wsets */ cwp = wsets; ITMLOOP(i, p, q) { cwp->pitem = p->pitem; cwp->flag = 1; /* this item must get closed */ SETLOOP(k) cwp->ws.lset[k] = p->look->lset[k]; WSBUMP(cwp); } /* now, go through the loop, closing each item */ work = 1; while (work) { work = 0; WSLOOP(wsets, u) { if (u->flag == 0) continue; c = *(u->pitem); /* dot is before c */ if (c < NTBASE) { u->flag = 0; continue; /* only interesting case * is where . is before * nonterminal */ } /* compute the lookahead */ aryfil(clset.lset, tbitset, 0); /* find items involving c */ WSLOOP(u, v) { if (v->flag == 1 && *(pi = v->pitem) == c) { v->flag = 0; if (nolook) continue; while ((ch = *++pi) > 0) { if (ch < NTBASE) { /* terminal symbol */ SETBIT(clset.lset, ch); break; } /* nonterminal symbol */ setunion(clset.lset, pfirst[ch - NTBASE]->lset); if (!pempty[ch - NTBASE]) break; } if (ch <= 0) setunion(clset.lset, v->ws.lset); } } /* now loop over productions derived from c */ c -= NTBASE; /* c is now nonterminal number */ t = pres[c + 1]; for (s = pres[c]; s < t; ++s) { /* put these items into the closure */ WSLOOP(wsets, v) { /* is the item there */ if (v->pitem == *s) { /* yes, it is there */ if (nolook) goto nexts; if (setunion(v->ws.lset, clset.lset)) v->flag = work = 1; goto nexts; } } /* not there; make a new entry */ if (cwp - wsets + 1 >= WSETSIZE) error("working set overflow"); cwp->pitem = *s; cwp->flag = 1; if (!nolook) { work = 1; SETLOOP(k) cwp->ws.lset[k] = clset.lset[k]; } WSBUMP(cwp); nexts: ; } } } /* have computed closure; flags are reset; return */ if (cwp > zzcwp) zzcwp = cwp; #ifdef debug if (foutput != NULL) { fprintf(foutput, "\nState %d, nolook = %d\n", i, nolook); WSLOOP(wsets, u) { if (u->flag) fprintf(foutput, "flag set!\n"); u->flag = 0; fprintf(foutput, "\t%s", writem(u->pitem)); prlook(&u->ws); fprintf(foutput, "\n"); } } #endif } \EOF\ else echo "will not over write ./yclsur.c" fi if `test ! -s ./ycpact.c` then echo "writing ./ycpact.c" cat > ./ycpact.c << '\EOF\' /* * ycpact.c - copy C action to next ; or closing curly brace * * HISTORY */ #include #include #include "y2.h" int cpyact(offset) int offset; { int brac, c, match, j, s, tok; fprintf(faction, "\n# line %d\n", lineno); brac = 0; loop: c = unix_getc(finput); swt: switch (c) { case ';': if (brac == 0) { putc(c, faction); return; } goto lcopy; case '{': brac++; goto lcopy; case '$': s = 1; tok = -1; c = unix_getc(finput); if (c == '<') { /* type description */ ungetc(c, finput); if (gettok() != TYPENAME) error("bad syntax on $ clause"); tok = numbval; c = unix_getc(finput); } if (c == '$') { fprintf(faction, "yyval"); if (ntypes) { /* put out the proper tag... */ if (tok < 0) tok = fdtype(*prdptr[nprod]); fprintf(faction, ".%s", typeset[tok]); } goto loop; } if (c == '-') { s = -s; c = unix_getc(finput); } if (isdigit(c)) { j = 0; while (isdigit(c)) { j = j * 10 + c - '0'; c = unix_getc(finput); } j = j * s - offset; if (j > 0) { error("Illegal use of $%d", j + offset); } fprintf(faction, "yypvt[-%d]", -j); if (ntypes) { /* put out the proper tag */ if (j + offset <= 0 && tok < 0) error("must specify type of $%d", j + offset); if (tok < 0) tok = fdtype(prdptr[nprod][j + offset]); fprintf(faction, ".%s", typeset[tok]); } goto swt; } putc('$', faction); if (s < 0) putc('-', faction); goto swt; case '}': if (--brac) goto lcopy; putc(c, faction); return; case '/': /* look for comments */ putc(c, faction); c = unix_getc(finput); if (c != '*') goto swt; /* it really is a comment */ putc(c, faction); c = unix_getc(finput); while (c != EOF) { while (c == '*') { putc(c, faction); if ((c = unix_getc(finput)) == '/') goto lcopy; } putc(c, faction); if (c == '\n') ++lineno; c = unix_getc(finput); } error("EOF inside comment"); case '\'': /* character constant */ match = '\''; goto string; case '"': /* character string */ match = '"'; string: putc(c, faction); while (c = unix_getc(finput)) { if (c == '\\') { putc(c, faction); c = unix_getc(finput); if (c == '\n') ++lineno; } else if (c == match) goto lcopy; else if (c == '\n') error("newline in string or char. const."); putc(c, faction); } error("EOF in string or character constant"); case -1: /* EOF */ error("action does not terminate"); case '\n': ++lineno; goto lcopy; } lcopy: putc(c, faction); goto loop; } \EOF\ else echo "will not over write ./ycpact.c" fi if `test ! -s ./ycpfir.c` then echo "writing ./ycpfir.c" cat > ./ycpfir.c << '\EOF\' /* * ycpfir.c - compute an array with the first of nonterminals * * HISTORY * {1} 28-Aug-81 Bob Denny * Modified to make debug code conditionally compile. * */ #include "y1.h" int cpfir() { /* compute an array with the first of nonterminals */ register *p, **s, i, **t, ch, changes; int *tmp; tmp = &wsets[nnonter]; zzcwp = tmp; NTLOOP(i) { aryfil(wsets[i].ws.lset, tbitset, 0); t = pres[i + 1]; for (s = pres[i]; s < t; ++s) { /* initially fill the sets */ for (p = *s; (ch = *p) > 0; ++p) { if (ch < NTBASE) { SETBIT(wsets[i].ws.lset, ch); break; } else if (!pempty[ch - NTBASE]) break; } } } /* now, reflect transitivity */ changes = 1; while (changes) { changes = 0; NTLOOP(i) { t = pres[i + 1]; for (s = pres[i]; s < t; ++s) { for (p = *s; (ch = (*p - NTBASE)) >= 0; ++p) { changes |= setunion(wsets[i].ws.lset, wsets[ch].ws.lset); if (!pempty[ch]) break; } } } } NTLOOP(i) pfirst[i] = flset(&wsets[i].ws); #ifdef debug if ((foutput != NULL)) { NTLOOP(i) { fprintf(foutput, "\n%s: ", nontrst[i].name); prlook(pfirst[i]); fprintf(foutput, " %d\n", pempty[i]); } } #endif } \EOF\ else echo "will not over write ./ycpfir.c" fi if `test ! -s ./ycpres.c` then echo "writing ./ycpres.c" cat > ./ycpres.c << '\EOF\' /* * ycpres.c - compute an array with the beginnings of productions * * compute an array with the beginnings of productions yielding given * nonterminals The array pres points to these lists the array pyield has * the lists: the total size is only NPROD+1 * * HISTORY * {1} 12-Apr-83 Bob Denny * Add symbol exit status. * */ #include "y1.h" extern int *pyield[NPROD]; int cpres() { register **pmem; register c, j, i; pmem = pyield; NTLOOP(i) { c = i + NTBASE; pres[i] = pmem; fatfl = 0; /* make undefined symbols nonfatal */ PLOOP(0, j) { if (*prdptr[j] == c) *pmem++ = prdptr[j] + 1; } if (pres[i] == pmem) { error("nonterminal %s not defined!", nontrst[i].name); } } pres[i] = pmem; fatfl = 1; if (nerrors) { summary(); exit(EX_ERR); } if (pmem != &pyield[nprod]) error("internal Yacc error: pyield %d", pmem - &pyield[nprod]); } \EOF\ else echo "will not over write ./ycpres.c" fi if `test ! -s ./ycpuni.c` then echo "writing ./ycpuni.c" cat > ./ycpuni.c << '\EOF\' /* * ycpuni.c - copy the union declaration & define file (if present) to output * * HISTORY */ #include "y2.h" int cpyunion() { int level, c; fprintf(ftable, "\n# line %d\n", lineno); fprintf(ftable, "\n#define UNION 1\n"); fprintf(ftable, "typedef union "); if (fdefine) fprintf(fdefine, "\ntypedef union "); level = 0; for (; ; ) { if ((c = unix_getc(finput)) < 0) error("EOF encountered while processing %%union"); putc(c, ftable); if (fdefine) putc(c, fdefine); switch (c) { case '\n': ++lineno; break; case '{': ++level; break; case '}': --level; if (level == 0) { /* we are finished copying */ fprintf(ftable, " YYSTYPE;\n"); if (fdefine) fprintf(fdefine, " YYSTYPE;\nextern YYSTYPE yylval;\n"); return; } } } } \EOF\ else echo "will not over write ./ycpuni.c" fi if `test ! -s ./ycpycd.c` then echo "writing ./ycpycd.c" cat > ./ycpycd.c << '\EOF\' /* * ycpycd.c - copies code between \{ and \} * * HISTORY */ #include "y2.h" int cpycode() { int c; c = unix_getc(finput); if (c == '\n') { c = unix_getc(finput); lineno++; } fprintf(ftable, "\n# line %d\n", lineno); while (c >= 0) { if (c == '\\') if ((c = unix_getc(finput)) == '}') return; else putc('\\', ftable); if (c == '%') if ((c = unix_getc(finput)) == '}') return; else putc('%', ftable); putc(c, ftable); if (c == '\n') ++lineno; c = unix_getc(finput); } error("eof before %%}"); } \EOF\ else echo "will not over write ./ycpycd.c" fi if `test ! -s ./ycstsh.c` then echo "writing ./ycstsh.c" cat > ./ycstsh.c << '\EOF\' #include "y2.h" char * cstash( s ) register char *s; { char *temp; temp = cnamp; do { if ( cnamp >= &cnames[cnamsz] ) error("too many characters in id's and literals" ); else *cnamp++ = *s; } while ( *s++); return( temp ); } \EOF\ else echo "will not over write ./ycstsh.c" fi if `test ! -s ./ydefin.c` then echo "writing ./ydefin.c" cat > ./ydefin.c << '\EOF\' #include "y2.h" defin( t, s ) register char *s; { /* define s to be a terminal if t=0 or a nonterminal if t=1 */ register val; if (t) { if ( ++nnonter >= NNONTERM ) error("too many nonterminals, limit %d", NNONTERM); nontrst[nnonter].name = cstash(s); return( NTBASE + nnonter ); } /* must be a token */ if ( ++ntokens >= NTERMS ) error("too many terminals, limit %d", NTERMS ); tokset[ntokens].name = cstash(s); /* establish value for token */ if ( s[0] == ' ' && s[2] == '\0' ) /* single character literal */ val = s[1]; else if ( s[0] == ' ' && s[1] == '\\' ) { /* escape sequence */ if ( s[3] == '\0' ) { /* single character escape sequence */ switch ( s[2] ) { /* character which is escaped */ case 'n': val = '\n'; break; case 'r': val = '\r'; break; case 'b': val = '\b'; break; case 't': val = '\t'; break; case 'f': val = '\f'; break; case '\'': val = '\''; break; case '"': val = '"'; break; case '\\': val = '\\'; break; default: error( "invalid escape" ); } } else if ( s[2] <= '7' && s[2] >= '0' ) { /* \nnn sequence */ if ( s[3] < '0' || s[3] > '7' || s[4] < '0' || s[4] > '7' || s[5] != '\0' ) error("illegal \\nnn construction" ); val = 64 * s[2] + 8 * s[3] + s[4] - 73 * '0'; if ( val == 0 ) error( "'\\000' is illegal" ); } } else { val = extval++; } tokset[ntokens].value = val; toklev[ntokens] = 0; return( ntokens ); } \EOF\ else echo "will not over write ./ydefin.c" fi if `test ! -s ./ydfout.c` then echo "writing ./ydfout.c" cat > ./ydfout.c << '\EOF\' /* * ydfout.c - * * HISTORY */ #include #include "y2.h" int defout() { /* write out the defines (at the end of the declaration section) */ register int i, c; register char *cp; for (i = ndefout; i <= ntokens; ++i) { cp = tokset[i].name; if (*cp == ' ') ++cp; /* literals */ for (; (c = *cp) != '\0'; ++cp) { if (islower(c) || isupper(c) || isdigit(c) || c == '_') ; /* VOID */ else goto nodef; } fprintf(ftable, "# define %s %d\n", tokset[i].name, tokset[i].value); if (fdefine != NULL) fprintf(fdefine, "# define %s %d\n", tokset[i].name, tokset[i].value); nodef: ; } ndefout = ntokens + 1; } \EOF\ else echo "will not over write ./ydfout.c" fi if `test ! -s ./yerror.c` then echo "writing ./yerror.c" cat > ./yerror.c << '\EOF\' #include "y1.h" /* * 12-Apr-83 (RBD) Add symbolic exit status */ /* VARARGS1 */ error(s, a1) char *s; { /* write out error comment */ ++nerrors; fprintf( stderr, "\n fatal error: "); fprintf( stderr, s, a1); fprintf( stderr, ", line %d\n", lineno ); if ( !fatfl ) return; summary(); exit(EX_ERR); } \EOF\ else echo "will not over write ./yerror.c" fi if `test ! -s ./yfdtyp.c` then echo "writing ./yfdtyp.c" cat > ./yfdtyp.c << '\EOF\' #include "y2.h" fdtype( t ) { /* determine the type of a symbol */ register v; if ( t >= NTBASE ) v = nontrst[t-NTBASE].tvalue; else v = TYPE( toklev[t] ); if ( v <= 0 ) error( "must specify type for %s", (t >= NTBASE) ? nontrst[t-NTBASE].name : tokset[t].name ); return( v ); } \EOF\ else echo "will not over write ./yfdtyp.c" fi if `test ! -s ./yflset.c` then echo "writing ./yflset.c" cat > ./yflset.c << '\EOF\' #include "y1.h" struct looksets *flset( p ) struct looksets *p; { /* decide if the lookahead set pointed to by p is known */ /* return pointer to a perminent location for the set */ register struct looksets *q; int j, *w; register *u, *v; for ( q = &lkst[nlset]; q-- > lkst; ) { u = p->lset; v = q->lset; w = &v[tbitset]; while ( v < w) if ( *u++ != *v++) goto more; /* we have matched */ return( q ); more: ; } /* add a new one */ q = &lkst[nlset++]; if ( nlset >= LSETSIZE ) error("too many lookahead sets" ); SETLOOP(j) { q->lset[j] = p->lset[j]; } return( q ); } \EOF\ else echo "will not over write ./yflset.c" fi if `test ! -s ./yfnact.c` then echo "writing ./yfnact.c" cat > ./yfnact.c << '\EOF\' #include "y2.h" finact() { /* finish action routine */ fclose(faction); fprintf( ftable, "# define YYERRCODE %d\n", tokset[2].value ); } \EOF\ else echo "will not over write ./yfnact.c" fi if `test ! -s ./yg2gen.c` then echo "writing ./yg2gen.c" cat > ./yg2gen.c << '\EOF\' #include "y3.h" /* * yg2gen.3c * * Modified to make debug code conditionally compile. * 28-Aug-81 * Bob Denny */ go2gen(c) { /* output the gotos for nonterminal c */ int i, work, cc; struct item *p, *q; /* first, find nonterminals with gotos on c */ aryfil( temp1, nnonter + 1, 0 ); temp1[c] = 1; work = 1; while ( work ) { work = 0; PLOOP(0, i) { if ( (cc = prdptr[i][1] - NTBASE) >= 0 ) { /* cc is a nonterminal */ if ( temp1[cc] != 0 ) { /* cc has a goto on c */ cc = *prdptr[i] - NTBASE; /* thus, the left side of production i does too */ if ( temp1[cc] == 0 ) { work = 1; temp1[cc] = 1; } } } } } /* now, we have temp1[c] = 1 if a goto on c in closure of cc */ #ifdef debug if ( foutput != NULL ) { fprintf( foutput, "%s: gotos on ", nontrst[c].name ); NTLOOP(i) if ( temp1[i] ) fprintf( foutput, "%s ", nontrst[i].name); fprintf( foutput, "\n"); } #endif /* 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; } } } } } \EOF\ else echo "will not over write ./yg2gen.c" fi if `test ! -s ./yg2out.c` then echo "writing ./yg2out.c" cat > ./yg2out.c << '\EOF\' #include "y3.h" go2out() { /* output the gotos for the nontermninals */ int i, j, k, best, count, cbest, times; fprintf( ftemp, "$\n" ); /* mark begining of gotos */ for ( i = 1; i <= nnonter; ++i ) { go2gen(i); /* find the best one to make default */ best = -1; times = 0; for ( j = 0; j <= nstate; ++j ) { /* is j the most frequent */ if ( tystate[j] == 0 ) continue; if ( tystate[j] == best ) continue; /* is tystate[j] the most frequent */ count = 0; cbest = tystate[j]; for ( k = j; k <= nstate; ++k ) if ( tystate[k] == cbest ) ++count; if ( count > times ) { best = cbest; times = count; } } /* best is now the default entry */ zzgobest += (times - 1); for ( j = 0; j <= nstate; ++j ) { if ( tystate[j] != 0 && tystate[j] != best ) { fprintf( ftemp, "%d,%d,", j, tystate[j] ); zzgoent += 1; } } /* now, the default */ zzgoent += 1; fprintf( ftemp, "%d\n", best ); } } \EOF\ else echo "will not over write ./yg2out.c" fi if `test ! -s ./ygin.c` then echo "writing ./ygin.c" cat > ./ygin.c << '\EOF\' #include "y4.h" gin(i) { register *p, *r, *s, *q1, *q2; /* enter gotos on nonterminal i into array a */ ggreed[i] = 0; q2 = mem0 + yypgo[i+1] - 1; q1 = mem0 + yypgo[i]; /* now, find a place for it */ for ( p = a; p < &a[ACTSIZE]; ++p ) { if ( *p ) continue; for ( r = q1; r < q2; r += 2 ) { s = p + *r + 1; if ( *s ) goto nextgp; if ( s > maxa ) { if ( (maxa = s) > &a[ACTSIZE] ) error( "a array overflow" ); } } /* we have found a spot */ *p = *q2; if ( p > maxa ) { if ( (maxa = p) > &a[ACTSIZE] ) error( "a array overflow" ); } for ( r = q1; r < q2; r += 2 ) { s = p + *r + 1; *s = r[1]; } pgo[i] = p - a; if ( adb > 1 ) fprintf( ftable, "Nonterminal %d, entry at %d\n" , i, pgo[i] ); goto nextgi; nextgp: ; } error( "cannot place goto %d\n", i ); nextgi: ; } \EOF\ else echo "will not over write ./ygin.c" fi if `test ! -s ./ygtnm.c` then echo "writing ./ygtnm.c" cat > ./ygtnm.c << '\EOF\' /* * ygtnm.c - * * HISTORY */ #include #include "y4.h" int gtnm() { register s, val, c; /* read and convert an integer from the standard input */ /* return the terminating character */ /* blanks, tabs, and newlines are ignored */ s = 1; val = 0; while ((c = unix_getc(finput)) != EOF) { if (isdigit(c)) { val = val * 10 + c - '0'; } else if (c == '-') s = -1; else if (c == '\r') continue; else break; } *pmem++ = s * val; if (pmem > &mem0[MEMSIZE]) error("out of space"); return (c); } \EOF\ else echo "will not over write ./ygtnm.c" fi if `test ! -s ./ygttok.c` then echo "writing ./ygttok.c" cat > ./ygttok.c << '\EOF\' /* * ygttok.c - * * HISTORY */ #include #include "y2.h" extern int peekline; /* number of '\n' seen in lookahead */ int gettok() { register i, base; register c, match, reserve; begin: reserve = 0; lineno += peekline; peekline = 0; c = unix_getc(finput); while (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r') { if (c == '\n') ++lineno; c = unix_getc(finput); } if (c == '/') { /* skip comment */ lineno += skipcom(); goto begin; } switch (c) { case -1: /* EOF */ return (ENDFILE); case '{': ungetc(c, finput); return ('='); /* action ... */ case '<': /* get, and look up, a type name (union * member name) */ i = 0; while ((c = unix_getc(finput)) != '>' && c >= 0 && c != '\n') { tokname[i] = c; if (++i >= NAMESIZE) --i; } if (c != '>') error("unterminated < ... > clause"); tokname[i] = '\0'; for (i = 1; i <= ntypes; ++i) { if (!strcmp(typeset[i], tokname)) { numbval = i; return (TYPENAME); } } typeset[numbval = ++ntypes] = cstash(tokname); return (TYPENAME); case '"': case '\'': match = c; tokname[0] = ' '; i = 1; for (; ; ) { c = unix_getc(finput); if (c == '\n' || c == EOF) error("illegal or missing ' or \""); if (c == '\\') { c = unix_getc(finput); tokname[i] = '\\'; if (++i >= NAMESIZE) --i; } else if (c == match) break; tokname[i] = c; if (++i >= NAMESIZE) --i; } break; case '%': case '\\': switch (c = unix_getc(finput)) { case '0': return (TERM); case '<': return (LEFT); case '2': return (BINARY); case '>': return (RIGHT); case '%': case '\\': return (MARK); case '=': return (PREC); case '{': return (LCURLY); default: reserve = 1; } default: if (isdigit(c)) { /* number */ numbval = c - '0'; base = (c == '0') ? 8 : 10; for (c = unix_getc(finput); isdigit(c); c = getc(finput)) { numbval = numbval * base + c - '0'; } ungetc(c, finput); return (NUMBER); } else if (islower(c) || isupper(c) || c == '_' || c == '.' || c == '$') { i = 0; while (islower(c) || isupper(c) || isdigit(c) || c == '_' || c == '.' || c == '$') { tokname[i] = c; if (reserve && isupper(c)) tokname[i] += 'a' - 'A'; if (++i >= NAMESIZE) --i; c = unix_getc(finput); } } else return (c); ungetc(c, finput); } tokname[i] = '\0'; if (reserve) { /* find a reserved word */ if (!strcmp(tokname, "term")) return (TERM); if (!strcmp(tokname, "token")) return (TERM); if (!strcmp(tokname, "left")) return (LEFT); if (!strcmp(tokname, "nonassoc")) return (BINARY); if (!strcmp(tokname, "binary")) return (BINARY); if (!strcmp(tokname, "right")) return (RIGHT); if (!strcmp(tokname, "prec")) return (PREC); if (!strcmp(tokname, "start")) return (START); if (!strcmp(tokname, "type")) return (TYPEDEF); if (!strcmp(tokname, "union")) return (UNION); error("invalid escape, or illegal reserved word: %s", tokname); } /* look ahead to distinguish IDENTIFIER from C_IDENTIFIER */ c = unix_getc(finput); while (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '/') { if (c == '\n') ++peekline; else if (c == '/') { /* look for comments */ peekline += skipcom(); } c = unix_getc(finput); } if (c == ':') return (C_IDENTIFIER); ungetc(c, finput); return (IDENTIFIER); } \EOF\ else echo "will not over write ./ygttok.c" fi if `test ! -s ./yhdprd.c` then echo "writing ./yhdprd.c" cat > ./yhdprd.c << '\EOF\' #include "y3.h" 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. */ register i, j; j = 0; levprd[0] = 0; PLOOP(1, i) { if ( !(levprd[i] & REDFLAG) ) { ++j; if ( foutput != NULL ) { fprintf( foutput, "Rule not reduced: %s\n", writem( prdptr[i] ) ); } } levprd[i] = *prdptr[i] - NTBASE; } if ( j ) fprintf( stdout, "%d rules never reduced\n", j ); } \EOF\ else echo "will not over write ./yhdprd.c" fi if `test ! -s ./ymain.c` then echo "writing ./ymain.c" cat > ./ymain.c << '\EOF\' #include "y1.h" /* * 12-Apr-83 (RBD) Add symbolic exit status */ main(argc, argv) int argc; char *argv[]; { puts("Setup..."); setup(argc, argv); /* initialize and read productions */ puts("cpres ..."); tbitset = NWORDS(ntokens); cpres(); /* make table of which productions yield a given nonterminal */ puts("cempty ..."); cempty(); /* make a table of which nonterminals can match the empty string */ puts("cpfir ..."); cpfir(); /* make a table of firsts of nonterminals */ puts("stagen ..."); stagen(); /* generate the states */ puts("output ..."); output(); /* write the states and the tables */ puts("go2out ..."); go2out(); puts("hideprod ..."); hideprod(); puts("summary ..."); summary(); puts("callopt ..."); callopt(); puts("others ..."); others(); puts("DONE !!!"); exit(EX_SUC); } \EOF\ else echo "will not over write ./ymain.c" fi if `test ! -s ./ymkfil` then echo "writing ./ymkfil" cat > ./ymkfil << '\EOF\' CFLAGS = -Ot -Ml LDFLAGS = -Ml -s OBJECTS = y1imp.o y2imp.o y3imp.o y4imp.o yaryfl.o ycemty.o ychcpy.o\ yclsur.o ycpfir.o ycpres.o yerror.o yflset.o ymain.o yothrs.o\ yprlok.o yptitm.o ysmnam.o ystagn.o ystate.o ystuni.o ysumry.o\ ywritm.o ychfnd.o ycpact.o ycpuni.o ycpycd.o ycstsh.o ydefin.o\ ydfout.o yfdtyp.o yfnact.o ygttok.o ysetup.o yskpcm.o yapack.o\ yg2gen.o yg2out.o yhdprd.o youtpt.o yprcft.o ywarry.o ywract.o\ ywstat.o yaoput.o yclopt.o ygin.o ygtnm.o ynxti.o yosmry.o\ ystin.o yarout.o PROGRAMS = yacc all: ${PROGRAMS} clean: rm -f ${PROGRAMS} rm -f ${OBJECTS} rm -f a.out core yacc: ${OBJECTS} cc ${LDFLAGS} ${OBJECTS} -o yacc dtxtrn.h: /usr/include/stdio.h system.h y1.h: dtxtrn.h y1imp.o: dtxtrn.h y2.h: dtxtrn.h y2imp.o: dtxtrn.h y3.h: dtxtrn.h y3imp.o: dtxtrn.h y4.h: dtxtrn.h y4imp.o: dtxtrn.h yaoput.o: y4.h yapack.o: y3.h yarout.o: y4.h yaryfl.o: y1.h ycemty.o: y1.h ychcpy.o: y1.h ychfnd.o: y2.h yclopt.o: y4.h yclsur.o: y1.h ycpact.o: /usr/include/stdio.h /usr/include/ctype.h y2.h ycpfir.o: y1.h ycpres.o: y1.h ycpuni.o: y2.h ycpycd.o: y2.h ycstsh.o: y2.h ydefin.o: y2.h ydfout.o: /usr/include/ctype.h y2.h yerror.o: y1.h yfdtyp.o: y2.h yflset.o: y1.h yfnact.o: y2.h yg2gen.o: y3.h yg2out.o: y3.h ygin.o: y4.h ygtnm.o: /usr/include/ctype.h y4.h ygttok.o: /usr/include/ctype.h y2.h yhdprd.o: y3.h ymain.o: y1.h ynxti.o: y4.h yosmry.o: y4.h yothrs.o: y1.h youtpt.o: y3.h yprcft.o: y3.h yprlok.o: y1.h yptitm.o: y1.h ysetup.o: y2.h yskpcm.o: y2.h ysmnam.o: y1.h ystagn.o: y1.h ystate.o: y1.h ystin.o: y4.h ystuni.o: y1.h ysumry.o: y1.h ywarry.o: y3.h ywract.o: y3.h ywritm.o: y1.h ywstat.o: y3.h \EOF\ else echo "will not over write ./ymkfil" fi if `test ! -s ./ynxti.c` then echo "writing ./ynxti.c" cat > ./ynxti.c << '\EOF\' #include "y4.h" nxti() { /* finds the next i */ register i, max, maxi; max = 0; for ( i = 1; i <= nnonter; ++i ) if ( ggreed[i] >= max ) { max = ggreed[i]; maxi = -i; } for ( i = 0; i < nstate; ++i ) if ( greed[i] >= max ) { max = greed[i]; maxi = i; } if ( nxdb ) fprintf( ftable, "nxti = %d, max = %d\n", maxi, max ); if ( max == 0 ) return( NOMORE ); else return( maxi ); } \EOF\ else echo "will not over write ./ynxti.c" fi if `test ! -s ./yosmry.c` then echo "writing ./yosmry.c" cat > ./yosmry.c << '\EOF\' #include "y4.h" /* * Write summary. */ osummary() { register int i, *p; if (foutput == NULL) return; i = 0; for (p = maxa; p >= a; --p) { if (*p == 0) ++i; } fprintf(foutput, "Optimizer space used: input %d/%d, output %d/%d\n", pmem - mem0 + 1, MEMSIZE, maxa - a + 1, ACTSIZE); fprintf(foutput, "%d table entries, %d zero\n", (maxa - a) + 1, i); fprintf(foutput, "maximum spread: %d, maximum offset: %d\n", maxspr, maxoff); fclose(foutput); } \EOF\ else echo "will not over write ./yosmry.c" fi if `test ! -s ./yothrs.c` then echo "writing ./yothrs.c" cat > ./yothrs.c << '\EOF\' /* Edits: * 06-Dec-80 Original code broken out of y1.c. * 18-Dec-80 Add conditional code for Decus for tempfile deletion. */ #include "y1.h" int others() { /* put out other arrays, copy the parsers */ register c, i, j; finput = (FILE * )fopen(PARSER, "r"); if (finput == (FILE * )NULL) error("cannot find parser %s", PARSER); warray("yyr1", levprd, nprod); aryfil(temp1, nprod, 0); PLOOP(1, i) temp1[i] = prdptr[i + 1] - prdptr[i] - 2; warray("yyr2", temp1, nprod); aryfil(temp1, nstate, -1000); TLOOP(i) { for (j = tstates[i]; j != 0; j = mstates[j]) { temp1[j] = tokset[i].value; } } NTLOOP(i) { for (j = ntstates[i]; j != 0; j = mstates[j]) { temp1[j] = -i; } } warray("yychk", temp1, nstate); warray("yydef", defact, nstate); /* copy parser text */ while ((c = unix_getc(finput)) != EOF) { if (c == '$') { if ((c = unix_getc(finput)) != 'A') putc('$', ftable); else { /* copy actions */ faction = fopen(ACTNAME, "r"); if (faction == NULL) error("cannot reopen action tempfile"); while ((c = unix_getc(faction)) != EOF) putc(c, ftable); fclose(faction); ZAPFILE(ACTNAME); c = unix_getc(finput); } } putc(c, ftable); } fclose(ftable); } int unix_getc(iop) FILE *iop; { int c; c = getc(iop); /* Stop on Control-Z */ if (c == '\032') return (EOF); else return (c); } \EOF\ else echo "will not over write ./yothrs.c" fi if `test ! -s ./youtpt.c` then echo "writing ./youtpt.c" cat > ./youtpt.c << '\EOF\' #include "y3.h" output() { /* print the output for the states */ int i, k, c; register struct wset *u, *v; fprintf( ftable, "short yyexca[] ={\n" ); SLOOP(i) { /* output the stuff for state i */ nolook = !(tystate[i] == MUSTLOOKAHEAD); closure(i); /* output actions */ nolook = 1; aryfil( temp1, ntokens + nnonter + 1, 0 ); WSLOOP(wsets, u) { c = *( u->pitem ); if ( c > 1 && c < NTBASE && temp1[c] == 0 ) { WSLOOP(u, v) { if ( c == *(v->pitem) ) putitem( v->pitem + 1, (struct looksets *)0 ); } temp1[c] = state(c); } else if ( c > NTBASE && temp1[ (c -= NTBASE) + ntokens ] == 0 ) { temp1[ c+ntokens ] = amem[indgo[i]+c]; } } if ( i == 1 ) temp1[1] = ACCEPTCODE; /* now, we have the shifts; look at the reductions */ lastred = 0; WSLOOP(wsets, u) { c = *( u->pitem ); if ( c <= 0 ) { /* reduction */ lastred = -c; TLOOP(k) { if ( BIT(u->ws.lset, k) ) { if ( temp1[k] == 0 ) temp1[k] = c; else if ( temp1[k] < 0 ) { /* reduce/reduce conflict */ if ( foutput != NULL ) fprintf( foutput, "\n%d: reduce/reduce conflict (red'ns %d and %d ) on %s", i, -temp1[k], lastred, symnam(k) ); if ( -temp1[k] > lastred ) temp1[k] = -lastred; ++zzrrconf; } else { /* potential shift/reduce conflict */ precftn( lastred, k, i ); } } } } } wract(i); } fprintf( ftable, "\t};\n" ); wdef( "YYNPROD", nprod ); } \EOF\ else echo "will not over write ./youtpt.c" fi echo "Finished archive 2 of 4" # if you want to concatenate archives, remove anything after this line exit 0