#include "dextern.h"
#define NOMORE -1000
static void gin(int);
static void stin(int);
static void osummary(void);
static void aoutput(void);
static void arout(wchar_t *, int *, int);
static int nxti(void);
static int gtnm(void);
static int *ggreed;
static int *pgo;
static int *yypgo;
static int maxspr = 0;
static int maxoff = 0;
int *optimmem;
static int *maxa;
static int nxdb = 0;
static int adb = 0;
void
callopt(void)
{
int i, *p, j, k, *q;
ggreed = (int *) malloc(sizeof (int) * size);
pgo = (int *) malloc(sizeof (int) * size);
yypgo = &nontrst[0].tvalue;
if ((finput = fopen(TEMPNAME, "r")) == NULL)
error(gettext(
"optimizer cannot open tempfile"));
optimmem = tracemem;
pgo[0] = 0;
temp1[0] = 0;
nstate = 0;
nnonter = 0;
for (;;) {
switch (gtnm()) {
case L'\n':
temp1[++nstate] = (--optimmem) - tracemem;
case L',':
continue;
case L'$':
break;
default:
error("bad tempfile");
}
break;
}
temp1[nstate] = yypgo[0] = (--optimmem) - tracemem;
for (;;) {
switch (gtnm()) {
case L'\n':
yypgo[++nnonter] = optimmem-tracemem;
case L',':
continue;
case EOF:
break;
default:
error(gettext(
"bad tempfile"));
}
break;
}
yypgo[nnonter--] = (--optimmem) - tracemem;
for (i = 0; i < nstate; ++i) {
k = 32000000;
j = 0;
q = tracemem + temp1[i+1];
for (p = tracemem + temp1[i]; p < q; p += 2) {
if (*p > j)
j = *p;
if (*p < k)
k = *p;
}
if (k <= j) {
if (k > maxoff)
maxoff = k;
}
tystate[i] = (temp1[i+1] - temp1[i]) + 2*j;
if (j > maxspr)
maxspr = j;
}
for (i = 1; i <= nnonter; ++i) {
ggreed[i] = 1;
j = 0;
q = tracemem + yypgo[i+1] -1;
for (p = tracemem + 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;
}
for (i = 0; i < new_actsize; ++i)
amem[i] = 0;
maxa = amem;
for (i = 0; i < nstate; ++i) {
if (tystate[i] == 0 && adb > 1)
(void) fprintf(ftable, "State %d: null\n", i);
indgo[i] = YYFLAG1;
}
while ((i = nxti()) != NOMORE) {
if (i >= 0)
stin(i);
else
gin(-i);
}
if (adb > 2) {
for (p = amem; p <= maxa; p += 10) {
(void) fprintf(ftable, "%4" PRIdPTR " ", p-amem);
for (i = 0; i < 10; ++i)
(void) fprintf(ftable, "%4d ", p[i]);
(void) fprintf(ftable, "\n");
}
}
aoutput();
osummary();
ZAPFILE(TEMPNAME);
}
static void
gin(int i)
{
int *r, *s, *q1, *q2;
int *p;
ggreed[i] = 0;
q2 = tracemem + yypgo[i+1] - 1;
q1 = tracemem + yypgo[i];
p = amem;
for (;;) {
while (p >= &amem[new_actsize])
exp_act(&p);
if (*p)
goto nextgp;
for (r = q1; r < q2; r += 2) {
s = p + *r + 1;
while (s >= &amem[new_actsize]) {
exp_act(&p);
s = p + *r + 1;
}
if (*s)
goto nextgp;
if (s > maxa) {
while ((maxa = s) >= &amem[new_actsize])
exp_act(&p);
}
}
*p = *q2;
if (p > maxa) {
while ((maxa = p) >= &amem[new_actsize])
exp_act(&p);
}
for (r = q1; r < q2; r += 2) {
s = p + *r + 1;
while (s >= &amem[new_actsize]) {
exp_act(&p);
s = p + *r + 1;
}
*s = r[1];
}
pgo[i] = p - amem;
if (adb > 1)
(void) fprintf(ftable,
"Nonterminal %d, entry at %d\n", i, pgo[i]);
goto nextgi;
nextgp:
++p;
}
nextgi:;
}
static void
stin(int i)
{
int *r, n, nn, flag, j, *q1, *q2;
int *s;
tystate[i] = 0;
q2 = tracemem + temp1[i + 1];
q1 = tracemem + temp1[i];
nn = -maxoff;
more:
for (n = nn; n < new_actsize; ++n) {
flag = 0;
for (r = q1; r < q2; r += 2) {
s = *r + n + amem;
if (s < amem)
goto nextn;
while (s >= &amem[new_actsize]) {
exp_act((int **)NULL);
s = *r + n + amem;
}
if (*s == 0)
++flag;
else if (*s != r[1])
goto nextn;
}
for (j = 0; j < nstate; ++j) {
if (indgo[j] == n) {
if (flag)
goto nextn;
if (temp1[j+1] + temp1[i] ==
temp1[j] + temp1[i+1]) {
indgo[i] = n;
if (adb > 1)
(void) fprintf(ftable,
"State %d: entry at"
" %d equals state %d\n",
i, n, j);
return;
}
goto nextn;
}
}
for (r = q1; r < q2; r += 2) {
while ((s = *r + n + amem) >= &amem[new_actsize]) {
exp_act((int **)NULL);
}
if (s > maxa)
maxa = s;
if (*s != 0 && *s != r[1])
error(gettext(
"clobber of amem array, pos'n %d, by %d"),
s-amem, r[1]);
*s = r[1];
}
indgo[i] = n;
if (adb > 1)
(void) fprintf(ftable,
"State %d: entry at %d\n", i, indgo[i]);
return;
nextn:;
}
exp_act((int **)NULL);
nn = new_actsize - ACTSIZE;
goto more;
}
static int
nxti(void)
{
int 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 (tystate[i] >= max) {
max = tystate[i];
maxi = i;
}
if (nxdb)
(void) fprintf(ftable, "nxti = %d, max = %d\n", maxi, max);
if (max == 0)
return (NOMORE);
else
return (maxi);
}
static void
osummary(void)
{
int i, *p;
if (foutput == NULL)
return;
i = 0;
for (p = maxa; p >= amem; --p) {
if (*p == 0)
++i;
}
(void) fprintf(foutput,
"Optimizer space used: input %" PRIdPTR
"/%d, output %" PRIdPTR "/%d\n",
optimmem-tracemem + 1, new_memsize, maxa-amem + 1, new_actsize);
(void) fprintf(foutput,
"%" PRIdPTR " table entries, %d zero\n", (maxa-amem) + 1, i);
(void) fprintf(foutput,
"maximum spread: %d, maximum offset: %d\n", maxspr, maxoff);
}
static void
aoutput(void)
{
(void) fprintf(ftable, "# define YYLAST %" PRIdPTR "\n", maxa-amem + 1);
arout(L"yyact", amem, (maxa - amem) + 1);
arout(L"yypact", indgo, nstate);
arout(L"yypgo", pgo, nnonter + 1);
}
static void
arout(wchar_t *s, int *v, int n)
{
int i;
(void) fprintf(ftable, "static const yytabelem %ws[]={\n", s);
for (i = 0; i < n; ) {
if (i % 10 == 0)
(void) fprintf(ftable, "\n");
(void) fprintf(ftable, "%6d", v[i]);
if (++i == n)
(void) fprintf(ftable, " };\n");
else
(void) fprintf(ftable, ",");
}
}
static int
gtnm(void)
{
int s, val, c;
s = 1;
val = 0;
while ((c = getwc(finput)) != EOF) {
if (iswdigit(c))
val = val * 10 + c - L'0';
else if (c == L'-')
s = -1;
else
break;
}
*optimmem++ = s*val;
if (optimmem >= &tracemem[new_memsize])
exp_mem(0);
return (c);
}
void
exp_act(int **ptr)
{
static int *actbase;
int i;
new_actsize += ACTSIZE;
actbase = amem;
amem = (int *) realloc((char *)amem, sizeof (int) * new_actsize);
if (amem == NULL)
error(gettext(
"couldn't expand action table"));
for (i = new_actsize-ACTSIZE; i < new_actsize; ++i)
amem[i] = 0;
if (ptr != NULL)
*ptr = *ptr - actbase + amem;
if (memp >= amem)
memp = memp - actbase + amem;
if (maxa >= amem)
maxa = maxa - actbase + amem;
}