/*
* 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
* 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"
#include <unistd.h>
#include <locale.h>
#include <stdarg.h> /* For error() */
static void mktbls(void);
static void others(void);
static void summary(void);
static int setunion(int *, int *);
static void cpres(void);
static void cpfir(void);
static void cempty(void);
static void stagen(void);
static void exp_lkst(void);
static void exp_wsets(void);
static void exp_states(void);
static void exp_psmem(void);
/* lookahead computations */
int TBITSET;
static int lsetsize;
/* working set computations */
int cwp;
/* state information */
static int *tmp_lset;
/* generation lists */
/* storage for the actions in the parser */
/* other storage areas */
int size;
/* storage for information about the nonterminals */
/* yielding each nonterminal */
/* each nonterminal */
/* deriving e */
extern int nprodsz;
int
{
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#endif
(void) textdomain(TEXT_DOMAIN);
mktbls();
cpres(); /* make table of which productions yield a */
/* given nonterminal */
cempty(); /* make a table of which nonterminals can match */
/* the empty string */
cpfir(); /* make a table of firsts of nonterminals */
stagen(); /* generate the states */
output(); /* write the states and the tables */
go2out();
hideprod();
summary();
callopt();
others();
return (0);
}
static void
mktbls()
{
int i;
if (size < new_memsize)
size = new_memsize;
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* This error happens when yacc could not allocate
* initial memory to be used for internal tables.
*
* You may just translate this as:
* 'Could not allocate internally used memory.'
*/
"couldn't allocate initial table"));
/*
* For lkst
*/
tmp_lset = (int *)
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* Yacc could not allocate memory for table named lookset.
* Do not translate 'lookset'.
*
* You may just translate this as:
* 'Could not allocate internally used memory.'
*/
"could not allocate lookset array"));
for (i = 0; i <= INIT_LSIZE; ++i)
/*
* For wsets
*/
tmp_lset = (int *)
"could not allocate lookset array"));
for (i = 0; i <= nnontersz; ++i)
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* Do not translate mktbls(). It is a function name.
*
* You may just translate this as:
* 'Could not allocate internally used memory.'
*/
"cannot allocate tables in mktbls()"));
}
/* put out other arrays, copy the parsers */
static void
others()
{
extern int gen_lines;
int c, i, j;
int tmpline;
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* This error message is issued when yacc can not find
* the parser to be copied.
*/
"cannot find parser %s"),
parser);
/* had_act[i] is either 1 or 0 */
PLOOP(1, i)
TLOOP(i)
NTLOOP(i)
temp1[j] = -i;
error("cannot open yacc.debug");
if (gen_lines)
tmpline = 1;
/* copy parser text */
if (c == '\n')
tmpline++;
if (c == L'$') {
else { /* copy actions */
tmpline++;
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* This error is issued when yacc can not open a
* temporary file to be used. You do not need to
* use the word 'tempfile'. You can translate it to
* mean 'temporary file'.
*/
"cannot open action tempfile"));
if (gen_lines)
"\n# line\t%d \"%s\"",
parser);
}
}
}
}
/* copies string q into p, returning next free char ptr */
static wchar_t *
chcopy(p, q)
wchar_t *p, *q;
{
while (*p = *q++)
++p;
return (p);
}
/* creates output string for item pointed to by pp */
wchar_t *
int *pp;
{
int i, *p;
wchar_t *q;
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* This error is issued when yacc could not allocate
* memory for internally used array.
*
* You may just translate this as:
* 'Could not allocate internally used memory.'
*/
"could not allocate output string array"));
for (i = 0; i < isize; ++i)
sarr[i] = L' ';
}
for (p = pp; *p > 0; ++p) /* NULL */;
p = prdptr[-*p];
q = chcopy(q, L" : ");
for (;;) {
*q = 0;
if ((i = *p) <= 0)
break;
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* This error is issued when yacc could not allocate
* memory for internally used array.
*
* You may just translate this as:
* 'Could not allocate internally used memory.'
*/
"cannot expand sarr arrays"));
}
}
/* an item calling for a reduction */
if ((i = *pp) < 0) {
q = chcopy(q, L" (");
(void) wsprintf(q, "%d)", -i);
}
return (sarr);
}
/* return a pointer to the name of symbol i */
wchar_t *
symnam(int i)
{
if (*cp == L' ')
++cp;
return (cp);
}
static int zzcwp = 0;
static int zzclose = 0;
int zzgoent = 0;
int zzgobest = 0;
int zzacent = 0;
int zzexcp = 0;
int zzsrconf = 0;
int zzrrconf = 0;
/* output the summary on the tty */
static void
summary()
{
"\n%d/%d terminals, %d/%d nonterminals\n",
"%d/%d grammar rules, %d/%d states\n",
"memory: states,etc. %" PRIdPTR
"%d goto entries\n", zzgoent);
"%d entries saved by goto default\n", zzgobest);
}
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* You may just leave this message un-translated.
* This message only makes sense to those who knows
* how yacc works, and the person should know what
* this message means in English.
*/
"\nconflicts: "));
if (zzsrconf)
if (zzrrconf)
}
}
/* write out error comment */
/*PRINTFLIKE1*/
void
error(char *s, ...)
{
extern char *infile;
++nerrors;
if (!lineno)
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is a prefix to the error messages
* passed to error() function.
*/
"command line: fatal: "));
else {
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is a prefix to the error messages
* passed to error() function.
*/
"line %d: fatal: "),
lineno);
}
if (!fatfl)
return;
summary();
exit(1);
}
/*
* Print out a warning message.
*/
/*PRINTFLIKE2*/
void
{
extern char *infile;
/*
* If flag, print lineno as well.
*/
if (flag == 0)
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is a prefix to the warning messages
* passed to warning() function.
*/
"warning: "));
else
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is a prefix to the warning messages
* passed to warning() function.
*/
"line %d: warning: "),
lineno);
}
/* set elements 0 through n-1 to c */
void
aryfil(v, n, c)
int *v, n, c;
{
int i;
for (i = 0; i < n; ++i)
v[i] = c;
}
/* set a to the union of a and b */
/* return 1 if b is not a subset of a, 0 otherwise */
static int
setunion(a, b)
int *a, *b;
{
int i, x, sub;
sub = 0;
SETLOOP(i) {
*a = (x = *a) | *b++;
if (*a++ != x)
sub = 1;
}
return (sub);
}
static void
prlook(p)
LOOKSETS *p;
{
int j, *pp;
if (pp == 0)
else {
TLOOP(j) {
symnam(j));
}
}
}
/*
* 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
*/
static void
cpres()
{
int **ptrpy;
int **pyield;
int c, j, i;
/*
* 2/29/88 -
* nprodsz is the size of the tables describing the productions.
* Normally this will be NPROD unless the production tables have
* been expanded, in which case the tables will be NPROD * N(where
* N is the number of times the tables had to be expanded.)
*/
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* This error is issued when yacc could not allocate
* memory for internally used array.
*
* pyield is name of an array. You should not try to translate
* this word.
*
* You may just translate this as:
* 'Could not allocate internally used memory.'
*/
"cannot allocate space for pyield array"));
NTLOOP(i) {
c = i+NTBASE;
fatfl = 0; /* make undefined symbols nonfatal */
PLOOP(0, j) {
if (*prdptr[j] == c) /* linear search for all c's */
}
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* Ask somebody who knows yacc how to translate nonterminal or
* look at translated yacc document.
*/
"undefined nonterminal: %ws"),
}
}
fatfl = 1;
if (nerrors) {
summary();
exit(1);
}
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* This is an internal error message.
* Very little use to user. You may leave it
* un-translated.
*
* pyied is name of an array. Do not translate it.
*/
"internal Yacc error: pyield %d"),
}
static int indebug = 0;
/* compute an array with the first of nonterminals */
static void
cpfir()
{
NTLOOP(i) {
t = pres[i+1];
/* initially fill the sets */
for (s = pres[i]; s < t; ++s) {
/* check if ch is non-terminal */
for (p = *s; (ch = *p) > 0; ++p) {
break;
break;
}
}
}
/* now, reflect transitivity */
changes = 1;
while (changes) {
changes = 0;
NTLOOP(i) {
t = pres[i+1];
for (s = pres[i]; s < t; ++s) {
break;
}
}
}
}
NTLOOP(i)
if (!indebug)
return;
NTLOOP(i) {
}
}
}
/* sorts last state,and sees if it equals earlier ones. returns state number */
int
state(int c)
{
int i;
return (0); /* null state */
/* sort the items */
for (l = k-1; l >= p1; --l)
int *s;
s = k->pitem;
l->pitem = s;
}
}
i != 0; i = mstates[i]) {
/* get ith state */
continue;
k = p1;
break;
++k;
}
if (l != q2)
continue;
/* found it */
/* fix up lookaheads */
if (nolook)
return (i);
int s;
SETLOOP(s)
/* register the new set */
}
}
return (i);
}
/* state is new */
if (nolook)
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* You may leave this untranslated. Leave
*/
exp_states();
if (c >= NTBASE) {
} else {
}
return (nstate++);
}
static int pidebug = 0;
void
int *ptr;
{
register ITEM *j;
if (!nolook)
if (j > zzmemsz) {
zzmemsz = j;
exp_psmem();
/* error("out of state space"); */
}
}
/*
* mark nonterminals which derive the empty string
* also, look for nonterminals which don't derive any token strings
*/
static void
cempty()
{
#define WHOKNOWS 0
int i, *p;
/*
* first, use the array pempty to detect productions
* that can never be reduced
*/
/* set pempty to WHONOWS */
/*
* now, look at productions, marking nonterminals which
* derive something
*/
more:
PLOOP(0, i) {
continue;
for (p = prdptr[i] + 1; *p >= 0; ++p)
break;
if (*p < 0) { /* production can be derived */
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;
fatfl = 0;
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* Ask somebody who knows yacc how to translate nonterminal or
* look at translated yacc document. Check how 'derive' is
* translated in these documents also.
*/
"nonterminal %ws never derives any token string"),
}
}
if (nerrors) {
summary();
exit(1);
}
/*
* now, compute the pempty array, to see which nonterminals
* derive the empty string
*/
/* set pempty to WHOKNOWS */
/* loop as long as we keep finding empty nonterminals */
PLOOP(1, i) {
/* not known to be empty */
for (p = prdptr[i]+1;
;
/* we have a nontrivially empty nonterminal */
if (*p < 0) {
goto again; /* got one ... try for another */
}
}
}
}
/* generate the states */
static int gsdebug = 0;
static void
stagen()
{
int i, j;
int c;
register WSET *p, *q;
/* initialize */
nstate = 0;
nstate = 1;
/* now, the main state generation loop */
more:
SLOOP(i) {
continue;
/* take state i, close it, and do gotos */
closure(i);
if (p->flag)
continue;
p->flag = 1;
c = *(p->pitem);
if (c <= 1) {
tystate[i] = MUSTLOOKAHEAD;
continue;
}
/* do a goto on c */
WSLOOP(p, q) {
/* this item contributes to the goto */
if (c == *(q->pitem)) {
q->flag = 1;
}
}
if (c < NTBASE)
(void) state(c); /* register new state */
}
NTLOOP(j) {
if (temp1[j])
temp1[j]);
}
}
goto more; /* we have done one goto; do some more */
}
/* no more to do... stop */
}
/* generate the closure of state i */
void
closure(int i)
{
register WSET *u, *v;
int *pi;
int **s, **t;
ITEM *q;
register ITEM *p;
int idx1 = 0;
++zzclose;
/* first, copy kernel of state i to wsets */
cwp = 0;
ITMLOOP(i, p, q) {
SETLOOP(k)
}
/* 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;
/*
* only interesting case is where . is
* before nonterminal
*/
continue;
}
/* compute the lookahead */
/* find items involving c */
WSLOOP(u, v) {
v->flag = 0;
if (nolook)
continue;
/* terminal symbol */
break;
}
/* nonterminal symbol */
break;
}
if (ch <= 0)
}
}
/* 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 */
/* yes, it is there */
if (v->pitem == *s) {
if (nolook)
goto nexts;
goto nexts;
}
}
/* not there; make a new entry */
exp_wsets();
if (!nolook) {
work = 1;
SETLOOP(k)
}
nexts:;
}
}
}
/* have computed closure; flags are reset; return */
if (u->flag)
u->flag = 0;
}
}
}
static LOOKSETS *
flset(p)
LOOKSETS *p;
{
/* decide if the lookahead set pointed to by p is known */
/* return pointer to a perminent location for the set */
int j, *w;
int *u, *v;
register LOOKSETS *q;
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 */
exp_lkst();
}
return (q);
}
static void
exp_lkst()
{
int i, j;
tmp_lset = (int *)
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* Memory allocation error. Do not translate lookset.
*
* You may just translate this as:
* 'Could not allocate internally used memory.'
*/
"could not expand lookset array"));
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* Memory allocation error. Do not translate lookset.
*
* You may just translate this as:
* 'Could not allocate internally used memory.'
*/
"could not expand lookahead sets"));
for (i = 0; i <= nnonter; ++i)
for (i = 0; i <= nstate+1; ++i) {
}
}
static void
{
int i, j;
tmp_lset = (int *)
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* Memory allocation error. Do not translate lookset.
*
* You may just translate this as:
* 'Could not allocate internally used memory.'
*/
"could not expand lookset array"));
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* Memory allocation error. You may just transltate
* this as 'Could not allocate internally used memory.'
*
* You may just translate this as:
* 'Could not allocate internally used memory.'
*/
"could not expand working sets"));
}
static void
{
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* Memory allocation error.
*
* You may just translate this as:
* 'Could not allocate internally used memory.'
*/
"cannot expand table of states"));
}
static void
{
int i;
new_pstsize += PSTSIZE;
/*
* TRANSLATION_NOTE -- This is a message from yacc.
* This message is passed to error() function.
* Memory allocation error.
*
* You may just translate this as:
* 'Could not allocate internally used memory.'
*/
"cannot expand pstate memory"));
}