/* Partially preprocesses a #if expression. ifexp points to the text * immediately following the #if. The function seeks to the end of the * expression and evaluates it. The return value points to the text * immediately following the expression. If the expression has a * defined state, status receives either statDefined or statUndefined. * If the expression's contents are disjoint from the defined and * undefined symbols, status receives statUnaffected. Otherwise the * expression is in a partial state, in which case status receives * statPartDefined, and the original string is modified so as to * remove the parts of the expression that have a defined state. */ static char const *seqif(struct ppproc *ppp, char *ifexp, enum status *status) { struct exptree *tree; char const *ret; char *str; int defined, n; tree = initexptree(); *status = statUnaffected; n = geterrormark(); ret = parseexptree(tree, ppp->cl, ifexp); if (errorsincemark(n)) { *status = statError; goto quit; } n = markdefined(tree, ppp->defs, TRUE) + markdefined(tree, ppp->undefs, FALSE); if (n) { *status = evaltree(tree, &defined) ? statDefined : statUndefined; if (!defined) { *status = statPartDefined; str = allocate(strlen(ifexp) + 1); n = unparseevaluated(tree, str); strcpy(str + n, ifexp + getexplength(tree)); strcpy(ifexp, str); deallocate(str); } } quit: freeexptree(tree); return ret; }
/* Extracts from the expression tree those parts that do not have a * defined value, and "unparses" that back into a C preprocessor * expression, storing the resulting source code in buffer. */ int unparseevaluated(struct exptree const *t, char *buffer) { char const *src; char *buf; size_t size; int n; if (t->exp == expNone) return 0; if (t->exp != expOperator) { if (t->valued) { size = sprintf(buffer, "%ld", t->value); } else { size = getexplength(t); memcpy(buffer, t->begin, size); } return (int)size; } if (t->op == opConditional) { if (t->child[0]->valued) return unparseevaluated(t->child[t->child[0]->value ? 1 : 2], buffer); } else if (t->op == opLogAnd || t->op == opLogOr) { if (t->child[0]->valued) return unparseevaluated(t->child[1], buffer); else if (t->child[1]->valued) return unparseevaluated(t->child[0], buffer); } buf = buffer; src = t->begin; for (n = 0 ; n < t->childcount ; ++n) { size = t->child[n]->begin - src; if (size) { memcpy(buf, src, size); buf += size; } buf += unparseevaluated(t->child[n], buf); src = t->child[n]->end; } size = t->end - src; if (size) { memcpy(buf, src, size); buf += size; } return (int)(buf - buffer); }