Build lexer and parser from libCom/Makefile. Since libCom now includes asLib.c and asLib_lex.c we must build antelope and flex without linking them to Com. This works because they only need epicsTempFile anyway. However make doesn't like a subdirectory with the same name as a target object, so the antelope source directory is now called yacc. The two main.c files were also renamed to avoid other build problems. Merge asHost into Com and remove mentions in CONFIG_BASE Lots of noise since SRCS must be renamed to Com_SRCS
1248 lines
23 KiB
C
1248 lines
23 KiB
C
/*************************************************************************\
|
|
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
|
* National Laboratory.
|
|
* Copyright (c) 2002 The Regents of the University of California, as
|
|
* Operator of Los Alamos National Laboratory.
|
|
* EPICS BASE is distributed subject to a Software License Agreement found
|
|
* in file LICENSE that is included with this distribution.
|
|
\*************************************************************************/
|
|
#include "defs.h"
|
|
|
|
static int nvectors;
|
|
static int nentries;
|
|
static short **froms;
|
|
static short **tos;
|
|
static short *tally;
|
|
static short *width;
|
|
static short *state_count;
|
|
static short *order;
|
|
static short *base;
|
|
static short *pos;
|
|
static int maxtable;
|
|
static short *table;
|
|
static short *check;
|
|
static int lowzero;
|
|
static int high;
|
|
|
|
static void output_prefix(void);
|
|
static void output_rule_data(void);
|
|
static void output_yydefred(void);
|
|
static void output_actions(void);
|
|
static void token_actions(void);
|
|
static void goto_actions(void);
|
|
static void save_column(int symbol, int default_state);
|
|
static void sort_actions(void);
|
|
static void pack_table(void);
|
|
static void output_base(void);
|
|
static void output_table(void);
|
|
static void output_check(void);
|
|
static void output_defines(void);
|
|
static void output_stored_text(void);
|
|
static void output_debug(void);
|
|
static void output_stype(void);
|
|
static void output_trailing_text(void);
|
|
static void output_semantic_actions(void);
|
|
static void free_itemsets(void);
|
|
static void free_shifts(void);
|
|
static void free_reductions(void);
|
|
|
|
|
|
void
|
|
output(void)
|
|
{
|
|
free_itemsets();
|
|
free_shifts();
|
|
free_reductions();
|
|
output_prefix();
|
|
output_stored_text();
|
|
output_defines();
|
|
output_rule_data();
|
|
output_yydefred();
|
|
output_actions();
|
|
free_parser();
|
|
output_debug();
|
|
output_stype();
|
|
if (rflag) write_section(tables);
|
|
write_section(header);
|
|
output_trailing_text();
|
|
write_section(body);
|
|
output_semantic_actions();
|
|
write_section(trailer);
|
|
}
|
|
|
|
|
|
static void
|
|
output_prefix(void)
|
|
{
|
|
if (symbol_prefix == NULL)
|
|
symbol_prefix = "yy";
|
|
else
|
|
{
|
|
++outline;
|
|
fprintf(code_file, "#define yyparse %sparse\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yylex %slex\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yyerror %serror\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yychar %schar\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yyval %sval\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yylval %slval\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yydebug %sdebug\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yynerrs %snerrs\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yyerrflag %serrflag\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yyss %sss\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yyssp %sssp\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yyvs %svs\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yyvsp %svsp\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yylhs %slhs\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yylen %slen\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yydefred %sdefred\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yydgoto %sdgoto\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yysindex %ssindex\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yyrindex %srindex\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yygindex %sgindex\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yytable %stable\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yycheck %scheck\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yyname %sname\n", symbol_prefix);
|
|
++outline;
|
|
fprintf(code_file, "#define yyrule %srule\n", symbol_prefix);
|
|
}
|
|
++outline;
|
|
fprintf(code_file, "#define YYPREFIX \"%s\"\n", symbol_prefix);
|
|
}
|
|
|
|
|
|
static void
|
|
output_rule_data(void)
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
fprintf(output_file, "static short %slhs[] = {%42d,", symbol_prefix,
|
|
symbol_value[start_symbol]);
|
|
|
|
j = 10;
|
|
for (i = 3; i < nrules; i++)
|
|
{
|
|
if (j >= 10)
|
|
{
|
|
if (!rflag) ++outline;
|
|
putc('\n', output_file);
|
|
j = 1;
|
|
}
|
|
else
|
|
++j;
|
|
|
|
fprintf(output_file, "%5d,", symbol_value[rlhs[i]]);
|
|
}
|
|
if (!rflag) outline += 2;
|
|
fprintf(output_file, "\n};\n");
|
|
|
|
fprintf(output_file, "static short %slen[] = {%42d,", symbol_prefix, 2);
|
|
|
|
j = 10;
|
|
for (i = 3; i < nrules; i++)
|
|
{
|
|
if (j >= 10)
|
|
{
|
|
if (!rflag) ++outline;
|
|
putc('\n', output_file);
|
|
j = 1;
|
|
}
|
|
else
|
|
j++;
|
|
|
|
fprintf(output_file, "%5d,", rrhs[i + 1] - rrhs[i] - 1);
|
|
}
|
|
if (!rflag) outline += 2;
|
|
fprintf(output_file, "\n};\n");
|
|
}
|
|
|
|
|
|
static void
|
|
output_yydefred(void)
|
|
{
|
|
int i, j;
|
|
|
|
fprintf(output_file, "static short %sdefred[] = {%39d,", symbol_prefix,
|
|
(defred[0] ? defred[0] - 2 : 0));
|
|
|
|
j = 10;
|
|
for (i = 1; i < nstates; i++)
|
|
{
|
|
if (j < 10)
|
|
++j;
|
|
else
|
|
{
|
|
if (!rflag) ++outline;
|
|
putc('\n', output_file);
|
|
j = 1;
|
|
}
|
|
|
|
fprintf(output_file, "%5d,", (defred[i] ? defred[i] - 2 : 0));
|
|
}
|
|
|
|
if (!rflag) outline += 2;
|
|
fprintf(output_file, "\n};\n");
|
|
}
|
|
|
|
|
|
static void
|
|
output_actions(void)
|
|
{
|
|
nvectors = 2*nstates + nvars;
|
|
|
|
froms = NEW2(nvectors, short *);
|
|
tos = NEW2(nvectors, short *);
|
|
tally = NEW2(nvectors, short);
|
|
width = NEW2(nvectors, short);
|
|
|
|
token_actions();
|
|
FREE(lookaheads);
|
|
FREE(LA);
|
|
FREE(LAruleno);
|
|
FREE(accessing_symbol);
|
|
|
|
goto_actions();
|
|
FREE(goto_map + ntokens);
|
|
FREE(from_state);
|
|
FREE(to_state);
|
|
|
|
sort_actions();
|
|
pack_table();
|
|
output_base();
|
|
output_table();
|
|
output_check();
|
|
}
|
|
|
|
|
|
static void
|
|
token_actions(void)
|
|
{
|
|
int i, j;
|
|
int shiftcount, reducecount;
|
|
int max, min;
|
|
short *actionrow, *r, *s;
|
|
action *p;
|
|
|
|
actionrow = NEW2(2*ntokens, short);
|
|
for (i = 0; i < nstates; ++i)
|
|
{
|
|
if (parser[i])
|
|
{
|
|
for (j = 0; j < 2*ntokens; ++j)
|
|
actionrow[j] = 0;
|
|
|
|
shiftcount = 0;
|
|
reducecount = 0;
|
|
for (p = parser[i]; p; p = p->next)
|
|
{
|
|
if (p->suppressed == 0)
|
|
{
|
|
if (p->action_code == SHIFT)
|
|
{
|
|
++shiftcount;
|
|
actionrow[p->symbol] = p->number;
|
|
}
|
|
else if (p->action_code == REDUCE && p->number != defred[i])
|
|
{
|
|
++reducecount;
|
|
actionrow[p->symbol + ntokens] = p->number;
|
|
}
|
|
}
|
|
}
|
|
|
|
tally[i] = shiftcount;
|
|
tally[nstates+i] = reducecount;
|
|
width[i] = 0;
|
|
width[nstates+i] = 0;
|
|
if (shiftcount > 0)
|
|
{
|
|
froms[i] = r = NEW2(shiftcount, short);
|
|
tos[i] = s = NEW2(shiftcount, short);
|
|
min = MAXSHORT;
|
|
max = 0;
|
|
for (j = 0; j < ntokens; ++j)
|
|
{
|
|
if (actionrow[j])
|
|
{
|
|
if (min > symbol_value[j])
|
|
min = symbol_value[j];
|
|
if (max < symbol_value[j])
|
|
max = symbol_value[j];
|
|
*r++ = symbol_value[j];
|
|
*s++ = actionrow[j];
|
|
}
|
|
}
|
|
width[i] = max - min + 1;
|
|
}
|
|
if (reducecount > 0)
|
|
{
|
|
froms[nstates+i] = r = NEW2(reducecount, short);
|
|
tos[nstates+i] = s = NEW2(reducecount, short);
|
|
min = MAXSHORT;
|
|
max = 0;
|
|
for (j = 0; j < ntokens; ++j)
|
|
{
|
|
if (actionrow[ntokens+j])
|
|
{
|
|
if (min > symbol_value[j])
|
|
min = symbol_value[j];
|
|
if (max < symbol_value[j])
|
|
max = symbol_value[j];
|
|
*r++ = symbol_value[j];
|
|
*s++ = actionrow[ntokens+j] - 2;
|
|
}
|
|
}
|
|
width[nstates+i] = max - min + 1;
|
|
}
|
|
}
|
|
}
|
|
FREE(actionrow);
|
|
}
|
|
|
|
static void
|
|
goto_actions(void)
|
|
{
|
|
int i, j, k;
|
|
|
|
state_count = NEW2(nstates, short);
|
|
|
|
k = default_goto(start_symbol + 1);
|
|
fprintf(output_file, "static short %sdgoto[] = {%40d,", symbol_prefix, k);
|
|
save_column(start_symbol + 1, k);
|
|
|
|
j = 10;
|
|
for (i = start_symbol + 2; i < nsyms; i++)
|
|
{
|
|
if (j >= 10)
|
|
{
|
|
if (!rflag) ++outline;
|
|
putc('\n', output_file);
|
|
j = 1;
|
|
}
|
|
else
|
|
++j;
|
|
|
|
k = default_goto(i);
|
|
fprintf(output_file, "%5d,", k);
|
|
save_column(i, k);
|
|
}
|
|
|
|
if (!rflag) outline += 2;
|
|
fprintf(output_file, "\n};\n");
|
|
FREE(state_count);
|
|
}
|
|
|
|
int
|
|
default_goto(int symbol)
|
|
{
|
|
int i;
|
|
int m;
|
|
int n;
|
|
int default_state;
|
|
int max;
|
|
|
|
m = goto_map[symbol];
|
|
n = goto_map[symbol + 1];
|
|
|
|
if (m == n) return (0);
|
|
|
|
for (i = 0; i < nstates; i++)
|
|
state_count[i] = 0;
|
|
|
|
for (i = m; i < n; i++)
|
|
state_count[to_state[i]]++;
|
|
|
|
max = 0;
|
|
default_state = 0;
|
|
for (i = 0; i < nstates; i++)
|
|
{
|
|
if (state_count[i] > max)
|
|
{
|
|
max = state_count[i];
|
|
default_state = i;
|
|
}
|
|
}
|
|
|
|
return (default_state);
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
save_column(int symbol, int default_state)
|
|
{
|
|
int i;
|
|
int m;
|
|
int n;
|
|
short *sp;
|
|
short *sp1;
|
|
short *sp2;
|
|
int count;
|
|
int symno;
|
|
|
|
m = goto_map[symbol];
|
|
n = goto_map[symbol + 1];
|
|
|
|
count = 0;
|
|
for (i = m; i < n; i++)
|
|
{
|
|
if (to_state[i] != default_state)
|
|
++count;
|
|
}
|
|
if (count == 0) return;
|
|
|
|
symno = symbol_value[symbol] + 2*nstates;
|
|
|
|
froms[symno] = sp1 = sp = NEW2(count, short);
|
|
tos[symno] = sp2 = NEW2(count, short);
|
|
|
|
for (i = m; i < n; i++)
|
|
{
|
|
if (to_state[i] != default_state)
|
|
{
|
|
*sp1++ = from_state[i];
|
|
*sp2++ = to_state[i];
|
|
}
|
|
}
|
|
|
|
tally[symno] = count;
|
|
width[symno] = sp1[-1] - sp[0] + 1;
|
|
}
|
|
|
|
static void
|
|
sort_actions(void)
|
|
{
|
|
int i;
|
|
int j;
|
|
int k;
|
|
int t;
|
|
int w;
|
|
|
|
order = NEW2(nvectors, short);
|
|
nentries = 0;
|
|
|
|
for (i = 0; i < nvectors; i++)
|
|
{
|
|
if (tally[i] > 0)
|
|
{
|
|
t = tally[i];
|
|
w = width[i];
|
|
j = nentries - 1;
|
|
|
|
while (j >= 0 && (width[order[j]] < w))
|
|
j--;
|
|
|
|
while (j >= 0 && (width[order[j]] == w) && (tally[order[j]] < t))
|
|
j--;
|
|
|
|
for (k = nentries - 1; k > j; k--)
|
|
order[k + 1] = order[k];
|
|
|
|
order[j + 1] = i;
|
|
nentries++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
pack_table(void)
|
|
{
|
|
int i;
|
|
int place;
|
|
int state;
|
|
|
|
base = NEW2(nvectors, short);
|
|
pos = NEW2(nentries, short);
|
|
|
|
maxtable = 1000;
|
|
table = NEW2(maxtable, short);
|
|
check = NEW2(maxtable, short);
|
|
|
|
lowzero = 0;
|
|
high = 0;
|
|
|
|
for (i = 0; i < maxtable; i++)
|
|
check[i] = -1;
|
|
|
|
for (i = 0; i < nentries; i++)
|
|
{
|
|
state = matching_vector(i);
|
|
|
|
if (state < 0)
|
|
place = pack_vector(i);
|
|
else
|
|
place = base[state];
|
|
|
|
pos[i] = place;
|
|
base[order[i]] = place;
|
|
}
|
|
|
|
for (i = 0; i < nvectors; i++)
|
|
{
|
|
if (froms[i])
|
|
FREE(froms[i]);
|
|
if (tos[i])
|
|
FREE(tos[i]);
|
|
}
|
|
|
|
FREE(froms);
|
|
FREE(tos);
|
|
FREE(pos);
|
|
}
|
|
|
|
|
|
/* The function matching_vector determines if the vector specified by */
|
|
/* the input parameter matches a previously considered vector. The */
|
|
/* test at the start of the function checks if the vector represents */
|
|
/* a row of shifts over terminal symbols or a row of reductions, or a */
|
|
/* column of shifts over a nonterminal symbol. Berkeley Yacc does not */
|
|
/* check if a column of shifts over a nonterminal symbols matches a */
|
|
/* previously considered vector. Because of the nature of LR parsing */
|
|
/* tables, no two columns can match. Therefore, the only possible */
|
|
/* match would be between a row and a column. Such matches are */
|
|
/* unlikely. Therefore, to save time, no attempt is made to see if a */
|
|
/* column matches a previously considered vector. */
|
|
/* */
|
|
/* Matching_vector is poorly designed. The test could easily be made */
|
|
/* faster. Also, it depends on the vectors being in a specific */
|
|
/* order. */
|
|
|
|
int
|
|
matching_vector(int vector)
|
|
{
|
|
int i;
|
|
int j;
|
|
int k;
|
|
int t;
|
|
int w;
|
|
int match;
|
|
int prev;
|
|
|
|
i = order[vector];
|
|
if (i >= 2*nstates)
|
|
return (-1);
|
|
|
|
t = tally[i];
|
|
w = width[i];
|
|
|
|
for (prev = vector - 1; prev >= 0; prev--)
|
|
{
|
|
j = order[prev];
|
|
if (width[j] != w || tally[j] != t)
|
|
return (-1);
|
|
|
|
match = 1;
|
|
for (k = 0; match && k < t; k++)
|
|
{
|
|
if (tos[j][k] != tos[i][k] || froms[j][k] != froms[i][k])
|
|
match = 0;
|
|
}
|
|
|
|
if (match)
|
|
return (j);
|
|
}
|
|
|
|
return (-1);
|
|
}
|
|
|
|
|
|
|
|
int
|
|
pack_vector(int vector)
|
|
{
|
|
int i, j, k, l;
|
|
int t;
|
|
int loc;
|
|
int ok;
|
|
short *from;
|
|
short *to;
|
|
int newmax;
|
|
|
|
i = order[vector];
|
|
t = tally[i];
|
|
assert(t);
|
|
|
|
from = froms[i];
|
|
to = tos[i];
|
|
|
|
j = lowzero - from[0];
|
|
for (k = 1; k < t; ++k)
|
|
if (lowzero - from[k] > j)
|
|
j = lowzero - from[k];
|
|
for (;; ++j)
|
|
{
|
|
if (j == 0)
|
|
continue;
|
|
ok = 1;
|
|
for (k = 0; ok && k < t; k++)
|
|
{
|
|
loc = j + from[k];
|
|
if (loc >= maxtable)
|
|
{
|
|
if (loc >= MAXTABLE)
|
|
fatal("maximum table size exceeded");
|
|
|
|
newmax = maxtable;
|
|
do { newmax += 200; } while (newmax <= loc);
|
|
table = (short *) REALLOC(table, newmax*sizeof(short));
|
|
if (table == 0) no_space();
|
|
check = (short *) REALLOC(check, newmax*sizeof(short));
|
|
if (check == 0) no_space();
|
|
for (l = maxtable; l < newmax; ++l)
|
|
{
|
|
table[l] = 0;
|
|
check[l] = -1;
|
|
}
|
|
maxtable = newmax;
|
|
}
|
|
|
|
if (check[loc] != -1)
|
|
ok = 0;
|
|
}
|
|
for (k = 0; ok && k < vector; k++)
|
|
{
|
|
if (pos[k] == j)
|
|
ok = 0;
|
|
}
|
|
if (ok)
|
|
{
|
|
for (k = 0; k < t; k++)
|
|
{
|
|
loc = j + from[k];
|
|
table[loc] = to[k];
|
|
check[loc] = from[k];
|
|
if (loc > high) high = loc;
|
|
}
|
|
|
|
while (check[lowzero] != -1)
|
|
++lowzero;
|
|
|
|
return (j);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
output_base(void)
|
|
{
|
|
int i, j;
|
|
|
|
fprintf(output_file, "static short %ssindex[] = {%39d,", symbol_prefix, base[0]);
|
|
|
|
j = 10;
|
|
for (i = 1; i < nstates; i++)
|
|
{
|
|
if (j >= 10)
|
|
{
|
|
if (!rflag) ++outline;
|
|
putc('\n', output_file);
|
|
j = 1;
|
|
}
|
|
else
|
|
++j;
|
|
|
|
fprintf(output_file, "%5d,", base[i]);
|
|
}
|
|
|
|
if (!rflag) outline += 2;
|
|
fprintf(output_file, "\n};\nstatic short %srindex[] = {%39d,", symbol_prefix,
|
|
base[nstates]);
|
|
|
|
j = 10;
|
|
for (i = nstates + 1; i < 2*nstates; i++)
|
|
{
|
|
if (j >= 10)
|
|
{
|
|
if (!rflag) ++outline;
|
|
putc('\n', output_file);
|
|
j = 1;
|
|
}
|
|
else
|
|
++j;
|
|
|
|
fprintf(output_file, "%5d,", base[i]);
|
|
}
|
|
|
|
if (!rflag) outline += 2;
|
|
fprintf(output_file, "\n};\nstatic short %sgindex[] = {%39d,", symbol_prefix,
|
|
base[2*nstates]);
|
|
|
|
j = 10;
|
|
for (i = 2*nstates + 1; i < nvectors - 1; i++)
|
|
{
|
|
if (j >= 10)
|
|
{
|
|
if (!rflag) ++outline;
|
|
putc('\n', output_file);
|
|
j = 1;
|
|
}
|
|
else
|
|
++j;
|
|
|
|
fprintf(output_file, "%5d,", base[i]);
|
|
}
|
|
|
|
if (!rflag) outline += 2;
|
|
fprintf(output_file, "\n};\n");
|
|
FREE(base);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
output_table(void)
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
++outline;
|
|
fprintf(code_file, "#define YYTABLESIZE %d\n", high);
|
|
fprintf(output_file, "static short %stable[] = {%40d,", symbol_prefix,
|
|
table[0]);
|
|
|
|
j = 10;
|
|
for (i = 1; i <= high; i++)
|
|
{
|
|
if (j >= 10)
|
|
{
|
|
if (!rflag) ++outline;
|
|
putc('\n', output_file);
|
|
j = 1;
|
|
}
|
|
else
|
|
++j;
|
|
|
|
fprintf(output_file, "%5d,", table[i]);
|
|
}
|
|
|
|
if (!rflag) outline += 2;
|
|
fprintf(output_file, "\n};\n");
|
|
FREE(table);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
output_check(void)
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
fprintf(output_file, "static short %scheck[] = {%40d,", symbol_prefix,
|
|
check[0]);
|
|
|
|
j = 10;
|
|
for (i = 1; i <= high; i++)
|
|
{
|
|
if (j >= 10)
|
|
{
|
|
if (!rflag) ++outline;
|
|
putc('\n', output_file);
|
|
j = 1;
|
|
}
|
|
else
|
|
++j;
|
|
|
|
fprintf(output_file, "%5d,", check[i]);
|
|
}
|
|
|
|
if (!rflag) outline += 2;
|
|
fprintf(output_file, "\n};\n");
|
|
FREE(check);
|
|
}
|
|
|
|
|
|
static int
|
|
is_C_identifier(char *name)
|
|
{
|
|
char *s;
|
|
int c;
|
|
|
|
s = name;
|
|
c = *s;
|
|
if (c == '"')
|
|
{
|
|
c = *++s;
|
|
if (!isalpha(c) && c != '_' && c != '$')
|
|
return (0);
|
|
while ((c = *++s) != '"')
|
|
{
|
|
if (!isalnum(c) && c != '_' && c != '$')
|
|
return (0);
|
|
}
|
|
return (1);
|
|
}
|
|
|
|
if (!isalpha(c) && c != '_' && c != '$')
|
|
return (0);
|
|
while ((c = *++s))
|
|
{
|
|
if (!isalnum(c) && c != '_' && c != '$')
|
|
return (0);
|
|
}
|
|
return (1);
|
|
}
|
|
|
|
|
|
static void
|
|
output_defines(void)
|
|
{
|
|
int c, i;
|
|
char *s;
|
|
|
|
for (i = 2; i < ntokens; ++i)
|
|
{
|
|
s = symbol_name[i];
|
|
if (is_C_identifier(s))
|
|
{
|
|
fprintf(code_file, "#define ");
|
|
if (dflag) fprintf(defines_file, "#define ");
|
|
c = *s;
|
|
if (c == '"')
|
|
{
|
|
while ((c = *++s) != '"')
|
|
{
|
|
putc(c, code_file);
|
|
if (dflag) putc(c, defines_file);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
putc(c, code_file);
|
|
if (dflag) putc(c, defines_file);
|
|
}
|
|
while ((c = *++s));
|
|
}
|
|
++outline;
|
|
fprintf(code_file, " %d\n", symbol_value[i]);
|
|
if (dflag) fprintf(defines_file, " %d\n", symbol_value[i]);
|
|
}
|
|
}
|
|
|
|
++outline;
|
|
fprintf(code_file, "#define YYERRCODE %d\n", symbol_value[1]);
|
|
|
|
if (dflag && unionized)
|
|
{
|
|
rewind(union_file);
|
|
while ((c = getc(union_file)) != EOF)
|
|
putc(c, defines_file);
|
|
fprintf(defines_file, " YYSTYPE;\nstatic YYSTYPE %slval;\n",
|
|
symbol_prefix);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
output_stored_text(void)
|
|
{
|
|
int c;
|
|
FILE *in, *out;
|
|
|
|
rewind(text_file);
|
|
in = text_file;
|
|
if ((c = getc(in)) == EOF)
|
|
return;
|
|
out = code_file;
|
|
if (c == '\n')
|
|
++outline;
|
|
putc(c, out);
|
|
while ((c = getc(in)) != EOF)
|
|
{
|
|
if (c == '\n')
|
|
++outline;
|
|
putc(c, out);
|
|
}
|
|
if (!lflag)
|
|
fprintf(out, line_format, ++outline + 1, code_file_name);
|
|
}
|
|
|
|
|
|
static void
|
|
output_debug(void)
|
|
{
|
|
int i, j, k, max;
|
|
char **symnam, *s;
|
|
|
|
++outline;
|
|
fprintf(code_file, "#define YYFINAL %d\n", final_state);
|
|
outline += 3;
|
|
fprintf(code_file, "#ifndef YYDEBUG\n#define YYDEBUG %d\n#endif\n",
|
|
tflag);
|
|
if (rflag)
|
|
fprintf(output_file, "#ifndef YYDEBUG\n#define YYDEBUG %d\n#endif\n",
|
|
tflag);
|
|
|
|
max = 0;
|
|
for (i = 2; i < ntokens; ++i)
|
|
if (symbol_value[i] > max)
|
|
max = symbol_value[i];
|
|
++outline;
|
|
fprintf(code_file, "#define YYMAXTOKEN %d\n", max);
|
|
|
|
symnam = (char **) MALLOC((max+1)*sizeof(char *));
|
|
if (symnam == 0) no_space();
|
|
|
|
/* Note that it is not necessary to initialize the element */
|
|
/* symnam[max]. */
|
|
for (i = 0; i < max; ++i)
|
|
symnam[i] = 0;
|
|
for (i = ntokens - 1; i >= 2; --i)
|
|
symnam[symbol_value[i]] = symbol_name[i];
|
|
symnam[0] = "end-of-file";
|
|
|
|
if (!rflag) ++outline;
|
|
fprintf(output_file, "#if YYDEBUG\nstatic char *%sname[] = {", symbol_prefix);
|
|
j = 80;
|
|
for (i = 0; i <= max; ++i)
|
|
{
|
|
if ((s = symnam[i]))
|
|
{
|
|
if (s[0] == '"')
|
|
{
|
|
k = 7;
|
|
while (*++s != '"')
|
|
{
|
|
++k;
|
|
if (*s == '\\')
|
|
{
|
|
k += 2;
|
|
if (*++s == '\\')
|
|
++k;
|
|
}
|
|
}
|
|
j += k;
|
|
if (j > 80)
|
|
{
|
|
if (!rflag) ++outline;
|
|
putc('\n', output_file);
|
|
j = k;
|
|
}
|
|
fprintf(output_file, "\"\\\"");
|
|
s = symnam[i];
|
|
while (*++s != '"')
|
|
{
|
|
if (*s == '\\')
|
|
{
|
|
fprintf(output_file, "\\\\");
|
|
if (*++s == '\\')
|
|
fprintf(output_file, "\\\\");
|
|
else
|
|
putc(*s, output_file);
|
|
}
|
|
else
|
|
putc(*s, output_file);
|
|
}
|
|
fprintf(output_file, "\\\"\",");
|
|
}
|
|
else if (s[0] == '\'')
|
|
{
|
|
if (s[1] == '"')
|
|
{
|
|
j += 7;
|
|
if (j > 80)
|
|
{
|
|
if (!rflag) ++outline;
|
|
putc('\n', output_file);
|
|
j = 7;
|
|
}
|
|
fprintf(output_file, "\"'\\\"'\",");
|
|
}
|
|
else
|
|
{
|
|
k = 5;
|
|
while (*++s != '\'')
|
|
{
|
|
++k;
|
|
if (*s == '\\')
|
|
{
|
|
k += 2;
|
|
if (*++s == '\\')
|
|
++k;
|
|
}
|
|
}
|
|
j += k;
|
|
if (j > 80)
|
|
{
|
|
if (!rflag) ++outline;
|
|
putc('\n', output_file);
|
|
j = k;
|
|
}
|
|
fprintf(output_file, "\"'");
|
|
s = symnam[i];
|
|
while (*++s != '\'')
|
|
{
|
|
if (*s == '\\')
|
|
{
|
|
fprintf(output_file, "\\\\");
|
|
if (*++s == '\\')
|
|
fprintf(output_file, "\\\\");
|
|
else
|
|
putc(*s, output_file);
|
|
}
|
|
else
|
|
putc(*s, output_file);
|
|
}
|
|
fprintf(output_file, "'\",");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
k = strlen(s) + 3;
|
|
j += k;
|
|
if (j > 80)
|
|
{
|
|
if (!rflag) ++outline;
|
|
putc('\n', output_file);
|
|
j = k;
|
|
}
|
|
putc('"', output_file);
|
|
do { putc(*s, output_file); } while (*++s);
|
|
fprintf(output_file, "\",");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
j += 2;
|
|
if (j > 80)
|
|
{
|
|
if (!rflag) ++outline;
|
|
putc('\n', output_file);
|
|
j = 2;
|
|
}
|
|
fprintf(output_file, "0,");
|
|
}
|
|
}
|
|
if (!rflag) outline += 2;
|
|
fprintf(output_file, "\n};\n");
|
|
FREE(symnam);
|
|
|
|
if (!rflag) ++outline;
|
|
fprintf(output_file, "static char *%srule[] = {\n", symbol_prefix);
|
|
for (i = 2; i < nrules; ++i)
|
|
{
|
|
fprintf(output_file, "\"%s :", symbol_name[rlhs[i]]);
|
|
for (j = rrhs[i]; ritem[j] > 0; ++j)
|
|
{
|
|
s = symbol_name[ritem[j]];
|
|
if (s[0] == '"')
|
|
{
|
|
fprintf(output_file, " \\\"");
|
|
while (*++s != '"')
|
|
{
|
|
if (*s == '\\')
|
|
{
|
|
if (s[1] == '\\')
|
|
fprintf(output_file, "\\\\\\\\");
|
|
else
|
|
fprintf(output_file, "\\\\%c", s[1]);
|
|
++s;
|
|
}
|
|
else
|
|
putc(*s, output_file);
|
|
}
|
|
fprintf(output_file, "\\\"");
|
|
}
|
|
else if (s[0] == '\'')
|
|
{
|
|
if (s[1] == '"')
|
|
fprintf(output_file, " '\\\"'");
|
|
else if (s[1] == '\\')
|
|
{
|
|
if (s[2] == '\\')
|
|
fprintf(output_file, " '\\\\\\\\");
|
|
else
|
|
fprintf(output_file, " '\\\\%c", s[2]);
|
|
s += 2;
|
|
while (*++s != '\'')
|
|
putc(*s, output_file);
|
|
putc('\'', output_file);
|
|
}
|
|
else
|
|
fprintf(output_file, " '%c'", s[1]);
|
|
}
|
|
else
|
|
fprintf(output_file, " %s", s);
|
|
}
|
|
if (!rflag) ++outline;
|
|
fprintf(output_file, "\",\n");
|
|
}
|
|
|
|
if (!rflag) outline += 2;
|
|
fprintf(output_file, "};\n#endif\n");
|
|
}
|
|
|
|
|
|
static void
|
|
output_stype(void)
|
|
{
|
|
if (!unionized && ntags == 0)
|
|
{
|
|
outline += 3;
|
|
fprintf(code_file, "#ifndef YYSTYPE\ntypedef int YYSTYPE;\n#endif\n");
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
output_trailing_text(void)
|
|
{
|
|
int c, last;
|
|
FILE *in, *out;
|
|
|
|
if (line == 0)
|
|
return;
|
|
|
|
in = input_file;
|
|
out = code_file;
|
|
c = *cptr;
|
|
if (c == '\n')
|
|
{
|
|
++lineno;
|
|
if ((c = getc(in)) == EOF)
|
|
return;
|
|
if (!lflag)
|
|
{
|
|
++outline;
|
|
fprintf(out, line_format, lineno, input_file_name);
|
|
}
|
|
if (c == '\n')
|
|
++outline;
|
|
putc(c, out);
|
|
last = c;
|
|
}
|
|
else
|
|
{
|
|
if (!lflag)
|
|
{
|
|
++outline;
|
|
fprintf(out, line_format, lineno, input_file_name);
|
|
}
|
|
do { putc(c, out); } while ((c = *++cptr) != '\n');
|
|
++outline;
|
|
putc('\n', out);
|
|
last = '\n';
|
|
}
|
|
|
|
while ((c = getc(in)) != EOF)
|
|
{
|
|
if (c == '\n')
|
|
++outline;
|
|
putc(c, out);
|
|
last = c;
|
|
}
|
|
|
|
if (last != '\n')
|
|
{
|
|
++outline;
|
|
putc('\n', out);
|
|
}
|
|
if (!lflag)
|
|
fprintf(out, line_format, ++outline + 1, code_file_name);
|
|
}
|
|
|
|
|
|
static void
|
|
output_semantic_actions(void)
|
|
{
|
|
int c, last;
|
|
FILE *out;
|
|
|
|
rewind(action_file);
|
|
|
|
if ((c = getc(action_file)) == EOF)
|
|
return;
|
|
|
|
out = code_file;
|
|
last = c;
|
|
if (c == '\n')
|
|
++outline;
|
|
putc(c, out);
|
|
while ((c = getc(action_file)) != EOF)
|
|
{
|
|
if (c == '\n')
|
|
++outline;
|
|
putc(c, out);
|
|
last = c;
|
|
}
|
|
|
|
if (last != '\n')
|
|
{
|
|
++outline;
|
|
putc('\n', out);
|
|
}
|
|
|
|
if (!lflag)
|
|
fprintf(out, line_format, ++outline + 1, code_file_name);
|
|
}
|
|
|
|
|
|
static void
|
|
free_itemsets(void)
|
|
{
|
|
core *cp, *next;
|
|
|
|
FREE(state_table);
|
|
for (cp = first_state; cp; cp = next)
|
|
{
|
|
next = cp->next;
|
|
FREE(cp);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
free_shifts(void)
|
|
{
|
|
shifts *sp, *next;
|
|
|
|
FREE(shift_table);
|
|
for (sp = first_shift; sp; sp = next)
|
|
{
|
|
next = sp->next;
|
|
FREE(sp);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
free_reductions(void)
|
|
{
|
|
reductions *rp, *next;
|
|
|
|
FREE(reduction_table);
|
|
for (rp = first_reduction; rp; rp = next)
|
|
{
|
|
next = rp->next;
|
|
FREE(rp);
|
|
}
|
|
}
|