int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken* ppToken)
{
while (token == PpAtomIdentifier && strcmp("defined", ppToken->name) != 0) {
- int macroReturn = MacroExpand(ppToken, true, false);
- if (macroReturn == 0) {
+ switch (MacroExpand(ppToken, true, false)) {
+ case MacroExpandNotStarted:
+ case MacroExpandError:
parseContext.ppError(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", "");
err = true;
res = 0;
- token = scanToken(ppToken);
break;
- }
- if (macroReturn == -1) {
+ case MacroExpandStarted:
+ break;
+ case MacroExpandUndef:
if (! shortCircuit && parseContext.profile == EEsProfile) {
const char* message = "undefined macro in expression not allowed in es profile";
if (parseContext.relaxedErrors())
else
parseContext.ppError(ppToken->loc, message, "preprocessor evaluation", ppToken->name);
}
+ break;
}
token = scanToken(ppToken);
+ if (err)
+ break;
}
return token;
int token;
while ((token = scanToken(ppToken)) != tMarkerInput::marker && token != EndOfInput) {
token = tokenPaste(token, *ppToken);
+ if (token == PpAtomIdentifier) {
+ switch (MacroExpand(ppToken, false, newLineOkay)) {
+ case MacroExpandNotStarted:
+ break;
+ case MacroExpandError:
+ token = EndOfInput;
+ break;
+ case MacroExpandStarted:
+ case MacroExpandUndef:
+ continue;
+ }
+ }
if (token == tMarkerInput::marker || token == EndOfInput)
break;
- if (token == PpAtomIdentifier && MacroExpand(ppToken, false, newLineOkay) != 0)
- continue;
expandedArg->putToken(token, ppToken);
}
if (token == EndOfInput) {
- // MacroExpand ate the marker, so had bad input, recover
+ // Error, or MacroExpand ate the marker, so had bad input, recover
delete expandedArg;
expandedArg = nullptr;
} else {
}
//
-// Check a token to see if it is a macro that should be expanded.
-// If it is, and defined, push a tInput that will produce the appropriate expansion
-// and return 1.
-// If it is, but undefined, and expandUndef is requested, push a tInput that will
-// expand to 0 and return -1.
-// Otherwise, return 0 to indicate no expansion, which is not necessarily an error.
+// Check a token to see if it is a macro that should be expanded:
+// - If it is, and defined, push a tInput that will produce the appropriate
+// expansion and return MacroExpandStarted.
+// - If it is, but undefined, and expandUndef is requested, push a tInput
+// that will expand to 0 and return MacroExpandUndef.
+// - Otherwise, there is no expansion, and there are two cases:
+// * It might be okay there is no expansion, and no specific error was
+// detected. Returns MacroExpandNotStarted.
+// * The expansion was started, but could not be completed, due to an error
+// that cannot be recovered from. Returns MacroExpandError.
//
-int TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay)
+MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay)
{
ppToken->space = false;
int macroAtom = atomStrings.getAtom(ppToken->name);
ppToken->ival = parseContext.getCurrentLoc().line;
snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
UngetToken(PpAtomConstInt, ppToken);
- return 1;
+ return MacroExpandStarted;
case PpAtomFileMacro: {
if (parseContext.getCurrentLoc().name)
ppToken->ival = parseContext.getCurrentLoc().string;
snprintf(ppToken->name, sizeof(ppToken->name), "%s", ppToken->loc.getStringNameOrNum().c_str());
UngetToken(PpAtomConstInt, ppToken);
- return 1;
+ return MacroExpandStarted;
}
case PpAtomVersionMacro:
ppToken->ival = parseContext.version;
snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
UngetToken(PpAtomConstInt, ppToken);
- return 1;
+ return MacroExpandStarted;
default:
break;
}
MacroSymbol* macro = macroAtom == 0 ? nullptr : lookupMacroDef(macroAtom);
- int depth = 0;
// no recursive expansions
if (macro != nullptr && macro->busy)
- return 0;
+ return MacroExpandNotStarted;
// not expanding undefined macros
if ((macro == nullptr || macro->undef) && ! expandUndef)
- return 0;
+ return MacroExpandNotStarted;
// 0 is the value of an undefined macro
if ((macro == nullptr || macro->undef) && expandUndef) {
pushInput(new tZeroInput(this));
- return -1;
+ return MacroExpandUndef;
}
tMacroInput *in = new tMacroInput(this);
if (token != '(') {
UngetToken(token, ppToken);
delete in;
- return 0;
+ return MacroExpandNotStarted;
}
in->args.resize(in->mac->args.size());
for (size_t i = 0; i < in->mac->args.size(); i++)
size_t arg = 0;
bool tokenRecorded = false;
do {
- depth = 0;
- while (1) {
+ TVector<char> nestStack;
+ while (true) {
token = scanToken(ppToken);
if (token == EndOfInput || token == tMarkerInput::marker) {
parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom));
delete in;
- return 0;
+ return MacroExpandError;
}
if (token == '\n') {
if (! newLineOkay) {
parseContext.ppError(loc, "End of line in macro substitution:", "macro expansion", atomStrings.getString(macroAtom));
delete in;
- return 0;
+ return MacroExpandError;
}
continue;
}
if (token == '#') {
parseContext.ppError(ppToken->loc, "unexpected '#'", "macro expansion", atomStrings.getString(macroAtom));
delete in;
- return 0;
+ return MacroExpandError;
}
if (in->mac->args.size() == 0 && token != ')')
break;
- if (depth == 0 && (token == ',' || token == ')'))
+ if (nestStack.size() == 0 && (token == ',' || token == ')'))
break;
if (token == '(')
- depth++;
- if (token == ')')
- depth--;
+ nestStack.push_back(')');
+ else if (token == '{' && parseContext.isReadingHLSL())
+ nestStack.push_back('}');
+ else if (nestStack.size() > 0 && token == nestStack.back())
+ nestStack.pop_back();
in->args[arg]->putToken(token, ppToken);
tokenRecorded = true;
}
+ // end of single argument scan
+
if (token == ')') {
+ // closing paren of call
if (in->mac->args.size() == 1 && tokenRecorded == 0)
break;
arg++;
}
arg++;
} while (arg < in->mac->args.size());
+ // end of all arguments scan
if (arg < in->mac->args.size())
parseContext.ppError(loc, "Too few args in Macro", "macro expansion", atomStrings.getString(macroAtom));
else if (token != ')') {
- depth=0;
+ // Error recover code; find end of call, if possible
+ int depth = 0;
while (token != EndOfInput && (depth > 0 || token != ')')) {
- if (token == ')')
+ if (token == ')' || token == '}')
depth--;
token = scanToken(ppToken);
- if (token == '(')
+ if (token == '(' || token == '{')
depth++;
}
if (token == EndOfInput) {
parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom));
delete in;
- return 0;
+ return MacroExpandError;
}
parseContext.ppError(loc, "Too many args in macro", "macro expansion", atomStrings.getString(macroAtom));
}
macro->busy = 1;
macro->body.reset();
- return 1;
+ return MacroExpandStarted;
}
} // end namespace glslang