#include "dextern.h"
#include <sys/param.h>
#include <sys/errno.h>
#include <unistd.h>
#include <locale.h>
#include <stdarg.h>
static void mktbls(void);
static void others(void);
static void summary(void);
static wchar_t *chcopy(wchar_t *, wchar_t *);
static int setunion(int *, int *);
static void prlook(LOOKSETS *);
static void cpres(void);
static void cpfir(void);
static void cempty(void);
static void stagen(void);
static LOOKSETS *flset(LOOKSETS *);
static void exp_lkst(void);
static void exp_wsets(void);
static void exp_states(void);
static void exp_psmem(void);
int TBITSET;
static int tbitset;
LOOKSETS *lkst;
static int lsetsize;
static int nlset = 0;
int nolook = 0;
static LOOKSETS clset;
static ITEM *psmem, *zzmemsz;
static int new_pstsize = PSTSIZE;
WSET *wsets;
int cwp;
static int wsetsz = 0;
int nstate = 0;
static int nstatesz = NSTATES;
ITEM **pstate;
int *tystate;
int *indgo;
static int *tmp_lset;
static int *tstates;
static int *ntstates;
static int *mstates;
int *amem, *memp;
int new_actsize = ACTSIZE;
int *temp1;
int lineno = 0;
int size;
static int fatfl = 1;
static int nerrors = 0;
static int ***pres;
static LOOKSETS **pfirst;
static int *pempty;
extern int nprodsz;
int
main(int argc, char *argv[])
{
(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
setup(argc, argv);
TBITSET = NWORDS(ntoksz*LKFACTOR);
tbitset = NWORDS(ntokens*LKFACTOR);
mktbls();
cpres();
cempty();
cpfir();
stagen();
output();
go2out();
hideprod();
summary();
callopt();
others();
return (0);
}
static void
mktbls(void)
{
int i;
size = ntoksz + nnontersz +1;
if (size < nstatesz)
size = nstatesz;
if (size < new_memsize)
size = new_memsize;
amem = (int *) malloc(sizeof (int) * new_actsize);
psmem = (ITEM *) malloc(sizeof (ITEM) * new_pstsize);
if ((psmem == NULL) || (amem == NULL))
error(gettext(
"couldn't allocate initial table"));
zzmemsz = psmem;
memp = amem;
#define INIT_LSIZE nnontersz * LKFACTOR
tmp_lset = (int *)
calloc((size_t)(TBITSET * (INIT_LSIZE+1)), sizeof (int));
if (tmp_lset == NULL)
error(gettext(
"could not allocate lookset array"));
lkst = (LOOKSETS *) malloc(sizeof (LOOKSETS) * (INIT_LSIZE + 1));
for (i = 0; i <= INIT_LSIZE; ++i)
lkst[i].lset = tmp_lset + TBITSET * i;
tmp_lset = NULL;
tmp_lset = (int *)
calloc((size_t)(TBITSET * (nnontersz+1)), sizeof (int));
if (tmp_lset == NULL)
error(gettext(
"could not allocate lookset array"));
wsets = (WSET *) malloc(sizeof (WSET) * (nnontersz + 1));
for (i = 0; i <= nnontersz; ++i)
wsets[i].ws.lset = tmp_lset + TBITSET * i;
tmp_lset = NULL;
clset.lset = (int *)malloc(sizeof (int)*TBITSET);
tstates = (int *)malloc(sizeof (int)*(ntoksz + 1));
ntstates = (int *)malloc(sizeof (int)*(nnontersz + 1));
temp1 = (int *)malloc(sizeof (int)*size);
pres = (int ***)malloc(sizeof (int **)*(nnontersz + 2));
pfirst = (LOOKSETS **)malloc(sizeof (LOOKSETS *)*(nnontersz + 2));
pempty = (int *)malloc(sizeof (int)*(nnontersz + 1));
pstate = (ITEM **)malloc(sizeof (ITEM *)*(nstatesz+2));
tystate = (int *)malloc(sizeof (int)*nstatesz);
indgo = (int *)malloc(sizeof (int)*nstatesz);
mstates = (int *)malloc(sizeof (int)*nstatesz);
defact = (int *)malloc(sizeof (int)*nstatesz);
if ((lkst == NULL) || (wsets == NULL) || (tstates == NULL) ||
(ntstates == NULL) || (temp1 == NULL) || (pres == NULL) ||
(pfirst == NULL) || (pempty == NULL) || (pstate == NULL) ||
(tystate == NULL) || (indgo == NULL) || (mstates == NULL) ||
(defact == NULL) || (clset.lset == NULL))
error(gettext(
"cannot allocate tables in mktbls()"));
aryfil(ntstates, nnontersz+1, 0);
aryfil(tstates, ntoksz+1, 0);
wsetsz = nnontersz + 1;
lsetsize = INIT_LSIZE + 1;
}
static void
others(void)
{
extern int gen_lines;
int c, i, j;
int tmpline;
finput = fopen(parser, "r");
if (finput == NULL)
error(gettext(
"cannot find parser %s"),
parser);
warray(L"yyr1", levprd, nprod);
aryfil(temp1, nprod, 0);
PLOOP(1, i)
temp1[i] = ((prdptr[i+1] - prdptr[i]-2) << 1) | had_act[i];
warray(L"yyr2", temp1, nprod);
aryfil(temp1, nstate, -10000000);
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(L"yychk", temp1, nstate);
warray(L"yydef", defact, nstate);
if ((fdebug = fopen(DEBUGNAME, "r")) == NULL)
error("cannot open yacc.debug");
while ((c = getwc(fdebug)) != EOF)
(void) putwc(c, ftable);
(void) fclose(fdebug);
ZAPFILE(DEBUGNAME);
if (gen_lines)
(void) fprintf(ftable, "# line\t1 \"%s\"\n", parser);
tmpline = 1;
while ((c = getwc(finput)) != EOF) {
if (c == '\n')
tmpline++;
if (c == L'$') {
if ((c = getwc(finput)) != L'A')
(void) putwc(L'$', ftable);
else {
tmpline++;
faction = fopen(ACTNAME, "r");
if (faction == NULL)
error(gettext(
"cannot open action tempfile"));
while ((c = getwc(faction)) != EOF)
(void) putwc(c, ftable);
(void) fclose(faction);
if (gen_lines)
(void) fprintf(ftable,
"\n# line\t%d \"%s\"",
tmpline,
parser);
ZAPFILE(ACTNAME);
c = getwc(finput);
}
}
(void) putwc(c, ftable);
}
(void) fclose(ftable);
}
static wchar_t *
chcopy(wchar_t *p, wchar_t *q)
{
while ((*p = *q++) != L'\0')
++p;
return (p);
}
#define ISIZE 400
wchar_t *
writem(int *pp)
{
int i, *p;
static int isize = ISIZE;
static wchar_t *sarr = NULL;
wchar_t *q;
if (sarr == NULL) {
sarr = (wchar_t *)malloc(sizeof (wchar_t) * isize);
if (sarr == NULL)
error(gettext(
"could not allocate output string array"));
for (i = 0; i < isize; ++i)
sarr[i] = L' ';
}
for (p = pp; *p > 0; ++p)
;
p = prdptr[-*p];
q = chcopy(sarr, nontrst[*p-NTBASE].name);
q = chcopy(q, L" : ");
for (;;) {
*q++ = ++p == pp ? L'_' : L' ';
*q = 0;
if ((i = *p) <= 0)
break;
q = chcopy(q, symnam(i));
while (q > &sarr[isize-30]) {
static wchar_t *sarrbase;
sarrbase = sarr;
isize += ISIZE;
sarr = (wchar_t *)
realloc((char *)sarr, sizeof (*sarr) * isize);
if (sarr == NULL)
error(gettext(
"cannot expand sarr arrays"));
q = q - sarrbase + sarr;
}
}
if ((i = *pp) < 0) {
q = chcopy(q, L" (");
(void) wsprintf(q, "%d)", -i);
}
return (sarr);
}
wchar_t *
symnam(int i)
{
wchar_t *cp;
cp = (i >= NTBASE) ? nontrst[i-NTBASE].name : tokset[i].name;
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;
static void
summary(void)
{
if (foutput != NULL) {
(void) fprintf(foutput,
"\n%d/%d terminals, %d/%d nonterminals\n",
ntokens, ntoksz, nnonter, nnontersz);
(void) fprintf(foutput,
"%d/%d grammar rules, %d/%d states\n",
nprod, nprodsz, nstate, nstatesz);
(void) fprintf(foutput,
"%d shift/reduce, %d reduce/reduce conflicts reported\n",
zzsrconf, zzrrconf);
(void) fprintf(foutput,
"%d/%d working sets used\n", zzcwp, wsetsz);
(void) fprintf(foutput,
"memory: states,etc. %" PRIdPTR
"/%d, parser %" PRIdPTR "/%d\n",
mem-tracemem, new_memsize,
memp-amem, new_actsize);
(void) fprintf(foutput,
"%d/%d distinct lookahead sets\n", nlset, lsetsize);
(void) fprintf(foutput,
"%d extra closures\n", zzclose - 2*nstate);
(void) fprintf(foutput,
"%d shift entries, %d exceptions\n", zzacent, zzexcp);
(void) fprintf(foutput,
"%d goto entries\n", zzgoent);
(void) fprintf(foutput,
"%d entries saved by goto default\n", zzgobest);
}
if (zzsrconf != 0 || zzrrconf != 0) {
(void) fprintf(stderr, gettext(
"\nconflicts: "));
if (zzsrconf)
(void) fprintf(stderr, "%d shift/reduce", zzsrconf);
if (zzsrconf && zzrrconf)
(void) fprintf(stderr, ", ");
if (zzrrconf)
(void) fprintf(stderr, "%d reduce/reduce", zzrrconf);
(void) fprintf(stderr, "\n");
}
if (ftemp != NULL)
(void) fclose(ftemp);
if (fdefine != NULL)
(void) fclose(fdefine);
}
void
error(char *s, ...)
{
extern char *infile;
va_list ap;
va_start(ap, s);
++nerrors;
if (!lineno)
(void) fprintf(stderr, gettext(
"command line: fatal: "));
else {
(void) fprintf(stderr, "\"%s\", ", infile);
(void) fprintf(stderr, gettext(
"line %d: fatal: "),
lineno);
}
(void) vfprintf(stderr, s, ap);
(void) fprintf(stderr, "\n");
va_end(ap);
if (!fatfl)
return;
summary();
exit(1);
}
void
warning(int flag, char *s, ...)
{
extern char *infile;
va_list ap;
va_start(ap, s);
(void) fprintf(stderr, "\"%s\", ", infile);
if (flag == 0)
(void) fprintf(stderr, gettext(
"warning: "));
else
(void) fprintf(stderr, gettext(
"line %d: warning: "),
lineno);
(void) vfprintf(stderr, s, ap);
(void) fprintf(stderr, "\n");
va_end(ap);
}
void
aryfil(int *v, int n, int c)
{
int i;
for (i = 0; i < n; ++i)
v[i] = c;
}
static int
setunion(int *a, int *b)
{
int i, x, sub;
sub = 0;
SETLOOP(i) {
*a = (x = *a) | *b++;
if (*a++ != x)
sub = 1;
}
return (sub);
}
static void
prlook(LOOKSETS *p)
{
int j, *pp;
pp = p->lset;
if (pp == 0)
(void) fprintf(foutput, "\tNULL");
else {
(void) fprintf(foutput, " { ");
TLOOP(j) {
if (BIT(pp, j))
(void) fprintf(foutput, "%ws ", symnam(j));
}
(void) fprintf(foutput, "}");
}
}
static void
cpres(void)
{
int **ptrpy;
int **pyield;
int c, j, i;
if ((pyield = (int **) malloc(sizeof (int *) * nprodsz)) == NULL)
error(gettext(
"cannot allocate space for pyield array"));
ptrpy = pyield;
NTLOOP(i) {
c = i+NTBASE;
pres[i] = ptrpy;
fatfl = 0;
PLOOP(0, j) {
if (*prdptr[j] == c)
*ptrpy++ = prdptr[j] + 1;
}
if (pres[i] == ptrpy) {
error(gettext(
"undefined nonterminal: %ws"),
nontrst[i].name);
}
}
pres[i] = ptrpy;
fatfl = 1;
if (nerrors) {
summary();
exit(1);
}
if (ptrpy != &pyield[nprod])
error(gettext(
"internal Yacc error: pyield %d"),
ptrpy-&pyield[nprod]);
}
static int indebug = 0;
static void
cpfir(void)
{
int *p, **s, i, **t, ch, changes;
zzcwp = nnonter;
NTLOOP(i) {
aryfil(wsets[i].ws.lset, tbitset, 0);
t = pres[i+1];
for (s = pres[i]; s < t; ++s) {
for (p = *s; (ch = *p) > 0; ++p) {
if (ch < NTBASE) {
SETBIT(wsets[i].ws.lset, ch);
break;
} else if (!pempty[ch-NTBASE])
break;
}
}
}
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);
if (!indebug)
return;
if ((foutput != NULL)) {
NTLOOP(i) {
(void) fprintf(foutput, "\n%ws: ", nontrst[i].name);
prlook(pfirst[i]);
(void) fprintf(foutput, " %d\n", pempty[i]);
}
}
}
int
state(int c)
{
int size1, size2;
int i;
ITEM *p1, *p2, *k, *l, *q1, *q2;
p1 = pstate[nstate];
p2 = pstate[nstate+1];
if (p1 == p2)
return (0);
for (k = p2 - 1; k > p1; k--) {
for (l = k-1; l >= p1; --l)
if (l->pitem > k->pitem) {
int *s;
LOOKSETS *ss;
s = k->pitem;
k->pitem = l->pitem;
l->pitem = s;
ss = k->look;
k->look = l->look;
l->look = ss;
}
}
size1 = p2 - p1;
for (i = (c >= NTBASE) ? ntstates[c-NTBASE] : tstates[c];
i != 0; i = mstates[i]) {
q1 = pstate[i];
q2 = pstate[i+1];
size2 = q2 - q1;
if (size1 != size2)
continue;
k = p1;
for (l = q1; l < q2; l++) {
if (l->pitem != k->pitem)
break;
++k;
}
if (l != q2)
continue;
pstate[nstate+1] = pstate[nstate];
if (nolook)
return (i);
for (l = q1, k = p1; l < q2; ++l, ++k) {
int s;
SETLOOP(s)
clset.lset[s] = l->look->lset[s];
if (setunion(clset.lset, k->look->lset)) {
tystate[i] = MUSTDO;
l->look = flset(&clset);
}
}
return (i);
}
if (nolook)
error(gettext(
"yacc state/nolook error"));
pstate[nstate+2] = p2;
if (nstate+1 >= nstatesz)
exp_states();
if (c >= NTBASE) {
mstates[nstate] = ntstates[c - NTBASE];
ntstates[c - NTBASE] = nstate;
} else {
mstates[nstate] = tstates[c];
tstates[c] = nstate;
}
tystate[nstate] = MUSTDO;
return (nstate++);
}
static int pidebug = 0;
void
putitem(int *ptr, LOOKSETS *lptr)
{
register ITEM *j;
if (pidebug && (foutput != NULL))
(void) fprintf(foutput,
"putitem(%ws), state %d\n", writem(ptr), nstate);
j = pstate[nstate+1];
j->pitem = ptr;
if (!nolook)
j->look = flset(lptr);
pstate[nstate+1] = ++j;
if (j > zzmemsz) {
zzmemsz = j;
if (zzmemsz >= &psmem[new_pstsize])
exp_psmem();
}
}
static void
cempty(void)
{
#define EMPTY 1
#define WHOKNOWS 0
#define OK 1
int i, *p;
aryfil(pempty, nnonter+1, WHOKNOWS);
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) {
pempty[*prdptr[i]-NTBASE] = OK;
goto more;
}
}
NTLOOP(i) {
if (i == 0)
continue;
if (pempty[i] != OK) {
fatfl = 0;
error(gettext(
"nonterminal %ws never derives any token string"),
nontrst[i].name);
}
}
if (nerrors) {
summary();
exit(1);
}
aryfil(pempty, nnonter+1, WHOKNOWS);
again:
PLOOP(1, i) {
if (pempty[*prdptr[i]-NTBASE] == WHOKNOWS) {
for (p = prdptr[i]+1;
*p >= NTBASE && pempty[*p-NTBASE] == EMPTY; ++p)
;
if (*p < 0) {
pempty[*prdptr[i]-NTBASE] = EMPTY;
goto again;
}
}
}
}
static int gsdebug = 0;
static void
stagen(void)
{
int i, j;
int c;
register WSET *p, *q;
nstate = 0;
pstate[0] = pstate[1] = psmem;
aryfil(clset.lset, tbitset, 0);
putitem(prdptr[0] + 1, &clset);
tystate[0] = MUSTDO;
nstate = 1;
pstate[2] = pstate[1];
aryfil(amem, new_actsize, 0);
more:
SLOOP(i) {
if (tystate[i] != MUSTDO)
continue;
tystate[i] = DONE;
aryfil(temp1, nnonter + 1, 0);
closure(i);
WSLOOP(wsets, p) {
if (p->flag)
continue;
p->flag = 1;
c = *(p->pitem);
if (c <= 1) {
if (pstate[i+1]-pstate[i] <= p-wsets)
tystate[i] = MUSTLOOKAHEAD;
continue;
}
WSLOOP(p, q) {
if (c == *(q->pitem)) {
putitem(q->pitem + 1, &q->ws);
q->flag = 1;
}
}
if (c < NTBASE)
(void) state(c);
else temp1[c-NTBASE] = state(c);
}
if (gsdebug && (foutput != NULL)) {
(void) fprintf(foutput, "%d: ", i);
NTLOOP(j) {
if (temp1[j])
(void) fprintf(foutput,
"%ws %d, ", nontrst[j].name,
temp1[j]);
}
(void) fprintf(foutput, "\n");
}
indgo[i] = apack(&temp1[1], nnonter - 1) - 1;
goto more;
}
}
static int cldebug = 0;
void
closure(int i)
{
int c, ch, work, k;
register WSET *u, *v;
int *pi;
int **s, **t;
ITEM *q;
register ITEM *p;
int idx1 = 0;
++zzclose;
cwp = 0;
ITMLOOP(i, p, q) {
wsets[cwp].pitem = p->pitem;
wsets[cwp].flag = 1;
SETLOOP(k)
wsets[cwp].ws.lset[k] = p->look->lset[k];
WSBUMP(cwp);
}
work = 1;
while (work) {
work = 0;
for (idx1 = 0; idx1 < cwp; idx1++) {
u = &wsets[idx1];
if (u->flag == 0)
continue;
c = *(u->pitem);
if (c < NTBASE) {
u->flag = 0;
continue;
}
aryfil(clset.lset, tbitset, 0);
WSLOOP(u, v) {
if (v->flag == 1 && *(pi = v->pitem) == c) {
v->flag = 0;
if (nolook)
continue;
while ((ch = *++pi) > 0) {
if (ch < NTBASE) {
SETBIT(clset.lset, ch);
break;
}
(void) setunion(clset.lset,
pfirst[ch-NTBASE]->lset);
if (!pempty[ch-NTBASE])
break;
}
if (ch <= 0)
(void) setunion(clset.lset,
v->ws.lset);
}
}
c -= NTBASE;
t = pres[c+1];
for (s = pres[c]; s < t; ++s) {
WSLOOP(wsets, v) {
if (v->pitem == *s) {
if (nolook)
goto nexts;
if (setunion(v->ws.lset,
clset.lset))
v->flag = work = 1;
goto nexts;
}
}
if (cwp + 1 >= wsetsz)
exp_wsets();
wsets[cwp].pitem = *s;
wsets[cwp].flag = 1;
if (!nolook) {
work = 1;
SETLOOP(k)
wsets[cwp].ws.lset[k] =
clset.lset[k];
}
WSBUMP(cwp);
nexts:;
}
}
}
if (&wsets[cwp] > &wsets[zzcwp])
zzcwp = cwp;
if (cldebug && (foutput != NULL)) {
(void) fprintf(foutput, "\nState %d, nolook = %d\n", i, nolook);
WSLOOP(wsets, u) {
if (u->flag)
(void) fprintf(foutput, "flag set!\n");
u->flag = 0;
(void) fprintf(foutput, "\t%ws", writem(u->pitem));
prlook(&u->ws);
(void) fprintf(foutput, "\n");
}
}
}
static LOOKSETS *
flset(LOOKSETS *p)
{
int j, *w;
int *u, *v;
register LOOKSETS *q;
for (q = &lkst[nlset]; q-- > lkst; ) {
u = p->lset;
v = q->lset;
w = & v[tbitset];
while (v < w)
if (*u++ != *v++)
goto more;
return (q);
more:;
}
q = &lkst[nlset++];
if (nlset >= lsetsize) {
exp_lkst();
q = &lkst[nlset++];
}
SETLOOP(j) q->lset[j] = p->lset[j];
return (q);
}
static void
exp_lkst(void)
{
int i, j;
static LOOKSETS *lookbase;
lookbase = lkst;
lsetsize += LSETSIZE;
tmp_lset = (int *)
calloc((size_t)(TBITSET * (lsetsize-LSETSIZE)), sizeof (int));
if (tmp_lset == NULL)
error(gettext(
"could not expand lookset array"));
lkst = (LOOKSETS *) realloc((char *)lkst, sizeof (LOOKSETS) * lsetsize);
for (i = lsetsize-LSETSIZE, j = 0; i < lsetsize; ++i, ++j)
lkst[i].lset = tmp_lset + TBITSET * j;
tmp_lset = NULL;
if (lkst == NULL)
error(gettext(
"could not expand lookahead sets"));
for (i = 0; i <= nnonter; ++i)
pfirst[i] = pfirst[i] - lookbase + lkst;
for (i = 0; i <= nstate+1; ++i) {
if (psmem[i].look)
psmem[i].look = psmem[i].look - lookbase + lkst;
if (pstate[i]->look)
pstate[i]->look = pstate[i]->look - lookbase + lkst;
}
}
static void
exp_wsets(void)
{
int i, j;
wsetsz += WSETSIZE;
tmp_lset = (int *)
calloc((size_t)(TBITSET * (wsetsz-WSETSIZE)), sizeof (int));
if (tmp_lset == NULL)
error(gettext(
"could not expand lookset array"));
wsets = (WSET *) realloc((char *)wsets, sizeof (WSET) * wsetsz);
for (i = wsetsz-WSETSIZE, j = 0; i < wsetsz; ++i, ++j)
wsets[i].ws.lset = tmp_lset + TBITSET * j;
tmp_lset = NULL;
if (wsets == NULL)
error(gettext(
"could not expand working sets"));
}
static void
exp_states(void)
{
nstatesz += NSTATES;
pstate = (ITEM **)
realloc((char *)pstate, sizeof (ITEM *)*(nstatesz+2));
mstates = (int *)realloc((char *)mstates, sizeof (int)*nstatesz);
defact = (int *)realloc((char *)defact, sizeof (int)*nstatesz);
tystate = (int *)realloc((char *)tystate, sizeof (int)*nstatesz);
indgo = (int *)realloc((char *)indgo, sizeof (int)*nstatesz);
if ((*pstate == NULL) || (tystate == NULL) || (defact == NULL) ||
(indgo == NULL) || (mstates == NULL))
error(gettext(
"cannot expand table of states"));
}
static void
exp_psmem(void)
{
int i;
new_pstsize += PSTSIZE;
psmem = (ITEM *) realloc((char *)psmem, sizeof (ITEM) * new_pstsize);
if (psmem == NULL)
error(gettext(
"cannot expand pstate memory"));
zzmemsz = zzmemsz - pstate[0] + psmem;
for (i = 1; i <= nstate+1; ++i)
pstate[i] = pstate[i] - pstate[0] + psmem;
pstate[0] = psmem;
}