#include "dextern.h"
#include "sgs.h"
#include <stdio.h>
#define IDENTIFIER 257
#define MARK 258
#define TERM 259
#define LEFT 260
#define RIGHT 261
#define BINARY 262
#define PREC 263
#define LCURLY 264
#define C_IDENTIFIER 265
#define NUMBER 266
#define START 267
#define TYPEDEF 268
#define TYPENAME 269
#define UNION 270
#define ENDFILE 0
#define LHS_TEXT_LEN 80
#define RHS_TEXT_LEN 640
#define v_FLAG 0x01
#define d_FLAG 0x02
#define DEFAULT_PREFIX "y"
char *infile;
static int numbval;
static int toksize = NAMESIZE;
static wchar_t *tokname;
char *parser = PARSER;
static void finact(void);
static wchar_t *cstash(wchar_t *);
static void defout(void);
static void cpyunion(void);
static void cpycode(void);
static void cpyact(int);
static void lhsfill(wchar_t *);
static void rhsfill(wchar_t *);
static void lrprnt(void);
static void beg_debug(void);
static void end_toks(void);
static void end_debug(void);
static void exp_tokname(void);
static void exp_prod(void);
static void exp_ntok(void);
static void exp_nonterm(void);
static int defin(int, wchar_t *);
static int gettok(void);
static int chfind(int, wchar_t *);
static int skipcom(void);
static int findchtok(int);
static void put_prefix_define(char *);
static wchar_t cnamesblk0[CNAMSZ];
static wchar_t *cnames = cnamesblk0;
static wchar_t *cnamp = cnamesblk0;
static int ndefout = 3;
static int defunion = 0;
static int ntypes = 0;
static wchar_t *typeset[NTYPES];
int ntokens = 0;
int ntoksz = NTERMS;
TOKSYMB *tokset;
int *toklev;
int nnonter = -1;
NTSYMB *nontrst;
int nnontersz = NNONTERM;
static int start;
static int extval = 0;
FILE *finput;
FILE *faction;
FILE *fdefine;
FILE *ftable;
FILE *ftemp;
FILE *fdebug;
FILE *foutput;
static wchar_t *lhstext;
static wchar_t *rhstext;
int *mem0;
int *mem;
int *tracemem;
extern int *optimmem;
int new_memsize = MEMSIZE;
int nprod = 1;
int nprodsz = NPROD;
int **prdptr;
int *levprd;
wchar_t *had_act;
int gen_lines = 1;
int act_lines = 0;
static int gen_testing = 0;
static char *v_stmp = "n";
int nmbchars = 0;
MBCLIT *mbchars = (MBCLIT *) 0;
int nmbcharsz = 0;
#define F_NAME_LENGTH 128
void
setup(int argc, char *argv[])
{
int ii, i, j, lev, t, ty;
int c;
int *p;
char *cp;
wchar_t actname[8];
unsigned int options = 0;
char *file_prefix = DEFAULT_PREFIX;
char *sym_prefix = "";
char fname[F_NAME_LENGTH+1];
foutput = NULL;
fdefine = NULL;
i = 1;
tokname = malloc(sizeof (wchar_t) * toksize);
tokset = malloc(sizeof (TOKSYMB) * ntoksz);
toklev = malloc(sizeof (int) * ntoksz);
nontrst = malloc(sizeof (NTSYMB) * nnontersz);
mem0 = malloc(sizeof (int) * new_memsize);
prdptr = malloc(sizeof (int *) * (nprodsz + 2));
levprd = malloc(sizeof (int) * (nprodsz + 2));
had_act = calloc(nprodsz + 2, sizeof (wchar_t));
lhstext = calloc(LHS_TEXT_LEN, sizeof (wchar_t));
rhstext = calloc(RHS_TEXT_LEN, sizeof (wchar_t));
aryfil(toklev, ntoksz, 0);
aryfil(levprd, nprodsz, 0);
for (ii = 0; ii < ntoksz; ++ii)
tokset[ii].value = 0;
for (ii = 0; ii < nnontersz; ++ii)
nontrst[ii].tvalue = 0;
aryfil(mem0, new_memsize, 0);
mem = mem0;
tracemem = mem0;
while ((c = getopt(argc, argv, "vVdltp:Q:Y:P:b:")) != EOF)
switch (c) {
case 'v':
options |= v_FLAG;
break;
case 'V':
(void) fprintf(stderr, "yacc: %s %s\n",
(const char *)SGU_PKG,
(const char *)SGU_REL);
break;
case 'Q':
v_stmp = optarg;
if (*v_stmp != 'y' && *v_stmp != 'n')
error(gettext(
"yacc: -Q should be followed by [y/n]"));
break;
case 'd':
options |= d_FLAG;
break;
case 'l':
gen_lines = 0;
break;
case 't':
gen_testing = 1;
break;
case 'Y':
cp = (char *)malloc(strlen(optarg)+
sizeof ("/yaccpar") + 1);
cp = strcpy(cp, optarg);
parser = strcat(cp, "/yaccpar");
break;
case 'P':
parser = optarg;
break;
case 'p':
if (strcmp(optarg, "yy") != 0)
sym_prefix = optarg;
else
sym_prefix = "";
break;
case 'b':
file_prefix = optarg;
break;
case '?':
default:
(void) fprintf(stderr, gettext(
"Usage: yacc [-vVdltY] [-Q(y/n)] [-b file_prefix] [-p sym_prefix]"
" [-P parser] file\n"));
exit(1);
}
if (options & v_FLAG) {
(void) strncpy(fname, file_prefix,
F_NAME_LENGTH - strlen(".output"));
(void) strcat(fname, ".output");
foutput = fopen(fname, "w");
if (foutput == NULL)
error(gettext(
"cannot open y.output"));
}
if (options & d_FLAG) {
(void) strncpy(fname, file_prefix,
F_NAME_LENGTH - strlen(".tab.h"));
(void) strcat(fname, ".tab.h");
fdefine = fopen(fname, "w");
if (fdefine == NULL)
error(gettext("cannot open y.tab.h"));
}
fdebug = fopen(DEBUGNAME, "w");
if (fdebug == NULL)
error(gettext(
"cannot open yacc.debug"));
(void) strncpy(fname, file_prefix,
F_NAME_LENGTH - strlen(".tab.c"));
(void) strcat(fname, ".tab.c");
ftable = fopen(fname, "w");
if (ftable == NULL)
error(gettext(
"cannot open %s"), fname);
ftemp = fopen(TEMPNAME, "w");
faction = fopen(ACTNAME, "w");
if (ftemp == NULL || faction == NULL)
error(gettext(
"cannot open temp file"));
if ((finput = fopen(infile = argv[optind], "r")) == NULL)
error(gettext(
"cannot open input file"));
lineno = 1;
cnamp = cnames;
(void) defin(0, L"$end");
extval = 0400;
(void) defin(0, L"error");
(void) defin(1, L"$accept");
mem = mem0;
lev = 0;
ty = 0;
i = 0;
beg_debug();
t = gettok();
if (*v_stmp == 'y')
(void) fprintf(ftable, "#ident\t\"yacc: %s %s\"\n",
(const char *)SGU_PKG, (const char *)SGU_REL);
for (; t != MARK && t != ENDFILE; ) {
int tok_in_line;
switch (t) {
case L';':
t = gettok();
break;
case START:
if ((t = gettok()) != IDENTIFIER) {
error("bad %%start construction");
}
start = chfind(1, tokname);
t = gettok();
continue;
case TYPEDEF:
tok_in_line = 0;
if ((t = gettok()) != TYPENAME)
error(gettext(
"bad syntax in %%type"));
ty = numbval;
for (;;) {
t = gettok();
switch (t) {
case IDENTIFIER:
tok_in_line = 1;
if ((t = chfind(1, tokname)) < NTBASE) {
j = TYPE(toklev[t]);
if (j != 0 && j != ty) {
error(gettext(
"type redeclaration of token %ws"),
tokset[t].name);
}
else
SETTYPE(toklev[t], ty);
} else {
j = nontrst[t-NTBASE].tvalue;
if (j != 0 && j != ty) {
error(gettext(
"type redeclaration of nonterminal %ws"),
nontrst[t-NTBASE].name);
}
else
nontrst[t-NTBASE].tvalue = ty;
}
case L',':
continue;
case L';':
t = gettok();
break;
default:
break;
}
if (!tok_in_line)
error(gettext(
"missing tokens or illegal tokens"));
break;
}
continue;
case UNION:
cpyunion();
defunion = 1;
t = gettok();
continue;
case LEFT:
case BINARY:
case RIGHT:
i++;
case TERM:
tok_in_line = 0;
lev = (t-TERM) | 04;
ty = 0;
t = gettok();
if (t == TYPENAME) {
ty = numbval;
t = gettok();
}
for (;;) {
switch (t) {
case L',':
t = gettok();
continue;
case L';':
break;
case IDENTIFIER:
tok_in_line = 1;
j = chfind(0, tokname);
if (j > NTBASE) {
error(gettext(
"%ws is not a token."),
tokname);
}
if (lev & ~04) {
if (ASSOC(toklev[j]) & ~04)
error(gettext(
"redeclaration of precedence of %ws"),
tokname);
SETASC(toklev[j], lev);
SETPLEV(toklev[j], i);
} else {
if (ASSOC(toklev[j]))
(void) warning(1,
gettext(
"redeclaration of precedence of %ws."),
tokname);
SETASC(toklev[j], lev);
}
if (ty) {
if (TYPE(toklev[j]))
error(gettext(
"redeclaration of type of %ws"),
tokname);
SETTYPE(toklev[j], ty);
}
if ((t = gettok()) == NUMBER) {
tokset[j].value = numbval;
if (j < ndefout && j > 2) {
error(gettext(
"type number of %ws should be defined earlier"),
tokset[j].name);
}
if (numbval >= -YYFLAG1) {
error(gettext(
"token numbers must be less than %d"),
-YYFLAG1);
}
t = gettok();
}
continue;
}
if (!tok_in_line)
error(gettext(
"missing tokens or illegal tokens"));
break;
}
continue;
case LCURLY:
defout();
cpycode();
t = gettok();
continue;
default:
error("syntax error");
}
}
if (t == ENDFILE) {
error("unexpected EOF before %%%%");
}
defout();
end_toks();
(void) fprintf(ftable, "\n#include <inttypes.h>\n");
(void) fprintf(ftable, "#include <stdlib.h>\n");
(void) fprintf(ftable, "#include <string.h>\n");
(void) fprintf(ftable, "\n#include <values.h>\n");
if (sym_prefix[0] != '\0')
put_prefix_define(sym_prefix);
(void) fprintf(ftable, "#define yyclearin yychar = -1\n");
(void) fprintf(ftable, "#define yyerrok yyerrflag = 0\n");
(void) fprintf(ftable, "extern int yychar;\nextern int yyerrflag;\n");
if (!(defunion || ntypes))
(void) fprintf(ftable,
"#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n");
(void) fprintf(ftable, "YYSTYPE yylval;\n");
(void) fprintf(ftable, "YYSTYPE yyval;\n");
(void) fprintf(ftable, "typedef int yytabelem;\n");
(void) fprintf(ftable,
"#ifndef YYMAXDEPTH\n#define YYMAXDEPTH 150\n#endif\n");
(void) fprintf(ftable, "#if YYMAXDEPTH > 0\n");
(void) fprintf(ftable, "int yy_yys[YYMAXDEPTH], *yys = yy_yys;\n");
(void) fprintf(ftable, "YYSTYPE yy_yyv[YYMAXDEPTH], *yyv = yy_yyv;\n");
(void) fprintf(ftable, "#else /* user does initial allocation */\n");
(void) fprintf(ftable, "int *yys;\nYYSTYPE *yyv;\n#endif\n");
(void) fprintf(ftable, "static int yymaxdepth = YYMAXDEPTH;\n");
prdptr[0] = mem;
*mem++ = NTBASE;
*mem++ = start;
*mem++ = 1;
*mem++ = 0;
prdptr[1] = mem;
while ((t = gettok()) == LCURLY)
cpycode();
if (t != C_IDENTIFIER)
error("bad syntax on first rule");
if (!start)
prdptr[0][1] = chfind(1, tokname);
while (t != MARK && t != ENDFILE) {
if (t == L'|') {
rhsfill((wchar_t *)0);
*mem = *prdptr[nprod-1];
if (++mem >= &tracemem[new_memsize])
exp_mem(1);
} else if (t == C_IDENTIFIER) {
*mem = chfind(1, tokname);
if (*mem < NTBASE)
error(gettext(
"illegal nonterminal in grammar rule"));
if (++mem >= &tracemem[new_memsize])
exp_mem(1);
lhsfill(tokname);
} else
error(gettext(
"illegal rule: missing semicolon or | ?"));
t = gettok();
more_rule:
while (t == IDENTIFIER) {
*mem = chfind(1, tokname);
if (*mem < NTBASE)
levprd[nprod] = toklev[*mem]& ~04;
if (++mem >= &tracemem[new_memsize])
exp_mem(1);
rhsfill(tokname);
t = gettok();
}
if (t == PREC) {
if (gettok() != IDENTIFIER)
error(gettext(
"illegal %%prec syntax"));
j = chfind(2, tokname);
if (j >= NTBASE)
error(gettext(
"nonterminal %ws illegal after %%prec"),
nontrst[j-NTBASE].name);
levprd[nprod] = toklev[j] & ~04;
t = gettok();
}
if (t == L'=') {
had_act[nprod] = 1;
levprd[nprod] |= ACTFLAG;
(void) fprintf(faction, "\ncase %d:", nprod);
cpyact(mem-prdptr[nprod] - 1);
(void) fprintf(faction, " break;");
if ((t = gettok()) == IDENTIFIER) {
lrprnt();
(void) wsprintf(actname, "$$%d", nprod);
j = chfind(1, actname);
if (mem + 2 >= &tracemem[new_memsize])
exp_mem(1);
for (p = mem; p >= prdptr[nprod]; --p)
p[2] = *p;
mem += 2;
p = prdptr[nprod];
*p++ = j;
*p++ = -nprod;
levprd[nprod+1] = levprd[nprod] & ~ACTFLAG;
levprd[nprod] = ACTFLAG;
if (++nprod >= nprodsz)
exp_prod();
prdptr[nprod] = p;
*mem++ = j;
if (mem >= &tracemem[new_memsize])
exp_mem(1);
goto more_rule;
}
}
while (t == L';')
t = gettok();
*mem++ = -nprod;
if (mem >= &tracemem[new_memsize])
exp_mem(1);
if (ntypes && !(levprd[nprod] & ACTFLAG) &&
nontrst[*prdptr[nprod]-NTBASE].tvalue) {
int tempty;
tempty = prdptr[nprod][1];
if (tempty < 0)
error(gettext(
"must return a value, since LHS has a type"));
else if (tempty >= NTBASE)
tempty = nontrst[tempty-NTBASE].tvalue;
else
tempty = TYPE(toklev[tempty]);
if (tempty != nontrst[*prdptr[nprod]-NTBASE].tvalue) {
error(gettext(
"default action causes potential type clash"));
}
}
if (++nprod >= nprodsz)
exp_prod();
prdptr[nprod] = mem;
levprd[nprod] = 0;
}
end_debug();
finact();
if (t == MARK) {
if (gen_lines)
(void) fprintf(ftable, "\n# line %d \"%s\"\n",
lineno, infile);
while ((c = getwc(finput)) != EOF)
(void) putwc(c, ftable);
}
(void) fclose(finput);
}
static void
finact(void)
{
(void) fclose(faction);
(void) fprintf(ftable, "# define YYERRCODE %d\n", tokset[2].value);
}
static wchar_t *
cstash(wchar_t *s)
{
wchar_t *temp;
static int used = 0;
static int used_save = 0;
static int exp_cname = CNAMSZ;
int len = wslen(s);
used_save = used;
while (len >= (exp_cname - used_save)) {
exp_cname += CNAMSZ;
if (!used)
free((char *)cnames);
if ((cnames = (wchar_t *)
malloc(sizeof (wchar_t)*exp_cname)) == NULL)
error(gettext(
"cannot expand string dump"));
cnamp = cnames;
used = 0;
}
temp = cnamp;
do {
*cnamp++ = *s;
} while (*s++);
used += cnamp - temp;
return (temp);
}
static int
defin(int t, wchar_t *s)
{
int val = 0;
if (t) {
if (++nnonter >= nnontersz)
exp_nonterm();
nontrst[nnonter].name = cstash(s);
return (NTBASE + nnonter);
}
if (++ntokens >= ntoksz)
exp_ntok();
tokset[ntokens].name = cstash(s);
if (s[0] == L' ' && s[2] == 0) {
val = findchtok(s[1]);
} else if (s[0] == L' ' && s[1] == L'\\') {
if (s[3] == 0) {
switch (s[2]) {
case L'a':
(void) warning(1, gettext(
"\\a is ANSI C \"alert\" character"));
#if __STDC__ - 1 == 0
val = L'\a';
break;
#else
val = L'\007';
break;
#endif
case L'v': val = L'\v'; break;
case L'n': val = L'\n'; break;
case L'r': val = L'\r'; break;
case L'b': val = L'\b'; break;
case L't': val = L'\t'; break;
case L'f': val = L'\f'; break;
case L'\'': val = L'\''; break;
case L'"': val = L'"'; break;
case L'?': val = L'?'; break;
case L'\\': val = L'\\'; break;
default: error(gettext(
"invalid escape"));
}
} else if (s[2] <= L'7' && s[2] >= L'0') {
int i = 3;
val = s[2] - L'0';
while (iswdigit(s[i]) && i <= 4) {
if (s[i] >= L'0' && s[i] <= L'7')
val = val * 8 + s[i] - L'0';
else
error(gettext(
"illegal octal number"));
i++;
}
if (s[i] != 0)
error(gettext(
"illegal \\nnn construction"));
if (val > 255)
error(
"\\nnn exceed \\377; use \\xnnnnnnnn for wchar_t value of multibyte char");
if (val == 0 && i >= 4)
error(gettext(
"'\\000' is illegal"));
} else if (s[2] == L'x') {
int i = 3;
val = 0;
(void) warning(1, gettext(
"\\x is ANSI C hex escape"));
if (iswxdigit(s[i]))
while (iswxdigit(s[i])) {
int tmpval;
if (iswdigit(s[i]))
tmpval = s[i] - L'0';
else if (s[i] >= L'a')
tmpval = s[i] - L'a' + 10;
else
tmpval = s[i] - L'A' + 10;
val = 16 * val + tmpval;
i++;
}
else
error(gettext(
"illegal hexadecimal number"));
if (s[i] != 0)
error(gettext(
"illegal \\xnn construction"));
#define LWCHAR_MAX 0x7fffffff
if ((unsigned)val > LWCHAR_MAX)
error(gettext(
" \\xnnnnnnnn exceed %#x"),
LWCHAR_MAX);
if (val == 0)
error(gettext(
"'\\x00' is illegal"));
val = findchtok(val);
} else
error(gettext(
"invalid escape"));
} else {
val = extval++;
}
tokset[ntokens].value = val;
toklev[ntokens] = 0;
return (ntokens);
}
static void
defout(void)
{
register int i, c;
register wchar_t *cp;
for (i = ndefout; i <= ntokens; ++i) {
cp = tokset[i].name;
if (*cp == L' ')
{
(void) fprintf(fdebug, "\t\"%ws\",\t%d,\n",
tokset[i].name + 1, tokset[i].value);
continue;
}
for (; (c = *cp) != 0; ++cp) {
if (iswlower(c) || iswupper(c) ||
iswdigit(c) || c == L'_')
;
else
goto nodef;
}
(void) fprintf(fdebug,
"\t\"%ws\",\t%d,\n", tokset[i].name,
tokset[i].value);
(void) fprintf(ftable,
"# define %ws %d\n", tokset[i].name,
tokset[i].value);
if (fdefine != NULL)
(void) fprintf(fdefine,
"# define %ws %d\n",
tokset[i].name,
tokset[i].value);
nodef:;
}
ndefout = ntokens+1;
}
static int
gettok(void)
{
int i, base;
static int peekline;
int c, match, reserve;
begin:
reserve = 0;
lineno += peekline;
peekline = 0;
c = getwc(finput);
while (iswspace(c)) {
if (c == L'\n')
++lineno;
c = getwc(finput);
}
if (c == L'/') {
lineno += skipcom();
goto begin;
}
switch (c) {
case EOF:
return (ENDFILE);
case L'{':
(void) ungetwc(c, finput);
return (L'=');
case L'<':
i = 0;
while ((c = getwc(finput)) != L'>' &&
c != EOF && c != L'\n') {
tokname[i] = c;
if (++i >= toksize)
exp_tokname();
}
if (c != L'>')
error(gettext(
"unterminated < ... > clause"));
tokname[i] = 0;
if (i == 0)
error("missing type name in < ... > clause");
for (i = 1; i <= ntypes; ++i) {
if (!wscmp(typeset[i], tokname)) {
numbval = i;
return (TYPENAME);
}
}
typeset[numbval = ++ntypes] = cstash(tokname);
return (TYPENAME);
case L'"':
case L'\'':
match = c;
tokname[0] = L' ';
i = 1;
for (;;) {
c = getwc(finput);
if (c == L'\n' || c == EOF)
error(gettext(
"illegal or missing ' or \""));
if (c == L'\\') {
c = getwc(finput);
tokname[i] = L'\\';
if (++i >= toksize)
exp_tokname();
} else if (c == match) break;
tokname[i] = c;
if (++i >= toksize)
exp_tokname();
}
break;
case L'%':
case L'\\':
switch (c = getwc(finput)) {
case L'0': return (TERM);
case L'<': return (LEFT);
case L'2': return (BINARY);
case L'>': return (RIGHT);
case L'%':
case L'\\': return (MARK);
case L'=': return (PREC);
case L'{': return (LCURLY);
default: reserve = 1;
}
default:
if (iswdigit(c)) {
numbval = c - L'0';
base = (c == L'0') ? 8 : 10;
for (c = getwc(finput);
iswdigit(c);
c = getwc(finput)) {
numbval = numbval*base + c - L'0';
}
(void) ungetwc(c, finput);
return (NUMBER);
} else if (iswlower(c) || iswupper(c) ||
c == L'_' || c == L'.' ||
c == L'$') {
i = 0;
while (iswlower(c) || iswupper(c) ||
iswdigit(c) || c == L'_' ||
c == L'.' || c == L'$') {
tokname[i] = c;
if (reserve && iswupper(c))
tokname[i] = towlower(c);
if (++i >= toksize)
exp_tokname();
c = getwc(finput);
}
}
else
return (c);
(void) ungetwc(c, finput);
}
tokname[i] = 0;
if (reserve) {
if (!wscmp(tokname, L"term"))
return (TERM);
if (!wscmp(tokname, L"token"))
return (TERM);
if (!wscmp(tokname, L"left"))
return (LEFT);
if (!wscmp(tokname, L"nonassoc"))
return (BINARY);
if (!wscmp(tokname, L"binary"))
return (BINARY);
if (!wscmp(tokname, L"right"))
return (RIGHT);
if (!wscmp(tokname, L"prec"))
return (PREC);
if (!wscmp(tokname, L"start"))
return (START);
if (!wscmp(tokname, L"type"))
return (TYPEDEF);
if (!wscmp(tokname, L"union"))
return (UNION);
error(gettext(
"invalid escape, or illegal reserved word: %ws"),
tokname);
}
c = getwc(finput);
while (iswspace(c) || c == L'/') {
if (c == L'\n') {
++peekline;
} else if (c == L'/') {
peekline += skipcom();
}
c = getwc(finput);
}
if (c == L':')
return (C_IDENTIFIER);
(void) ungetwc(c, finput);
return (IDENTIFIER);
}
static int
fdtype(int t)
{
int v;
if (t >= NTBASE)
v = nontrst[t-NTBASE].tvalue;
else
v = TYPE(toklev[t]);
if (v <= 0)
error(gettext(
"must specify type for %ws"),
(t >= NTBASE) ? nontrst[t-NTBASE].name:
tokset[t].name);
return (v);
}
static int
chfind(int t, wchar_t *s)
{
int i;
if (s[0] == ' ')
t = 0;
TLOOP(i) {
if (!wscmp(s, tokset[i].name)) {
return (i);
}
}
NTLOOP(i) {
if (!wscmp(s, nontrst[i].name)) {
return (i + NTBASE);
}
}
if (t > 1)
error(gettext(
"%ws should have been defined earlier"), s);
return (defin(t, s));
}
static void
cpyunion(void)
{
int level, c;
if (gen_lines)
(void) fprintf(ftable, "\n# line %d \"%s\"\n", lineno, infile);
(void) fprintf(ftable, "typedef union\n");
if (fdefine)
(void) fprintf(fdefine, "\ntypedef union\n");
(void) fprintf(ftable, "#ifdef __cplusplus\n\tYYSTYPE\n#endif\n");
if (fdefine)
(void) fprintf(fdefine,
"#ifdef __cplusplus\n\tYYSTYPE\n#endif\n");
level = 0;
for (;;) {
if ((c = getwc(finput)) == EOF)
error(gettext(
"EOF encountered while processing %%union"));
(void) putwc(c, ftable);
if (fdefine)
(void) putwc(c, fdefine);
switch (c) {
case L'\n':
++lineno;
break;
case L'{':
++level;
break;
case L'}':
--level;
if (level == 0) {
(void) fprintf(ftable, " YYSTYPE;\n");
if (fdefine)
(void) fprintf(fdefine,
" YYSTYPE;\nextern YYSTYPE yylval;\n");
return;
}
}
}
}
static void
cpycode(void)
{
int c;
c = getwc(finput);
if (c == L'\n') {
c = getwc(finput);
lineno++;
}
if (gen_lines)
(void) fprintf(ftable, "\n# line %d \"%s\"\n", lineno, infile);
while (c != EOF) {
if (c == L'\\') {
if ((c = getwc(finput)) == L'}')
return;
else
(void) putwc(L'\\', ftable);
} else if (c == L'%') {
if ((c = getwc(finput)) == L'}')
return;
else
(void) putwc(L'%', ftable);
}
(void) putwc(c, ftable);
if (c == L'\n')
++lineno;
c = getwc(finput);
}
error(gettext(
"eof before %%}"));
}
static int
skipcom(void)
{
int c, i = 0;
if (getwc(finput) != L'*')
error(gettext(
"illegal comment"));
c = getwc(finput);
while (c != EOF) {
while (c == L'*') {
if ((c = getwc(finput)) == L'/')
return (i);
}
if (c == L'\n')
++i;
c = getwc(finput);
}
error(gettext(
"EOF inside comment"));
return (0);
}
static void
cpyact(int offset)
{
int brac, c, match, i, t, j, s, tok, argument, m;
wchar_t id_name[NAMESIZE+1];
int id_idx = 0;
if (gen_lines) {
(void) fprintf(faction, "\n# line %d \"%s\"\n", lineno, infile);
act_lines++;
}
brac = 0;
id_name[0] = 0;
loop:
c = getwc(finput);
swt:
switch (c) {
case L';':
if (brac == 0) {
(void) putwc(c, faction);
return;
}
goto lcopy;
case L'{':
brac++;
goto lcopy;
case L'$':
s = 1;
tok = -1;
argument = 1;
while ((c = getwc(finput)) == L' ' || c == L'\t')
;
if (c == L'<') {
(void) ungetwc(c, finput);
if (gettok() != TYPENAME)
error(gettext(
"bad syntax on $<ident> clause"));
tok = numbval;
c = getwc(finput);
}
if (c == L'$') {
(void) fprintf(faction, "yyval");
if (ntypes) {
if (tok < 0)
tok = fdtype(*prdptr[nprod]);
(void) fprintf(faction,
".%ws", typeset[tok]);
}
goto loop;
}
if (iswalpha(c)) {
int same = 0;
int id_sw = 0;
(void) ungetwc(c, finput);
if (gettok() != IDENTIFIER)
error(gettext(
"bad action format"));
id_sw = nnonter;
t = chfind(1, tokname);
if (id_sw != nnonter)
id_sw = 1;
else
id_sw = 0;
while ((c = getwc(finput)) == L' ' ||
c == L'\t')
;
if (c == L'#') {
while ((c = getwc(finput)) == L' ' ||
c == L'\t')
;
if (iswdigit(c)) {
m = 0;
while (iswdigit(c)) {
m = m*10+c-L'0';
c = getwc(finput);
}
argument = m;
} else
error(gettext(
"illegal character \"#\""));
}
if (argument < 1)
error(gettext(
"illegal action argument no."));
for (i = 1; i <= offset; ++i)
if (prdptr[nprod][i] == t)
if (++same == argument) {
(void) fprintf(faction,
"yypvt[-%d]", offset-i);
if (ntypes) {
if (tok < 0)
tok =
fdtype(prdptr[nprod][i]);
(void) fprintf(faction,
".%ws",
typeset[tok]);
}
goto swt;
}
(void) fprintf(faction, "$%ws", tokname);
warning(1, gettext(
"Illegal character '$' in Ansi C symbol: %ws$%ws."),
id_name, tokname);
if (id_sw == 1)
--nnonter;
goto swt;
}
if (c == '-') {
s = -s;
c = getwc(finput);
}
if (iswdigit(c)) {
j = 0;
while (iswdigit(c)) {
j = j*10 + c - L'0';
c = getwc(finput);
}
j = j*s - offset;
if (j > 0) {
error(gettext(
"Illegal use of $%d"),
j + offset);
}
(void) fprintf(faction, "yypvt[-%d]", -j);
if (ntypes) {
if (j + offset <= 0 && tok < 0)
error(gettext(
"must specify type of $%d"),
j + offset);
if (tok < 0)
tok = fdtype(prdptr[nprod][j+offset]);
(void) fprintf(faction,
".%ws", typeset[tok]);
}
goto swt;
}
(void) putwc(L'$', faction);
if (s < 0)
(void) putwc(L'-', faction);
goto swt;
case L'}':
if (--brac)
goto lcopy;
(void) putwc(c, faction);
return;
case L'/':
(void) putwc(c, faction);
c = getwc(finput);
if (c != L'*')
goto swt;
(void) putwc(c, faction);
c = getwc(finput);
while (c != EOF) {
while (c == L'*') {
(void) putwc(c, faction);
if ((c = getwc(finput)) == L'/')
goto lcopy;
}
(void) putwc(c, faction);
if (c == L'\n')
++lineno;
c = getwc(finput);
}
error("EOF inside comment");
case L'\'':
case L'"':
match = c;
(void) putwc(c, faction);
while ((c = getwc(finput)) != EOF) {
if (c == L'\\') {
(void) putwc(c, faction);
c = getwc(finput);
if (c == L'\n')
++lineno;
} else if (c == match)
goto lcopy;
else if (c == L'\n')
error(gettext(
"newline in string or char. const."));
(void) putwc(c, faction);
}
error(gettext(
"EOF in string or character constant"));
case EOF:
error(gettext(
"action does not terminate"));
case L'\n':
++lineno;
goto lcopy;
}
lcopy:
(void) putwc(c, faction);
if (id_idx >= NAMESIZE) {
;
}
else if (iswalnum(c) || c == L'_') {
id_name[id_idx++] = c;
id_name[id_idx] = 0;
} else {
id_idx = 0;
id_name[id_idx] = 0;
}
goto loop;
}
static void
lhsfill(wchar_t *s)
{
static int lhs_len = LHS_TEXT_LEN;
int s_lhs = wslen(s);
if (s_lhs >= lhs_len) {
lhs_len = s_lhs + 2;
lhstext = (wchar_t *)
realloc((char *)lhstext, sizeof (wchar_t)*lhs_len);
if (lhstext == NULL)
error(gettext(
"couldn't expanded LHS length"));
}
rhsfill((wchar_t *)0);
(void) wscpy(lhstext, s);
}
static void
rhsfill(wchar_t *s)
{
static wchar_t *loc;
static int rhs_len = RHS_TEXT_LEN;
static int used = 0;
int s_rhs = (s == NULL ? 0 : wslen(s));
register wchar_t *p;
if (!s)
{
if (*lhstext)
lrprnt();
(loc = rhstext)[0] = 0;
return;
}
p = s;
used = loc - rhstext;
if ((s_rhs + 3) >= (rhs_len - used)) {
static wchar_t *textbase;
textbase = rhstext;
rhs_len += s_rhs + RHS_TEXT_LEN;
rhstext = (wchar_t *)
realloc((char *)rhstext, sizeof (wchar_t)*rhs_len);
if (rhstext == NULL)
error(gettext(
"couldn't expanded RHS length"));
loc = loc - textbase + rhstext;
}
*loc++ = L' ';
if (*s == L' ')
{
*loc++ = L'\'';
p++;
}
while ((*loc = *p++))
if (loc++ > &rhstext[ RHS_TEXT_LEN ] - 3)
break;
if (*s == L' ')
*loc++ = L'\'';
*loc = 0;
}
static void
lrprnt(void)
{
wchar_t *rhs;
wchar_t *m_rhs = NULL;
if (!*rhstext)
rhs = L" /* empty */";
else {
int idx1;
int idx2;
wchar_t *p;
for (idx1 = 0; rhstext[idx1] != 0; idx1++) {
if (rhstext[idx1] == L'"') {
idx2 = wslen(rhstext)*2;
p = m_rhs = (wchar_t *)
malloc((idx2 + 1)*sizeof (wchar_t));
if (m_rhs == NULL)
error(gettext(
"Couldn't allocate memory for RHS."));
for (idx2 = 0; rhstext[idx2] != 0; idx2++) {
if (rhstext[idx2] == L'"') {
int tmp_l = idx2-1;
int cnt = 0;
while (tmp_l >= 0 &&
rhstext[tmp_l] == '\\') {
cnt++;
tmp_l--;
}
if (cnt%2 == 0)
*p++ = L'\\';
}
*p++ = rhstext[idx2];
}
*p = 0;
break;
}
}
if (m_rhs == NULL)
rhs = rhstext;
else
rhs = m_rhs;
}
(void) fprintf(fdebug, "\t\"%ws :%ws\",\n", lhstext, rhs);
if (m_rhs)
free(m_rhs);
}
static void
beg_debug(void)
{
(void) fprintf(fdebug,
"typedef struct\n");
(void) fprintf(fdebug,
"#ifdef __cplusplus\n\tyytoktype\n");
(void) fprintf(fdebug, "#endif\n{\n");
(void) fprintf(fdebug,
"#ifdef __cplusplus\nconst\n#endif\n");
(void) fprintf(fdebug, "char *t_name; int t_val; } yytoktype;\n");
(void) fprintf(fdebug,
"#ifndef YYDEBUG\n#\tdefine YYDEBUG\t%d", gen_testing);
(void) fprintf(fdebug, "\t/*%sallow debugging */\n#endif\n\n",
gen_testing ? " " : " don't ");
(void) fprintf(fdebug, "#if YYDEBUG\n\nyytoktype yytoks[] =\n{\n");
}
static void
end_toks(void)
{
(void) fprintf(fdebug, "\t\"-unknown-\",\t-1\t/* ends search */\n");
(void) fprintf(fdebug, "};\n\n");
(void) fprintf(fdebug, "const char * yyreds[] =\n{\n");
(void) fprintf(fdebug, "\t\"-no such reduction-\",\n");
}
static void
end_debug(void)
{
lrprnt();
(void) fprintf(fdebug, "};\n#endif /* YYDEBUG */\n");
(void) fclose(fdebug);
}
static void
exp_tokname(void)
{
toksize += NAMESIZE;
tokname = (wchar_t *)
realloc((char *)tokname, sizeof (wchar_t) * toksize);
}
static void
exp_prod(void)
{
int i;
nprodsz += NPROD;
prdptr = (int **) realloc((char *)prdptr, sizeof (int *) * (nprodsz+2));
levprd = (int *) realloc((char *)levprd, sizeof (int) * (nprodsz+2));
had_act = (wchar_t *)
realloc((char *)had_act, sizeof (wchar_t) * (nprodsz+2));
for (i = nprodsz-NPROD; i < nprodsz+2; ++i)
had_act[i] = 0;
if ((*prdptr == NULL) || (levprd == NULL) || (had_act == NULL))
error(gettext(
"couldn't expand productions"));
}
static void
exp_ntok(void)
{
ntoksz += NTERMS;
tokset = (TOKSYMB *) realloc((char *)tokset, sizeof (TOKSYMB) * ntoksz);
toklev = (int *) realloc((char *)toklev, sizeof (int) * ntoksz);
if ((tokset == NULL) || (toklev == NULL))
error(gettext(
"couldn't expand NTERMS"));
}
static void
exp_nonterm(void)
{
nnontersz += NNONTERM;
nontrst = (NTSYMB *)
realloc((char *)nontrst, sizeof (TOKSYMB) * nnontersz);
if (nontrst == NULL)
error(gettext(
"couldn't expand NNONTERM"));
}
void
exp_mem(int flag)
{
int i;
static int *membase;
new_memsize += MEMSIZE;
membase = tracemem;
tracemem = (int *)
realloc((char *)tracemem, sizeof (int) * new_memsize);
if (tracemem == NULL)
error(gettext(
"couldn't expand mem table"));
if (flag) {
for (i = 0; i <= nprod; ++i)
prdptr[i] = prdptr[i] - membase + tracemem;
mem = mem - membase + tracemem;
} else {
size += MEMSIZE;
temp1 = (int *)realloc((char *)temp1, sizeof (int)*size);
optimmem = optimmem - membase + tracemem;
}
}
static int
findchtok(int chlit)
{
int i;
if (chlit < 0xff)
return (chlit);
for (i = 0; i < nmbchars; ++i) {
if (mbchars->character == chlit)
return (mbchars->tvalue);
}
if (++nmbchars > nmbcharsz) {
nmbcharsz += NMBCHARSZ;
mbchars = (MBCLIT *)
realloc((char *)mbchars, sizeof (MBCLIT)*nmbcharsz);
if (mbchars == NULL)
error(gettext(
"too many character literals"));
}
mbchars[nmbchars-1].character = chlit;
return (mbchars[nmbchars-1].tvalue = extval++);
}
static void
put_prefix_define(char *pre)
{
char *syms[] = {
"parse",
"lex",
"error",
"lval",
"val",
"char",
"debug",
"errflag",
"nerrs",
NULL};
int i;
for (i = 0; syms[i]; i++)
(void) fprintf(ftable, "#define\tyy%s\t%s%s\n",
syms[i], pre, syms[i]);
}