/* 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; }
/* Reads a constant from the C source at input via the given lexer, * and uses it to initialize the expression tree. Literal numbers, * strings, characters, macro identifiers and function-like macro * invocations, and uses of the defined operator are all considered * constants by this function. The return value is the text following * the constant. */ static char const *parseconstant(struct exptree *t, struct clexer *cl, char const *input) { char *p; int size, paren, mark; mark = geterrormark(); t->begin = input; if (charquotep(cl)) { t->exp = expConstant; t->valued = TRUE; t->value = getcharconstant(input + 1); while (!endoflinep(cl) && charquotep(cl)) input = nextchar(cl, input); t->end = input; input = skipwhite(cl, input); } else if (!memcmp(input, "defined", 7)) { t->exp = expDefined; input = skipwhite(cl, nextchars(cl, input, 7)); paren = *input == '('; if (paren) input = skipwhite(cl, nextchar(cl, input)); size = getidentifierlength(input); if (!size) { error(errDefinedSyntax); goto failure; } t->identifier = input; input = nextchars(cl, input, size); if (paren) { input = skipwhite(cl, input); if (*input != ')') { error(errDefinedSyntax); goto failure; } input = nextchar(cl, input); } t->valued = FALSE; t->end = input; input = skipwhite(cl, input); } else if (isdigit(*input)) { t->exp = expConstant; if (*input == '0') { input = nextchar(cl, input); if (tolower(*input) == 'x') { do input = nextchar(cl, input); while (isxdigit(*input)); } else { while (*input >= '0' && *input <= '7') input = nextchar(cl, input); } } else { do input = nextchar(cl, input); while (isdigit(*input)); } t->value = strtol(t->begin, &p, 0); t->valued = p == input; if (toupper(*input) == 'L') { input = nextchar(cl, input); if (toupper(*input) == 'L') input = nextchar(cl, input); if (toupper(*input) == 'U') input = nextchar(cl, input); } else if (toupper(*input) == 'U') { input = nextchar(cl, input); if (toupper(*input) == 'L') { input = nextchar(cl, input); if (toupper(*input) == 'L') input = nextchar(cl, input); } } t->end = input; input = skipwhite(cl, input); } else if (_issym(*input)) { do input = nextchar(cl, input); while (_issym(*input)); t->end = input; input = skipwhite(cl, input); if (*input == '(') { t->exp = expParamMacro; paren = getparenlevel(cl); do { input = nextchar(cl, input); if (endoflinep(cl)) { error(errOpenParenthesis); goto failure; } } while (getparenlevel(cl) >= paren); t->valued = FALSE; t->end = input; input = skipwhite(cl, input); } else { t->exp = expMacro; } } else { error(errSyntax); goto failure; } if (!errorsincemark(mark)) return input; failure: t->exp = expNone; t->end = input; return input; }