/* 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; }
/* 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); }