int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken* ppToken) { TSourceLoc loc = ppToken->loc; // because we sometimes read the newline before reporting the error if (token == PpAtomIdentifier) { if (ppToken->atom == PpAtomDefined) { bool needclose = 0; token = scanToken(ppToken); if (token == '(') { needclose = true; token = scanToken(ppToken); } if (token != PpAtomIdentifier) { parseContext.ppError(loc, "incorrect directive, expected identifier", "preprocessor evaluation", ""); err = true; res = 0; return token; } Symbol* s = LookUpSymbol(ppToken->atom); res = s ? ! s->mac.undef : 0; token = scanToken(ppToken); if (needclose) { if (token != ')') { parseContext.ppError(loc, "expected ')'", "preprocessor evaluation", ""); err = true; res = 0; return token; } token = scanToken(ppToken); } } else { token = evalToToken(token, shortCircuit, res, err, ppToken); return eval(token, precedence, shortCircuit, res, err, ppToken); } } else if (token == PpAtomConstInt) { res = ppToken->ival; token = scanToken(ppToken); } else if (token == '(') { token = scanToken(ppToken); token = eval(token, MIN_PRECEDENCE, shortCircuit, res, err, ppToken); if (! err) { if (token != ')') { parseContext.ppError(loc, "expected ')'", "preprocessor evaluation", ""); err = true; res = 0; return token; } token = scanToken(ppToken); } } else { int op = NUM_ELEMENTS(unop) - 1; for (; op >= 0; op--) { if (unop[op].token == token) break; } if (op >= 0) { token = scanToken(ppToken); token = eval(token, UNARY, shortCircuit, res, err, ppToken); res = unop[op].op(res); } else { parseContext.ppError(loc, "bad expression", "preprocessor evaluation", ""); err = true; res = 0; return token; } } token = evalToToken(token, shortCircuit, res, err, ppToken); // Perform evaluation of binary operation, if there is one, otherwise we are done. while (! err) { if (token == ')' || token == '\n') break; int op; for (op = NUM_ELEMENTS(binop) - 1; op >= 0; op--) { if (binop[op].token == token) break; } if (op < 0 || binop[op].precedence <= precedence) break; int leftSide = res; // Setup short-circuiting, needed for ES, unless already in a short circuit. // (Once in a short-circuit, can't turn off again, until that whole subexpression is done. if (! shortCircuit) { if ((token == PpAtomOr && leftSide == 1) || (token == PpAtomAnd && leftSide == 0)) shortCircuit = true; } token = scanToken(ppToken); token = eval(token, binop[op].precedence, shortCircuit, res, err, ppToken); if (binop[op].op == op_div || binop[op].op == op_mod) { if (res == 0) { parseContext.ppError(loc, "division by 0", "preprocessor evaluation", ""); res = 1; } } res = binop[op].op(leftSide, res); } return token; }
int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken* ppToken) { TSourceLoc loc = ppToken->loc; // because we sometimes read the newline before reporting the error if (token == PpAtomIdentifier) { if (strcmp("defined", ppToken->name) == 0) { if (! parseContext.isReadingHLSL() && isMacroInput()) { if (parseContext.relaxedErrors()) parseContext.ppWarn(ppToken->loc, "nonportable when expanded from macros for preprocessor expression", "defined", ""); else parseContext.ppError(ppToken->loc, "cannot use in preprocessor expression when expanded from macros", "defined", ""); } bool needclose = 0; token = scanToken(ppToken); if (token == '(') { needclose = true; token = scanToken(ppToken); } if (token != PpAtomIdentifier) { parseContext.ppError(loc, "incorrect directive, expected identifier", "preprocessor evaluation", ""); err = true; res = 0; return token; } MacroSymbol* macro = lookupMacroDef(atomStrings.getAtom(ppToken->name)); res = macro != nullptr ? !macro->undef : 0; token = scanToken(ppToken); if (needclose) { if (token != ')') { parseContext.ppError(loc, "expected ')'", "preprocessor evaluation", ""); err = true; res = 0; return token; } token = scanToken(ppToken); } } else { token = evalToToken(token, shortCircuit, res, err, ppToken); return eval(token, precedence, shortCircuit, res, err, ppToken); } } else if (token == PpAtomConstInt) { res = ppToken->ival; token = scanToken(ppToken); } else if (token == '(') { token = scanToken(ppToken); token = eval(token, MIN_PRECEDENCE, shortCircuit, res, err, ppToken); if (! err) { if (token != ')') { parseContext.ppError(loc, "expected ')'", "preprocessor evaluation", ""); err = true; res = 0; return token; } token = scanToken(ppToken); } } else { int op = NUM_ELEMENTS(unop) - 1; for (; op >= 0; op--) { if (unop[op].token == token) break; } if (op >= 0) { token = scanToken(ppToken); token = eval(token, UNARY, shortCircuit, res, err, ppToken); res = unop[op].op(res); } else { parseContext.ppError(loc, "bad expression", "preprocessor evaluation", ""); err = true; res = 0; return token; } } token = evalToToken(token, shortCircuit, res, err, ppToken); // Perform evaluation of binary operation, if there is one, otherwise we are done. while (! err) { if (token == ')' || token == '\n') break; int op; for (op = NUM_ELEMENTS(binop) - 1; op >= 0; op--) { if (binop[op].token == token) break; } if (op < 0 || binop[op].precedence <= precedence) break; int leftSide = res; // Setup short-circuiting, needed for ES, unless already in a short circuit. // (Once in a short-circuit, can't turn off again, until that whole subexpression is done. if (! shortCircuit) { if ((token == PpAtomOr && leftSide == 1) || (token == PpAtomAnd && leftSide == 0)) shortCircuit = true; } token = scanToken(ppToken); token = eval(token, binop[op].precedence, shortCircuit, res, err, ppToken); if (binop[op].op == op_div || binop[op].op == op_mod) { if (res == 0) { parseContext.ppError(loc, "division by 0", "preprocessor evaluation", ""); res = 1; } } res = binop[op].op(leftSide, res); } return token; }