cpp: fix mutually recursive macros
Handle cases where parameterless macros expand to each other: #define FOO BAR #define BAR FOO FOO There were cases where the macros didn't make it into the hidesets, and we would recurse infinitely. This fixes that.
This commit is contained in:
parent
77ddc8c654
commit
0366f11300
|
@ -110,7 +110,7 @@ void doif(Tokenrow *, enum kwtype);
|
||||||
void expand(Tokenrow *, Nlist *);
|
void expand(Tokenrow *, Nlist *);
|
||||||
void builtin(Tokenrow *, int);
|
void builtin(Tokenrow *, int);
|
||||||
int gatherargs(Tokenrow *, Tokenrow **, int, int *);
|
int gatherargs(Tokenrow *, Tokenrow **, int, int *);
|
||||||
void substargs(Nlist *, Tokenrow *, Tokenrow **);
|
void substargs(Nlist *, Tokenrow *, Tokenrow **, int);
|
||||||
void expandrow(Tokenrow *, char *);
|
void expandrow(Tokenrow *, char *);
|
||||||
void maketokenrow(int, Tokenrow *);
|
void maketokenrow(int, Tokenrow *);
|
||||||
Tokenrow *copytokenrow(Tokenrow *, Tokenrow *);
|
Tokenrow *copytokenrow(Tokenrow *, Tokenrow *);
|
||||||
|
|
|
@ -169,9 +169,8 @@ expandrow(Tokenrow *trp, char *flag)
|
||||||
}
|
}
|
||||||
if (np->flag&ISMAC)
|
if (np->flag&ISMAC)
|
||||||
builtin(trp, np->val);
|
builtin(trp, np->val);
|
||||||
else {
|
else
|
||||||
expand(trp, np);
|
expand(trp, np);
|
||||||
}
|
|
||||||
tp = trp->tp;
|
tp = trp->tp;
|
||||||
}
|
}
|
||||||
if (flag)
|
if (flag)
|
||||||
|
@ -186,18 +185,17 @@ expandrow(Tokenrow *trp, char *flag)
|
||||||
void
|
void
|
||||||
expand(Tokenrow *trp, Nlist *np)
|
expand(Tokenrow *trp, Nlist *np)
|
||||||
{
|
{
|
||||||
Tokenrow ntr;
|
int ntokc, narg, i, hs;
|
||||||
int ntokc, narg, i;
|
|
||||||
Token *tp;
|
|
||||||
Tokenrow *atr[NARG+1];
|
Tokenrow *atr[NARG+1];
|
||||||
int hs;
|
Tokenrow ntr;
|
||||||
|
Token *tp;
|
||||||
|
|
||||||
copytokenrow(&ntr, np->vp); /* copy macro value */
|
copytokenrow(&ntr, np->vp); /* copy macro value */
|
||||||
if (np->ap==NULL) { /* parameterless */
|
if (np->ap==NULL) { /* parameterless */
|
||||||
ntokc = 1;
|
ntokc = 1;
|
||||||
/* substargs for handling # and ## */
|
/* substargs for handling # and ## */
|
||||||
atr[0] = nil;
|
atr[0] = nil;
|
||||||
substargs(np, &ntr, atr);
|
substargs(np, &ntr, atr, trp->tp->hideset);
|
||||||
} else {
|
} else {
|
||||||
ntokc = gatherargs(trp, atr, (np->flag&ISVARMAC) ? rowlen(np->ap) : 0, &narg);
|
ntokc = gatherargs(trp, atr, (np->flag&ISVARMAC) ? rowlen(np->ap) : 0, &narg);
|
||||||
if (narg<0) { /* not actually a call (no '(') */
|
if (narg<0) { /* not actually a call (no '(') */
|
||||||
|
@ -210,12 +208,13 @@ expand(Tokenrow *trp, Nlist *np)
|
||||||
trp->tp += ntokc;
|
trp->tp += ntokc;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
substargs(np, &ntr, atr); /* put args into replacement */
|
substargs(np, &ntr, atr, trp->tp->hideset); /* put args into replacement */
|
||||||
for (i=0; i<narg; i++) {
|
for (i=0; i<narg; i++) {
|
||||||
dofree(atr[i]->bp);
|
dofree(atr[i]->bp);
|
||||||
dofree(atr[i]);
|
dofree(atr[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hs = newhideset(trp->tp->hideset, np);
|
hs = newhideset(trp->tp->hideset, np);
|
||||||
for (tp=ntr.bp; tp<ntr.lp; tp++) { /* distribute hidesets */
|
for (tp=ntr.bp; tp<ntr.lp; tp++) { /* distribute hidesets */
|
||||||
if (tp->type==NAME) {
|
if (tp->type==NAME) {
|
||||||
|
@ -343,19 +342,20 @@ ispaste(Tokenrow *rtr, Token **ap, Token **an, int *ntok)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* substitute the argument list into the replacement string
|
* substitute the argument list into the replacement string
|
||||||
* This would be simple except for ## and #
|
* This would be simple except for ## and #
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
substargs(Nlist *np, Tokenrow *rtr, Tokenrow **atr)
|
substargs(Nlist *np, Tokenrow *rtr, Tokenrow **atr, int hideset)
|
||||||
{
|
{
|
||||||
Tokenrow ttr, rp, rn;
|
Tokenrow ttr, rp, rn;
|
||||||
Token *tp, *ap, *an, *pp, *pn;
|
Token *tp, *ap, *an, *pp, *pn;
|
||||||
int ntok, argno, hs;
|
int ntok, argno, hs;
|
||||||
|
|
||||||
for (rtr->tp=rtr->bp; rtr->tp<rtr->lp; ) {
|
for (rtr->tp=rtr->bp; rtr->tp<rtr->lp; ) {
|
||||||
if(rtr->tp->hideset && checkhideset(rtr->tp->hideset, np)) {
|
if(rtr->tp->hideset && checkhideset(hideset, np)) {
|
||||||
rtr->tp++;
|
rtr->tp++;
|
||||||
} else if (rtr->tp->type==SHARP) { /* string operator */
|
} else if (rtr->tp->type==SHARP) { /* string operator */
|
||||||
tp = rtr->tp;
|
tp = rtr->tp;
|
||||||
|
@ -405,10 +405,10 @@ substargs(Nlist *np, Tokenrow *rtr, Tokenrow **atr)
|
||||||
*ttr.tp = *rtr->tp;
|
*ttr.tp = *rtr->tp;
|
||||||
|
|
||||||
hs = newhideset(rtr->tp->hideset, np);
|
hs = newhideset(rtr->tp->hideset, np);
|
||||||
if(ttr.tp->hideset == 0)
|
if(hideset == 0)
|
||||||
ttr.tp->hideset = hs;
|
ttr.tp->hideset = hs;
|
||||||
else
|
else
|
||||||
ttr.tp->hideset = unionhideset(ttr.tp->hideset, hs);
|
ttr.tp->hideset = unionhideset(hideset, hs);
|
||||||
expandrow(&ttr, (char*)np->name);
|
expandrow(&ttr, (char*)np->name);
|
||||||
for(tp = ttr.bp; tp != ttr.lp; tp++)
|
for(tp = ttr.bp; tp != ttr.lp; tp++)
|
||||||
if(tp->type == COMMA)
|
if(tp->type == COMMA)
|
||||||
|
|
Loading…
Reference in a new issue