/* Recursively examines an expression tree and sets the definition * state of any identifiers within that appear in the given symset. * The third parameter indicates whether the identifiers are to be * treated as defined or as undefined. */ int markdefined(struct exptree *t, struct symset *set, int defined) { long value; int count, n; count = 0; for (n = 0 ; n < t->childcount ; ++n) count += markdefined(t->child[n], set, defined); if (!t->valued) { if (t->exp == expDefined) { if (findsymbolinset(set, t->identifier, NULL)) { t->valued = TRUE; t->value = defined ? 1 : 0; ++count; } } else if (t->exp == expMacro) { if (findsymbolinset(set, t->begin, &value)) { t->valued = TRUE; t->value = defined ? value : 0; ++count; } } } return count; }
/* Partially preprocesses the current line of input. If the input * contains a preprocessor statement, the state of ppproc is updated * to reflect the current section, and if necessary the line of input * will be altered for output. */ static void seq(struct ppproc *ppp) { char const *input; char const *cmd; enum status status; int incomment; enum ppcmd id; int size, n; incomment = ccommentp(ppp->cl); ppp->absorb = FALSE; input = examinechar(ppp->cl, ppp->line); while (!preproclinep(ppp->cl)) { if (endoflinep(ppp->cl)) return; input = nextchar(ppp->cl, input); } cmd = skipwhite(ppp->cl, nextchar(ppp->cl, input)); input = getpreprocessorcmd(ppp->cl, cmd, &id); switch (id) { case cmdIfdef: case cmdIfndef: if (ppp->level + 1 >= sizearray(ppp->stack)) { error(errIfsTooDeep); break; } ++ppp->level; ppp->stack[ppp->level] = F_If | F_Ifdef; if (!ppp->copy) { input = restofline(ppp->cl, input); break; } ppp->stack[ppp->level] |= F_Copy; size = getidentifierlength(input); if (!size) { error(errEmptyIf); break; } if (findsymbolinset(ppp->defs, input, NULL)) n = statDefined; else if (findsymbolinset(ppp->undefs, input, NULL)) n = statUndefined; else n = statUnaffected; input = skipwhite(ppp->cl, nextchars(ppp->cl, input, size)); if (!endoflinep(ppp->cl)) { error(errSyntax); break; } if (n != statUnaffected) { ppp->absorb = TRUE; ppp->stack[ppp->level] |= F_Ours; ppp->copy = n == (id == cmdIfdef ? statDefined : statUndefined); } break; case cmdIf: if (ppp->level + 1 >= sizearray(ppp->stack)) { error(errIfsTooDeep); break; } ++ppp->level; ppp->stack[ppp->level] = F_If | (ppp->copy ? F_Copy : 0); if (!ppp->copy) { input = restofline(ppp->cl, input); break; } input = seqif(ppp, (char*)input, &status); if (status == statError) break; input = skipwhite(ppp->cl, input); if (!endoflinep(ppp->cl)) { error(errIfSyntax); break; } if (status == statDefined || status == statUndefined) { ppp->absorb = TRUE; ppp->stack[ppp->level] |= F_Ours; ppp->copy = status == statDefined; } break; case cmdElse: if (ppp->level < 0 || (ppp->stack[ppp->level] & F_Else)) { error(errDanglingElse); break; } ppp->stack[ppp->level] |= F_Else; if (!endoflinep(ppp->cl)) { error(errSyntax); break; } if (ppp->stack[ppp->level] & F_Ours) { ppp->copy = !ppp->copy; ppp->absorb = TRUE; n = ppp->level; while (ppp->stack[n] & F_Elif) { if (ppp->stack[n] & F_ElseModify) { ppp->absorb = TRUE; break; } --n; if (!(ppp->stack[n] & F_Ours)) ppp->absorb = FALSE; } } break; case cmdElif: if (ppp->level < 0 || !(ppp->stack[ppp->level] & F_If) || (ppp->stack[ppp->level] & F_Else)) { error(errDanglingElse); break; } else if (ppp->level + 1 >= sizearray(ppp->stack)) { error(errIfsTooDeep); break; } if (ppp->stack[ppp->level] & F_Ifdef) error(errElifWithIfdef); ppp->stack[ppp->level] |= F_Else; if (ppp->stack[ppp->level] & F_Ours) ppp->copy = !ppp->copy; ++ppp->level; ppp->stack[ppp->level] = F_If | F_Elif | (ppp->copy ? F_Copy : 0); if (!ppp->copy) { input = restofline(ppp->cl, input); break; } input = seqif(ppp, (char*)input, &status); if (status == statError) break; input = skipwhite(ppp->cl, input); if (!endoflinep(ppp->cl)) { error(errIfSyntax); break; } if (status == statUndefined) { ppp->copy = FALSE; ppp->absorb = TRUE; ppp->stack[ppp->level] |= F_Ours; } else if (status == statDefined) { ppp->absorb = TRUE; n = ppp->level; while (ppp->stack[n] & F_Elif) { --n; if (!(ppp->stack[n] & F_Ours)) { strcpy((char*)cmd, "else"); ppp->stack[ppp->level] |= F_ElseModify; ppp->absorb = FALSE; break; } } ppp->stack[ppp->level] |= F_Ours; } else { n = ppp->level; while (ppp->stack[n] & F_Elif) { --n; if (!(ppp->stack[n] & F_Ours)) { n = -1; break; } } if (n >= 0) { memmove((char*)cmd, cmd + 2, strlen(cmd + 2) + 1); ppp->stack[ppp->level] |= F_IfModify; } } break; case cmdEndif: if (ppp->level < 0) { error(errDanglingEnd); break; } if (!endoflinep(ppp->cl)) { error(errSyntax); input = restofline(ppp->cl, input); } ppp->absorb = TRUE; for ( ; ppp->stack[ppp->level] & F_Elif ; --ppp->level) { if (ppp->stack[ppp->level] & (F_IfModify | F_ElseModify)) ppp->absorb = FALSE; } if (ppp->absorb) ppp->absorb = ppp->stack[ppp->level] & F_Ours; ppp->copy = ppp->stack[ppp->level] & F_Copy; --ppp->level; break; default: input = restofline(ppp->cl, input); break; } if (ppp->absorb && incomment != ccommentp(ppp->cl)) error(errBrokenComment); }