Preprocessor: Rationalize, simplify, and correct the stack of input sources and their tokenization. This included
- consistently dealing with EOF and its effect on error recovery (bug 11444, #1) - turning a simulated OO hierarchy of function pointers and typecasting into a real C++ class hierarchy - correctly handling '\' everywhere, in all classes of tokens, as a layer before preprocessing itself - conditionally handling '\n' in macro expansion input, depending on whether it is in a macro expression or not - delete some unused "memory cleanup" code git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24626 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
08d182470b
commit
fcb4ed054c
16 changed files with 750 additions and 479 deletions
|
|
@ -132,7 +132,7 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
|
|||
Symbol *symb;
|
||||
|
||||
// get macro name
|
||||
int token = currentInput->scan(this, currentInput, ppToken);
|
||||
int token = scanToken(ppToken);
|
||||
if (token != CPP_IDENTIFIER) {
|
||||
parseContext.error(ppToken->loc, "must be followed by macro name", "#define", "");
|
||||
return token;
|
||||
|
|
@ -145,12 +145,12 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
|
|||
}
|
||||
|
||||
// gather parameters to the macro, between (...)
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
if (token == '(' && ! ppToken->space) {
|
||||
int argc = 0;
|
||||
int args[maxMacroArgs];
|
||||
do {
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
if (argc == 0 && token == ')')
|
||||
break;
|
||||
if (token != CPP_IDENTIFIER) {
|
||||
|
|
@ -173,7 +173,7 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
|
|||
else
|
||||
parseContext.error(ppToken->loc, "too many macro parameters", "#define", "");
|
||||
}
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
} while (token == ',');
|
||||
if (token != ')') {
|
||||
parseContext.error(ppToken->loc, "missing parenthesis", "#define", "");
|
||||
|
|
@ -183,7 +183,7 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
|
|||
mac.argc = argc;
|
||||
mac.args = (int*)mem_Alloc(pool, argc * sizeof(int));
|
||||
memcpy(mac.args, args, argc * sizeof(int));
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
}
|
||||
|
||||
// record the definition of the macro
|
||||
|
|
@ -191,7 +191,7 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
|
|||
mac.body = new TokenStream;
|
||||
while (token != '\n') {
|
||||
RecordToken(mac.body, token, ppToken);
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
if (token != '\n' && ppToken->space)
|
||||
RecordToken(mac.body, ' ', ppToken);
|
||||
}
|
||||
|
|
@ -238,7 +238,7 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
|
|||
// Handle #undef
|
||||
int TPpContext::CPPundef(TPpToken* ppToken)
|
||||
{
|
||||
int token = currentInput->scan(this, currentInput, ppToken);
|
||||
int token = scanToken(ppToken);
|
||||
Symbol *symb;
|
||||
if (token != CPP_IDENTIFIER) {
|
||||
parseContext.error(ppToken->loc, "must be followed by macro name", "#undef", "");
|
||||
|
|
@ -246,14 +246,14 @@ int TPpContext::CPPundef(TPpToken* ppToken)
|
|||
return token;
|
||||
}
|
||||
|
||||
const char* name = GetAtomString(ppToken->atom); // TODO preprocessor simplification: the token text should have been built into the ppToken during currentInput->scan()
|
||||
const char* name = GetAtomString(ppToken->atom); // TODO preprocessor simplification: the token text should have been built into the ppToken during scanToken()
|
||||
parseContext.reservedPpErrorCheck(ppToken->loc, name, "#undef");
|
||||
|
||||
symb = LookUpSymbol(ppToken->atom);
|
||||
if (symb) {
|
||||
symb->mac.undef = 1;
|
||||
}
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
if (token != '\n')
|
||||
parseContext.error(ppToken->loc, "can only be followed by a single macro name", "#undef", "");
|
||||
|
||||
|
|
@ -269,21 +269,21 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
|
|||
{
|
||||
int atom;
|
||||
int depth = 0;
|
||||
int token = currentInput->scan(this, currentInput, ppToken);
|
||||
int token = scanToken(ppToken);
|
||||
|
||||
while (token != EOF) {
|
||||
if (token != '#') {
|
||||
while (token != '\n' && token != EOF)
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
|
||||
if (token == EOF)
|
||||
return EOF;
|
||||
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((token = currentInput->scan(this, currentInput, ppToken)) != CPP_IDENTIFIER)
|
||||
if ((token = scanToken(ppToken)) != CPP_IDENTIFIER)
|
||||
continue;
|
||||
|
||||
atom = ppToken->atom;
|
||||
|
|
@ -292,7 +292,7 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
|
|||
ifdepth++;
|
||||
elsetracker++;
|
||||
} else if (atom == endifAtom) {
|
||||
token = extraTokenCheck(atom, ppToken, currentInput->scan(this, currentInput, ppToken));
|
||||
token = extraTokenCheck(atom, ppToken, scanToken(ppToken));
|
||||
elseSeen[elsetracker] = false;
|
||||
--elsetracker;
|
||||
if (depth == 0) {
|
||||
|
|
@ -306,7 +306,7 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
|
|||
} else if (matchelse && depth == 0) {
|
||||
if (atom == elseAtom) {
|
||||
elseSeen[elsetracker] = true;
|
||||
token = extraTokenCheck(atom, ppToken, currentInput->scan(this, currentInput, ppToken));
|
||||
token = extraTokenCheck(atom, ppToken, scanToken(ppToken));
|
||||
// found the #else we are looking for
|
||||
break;
|
||||
} else if (atom == elifAtom) {
|
||||
|
|
@ -327,7 +327,7 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
|
|||
parseContext.error(ppToken->loc, "#else after #else", "#else", "");
|
||||
else
|
||||
elseSeen[elsetracker] = true;
|
||||
token = extraTokenCheck(atom, ppToken, currentInput->scan(this, currentInput, ppToken));
|
||||
token = extraTokenCheck(atom, ppToken, scanToken(ppToken));
|
||||
} else if (atom == elifAtom) {
|
||||
if (elseSeen[elsetracker])
|
||||
parseContext.error(ppToken->loc, "#elif after #else", "#elif", "");
|
||||
|
|
@ -363,7 +363,7 @@ int TPpContext::extraTokenCheck(int atom, TPpToken* ppToken, int token)
|
|||
parseContext.error(ppToken->loc, message, label, "");
|
||||
|
||||
while (token != '\n')
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
}
|
||||
|
||||
return token;
|
||||
|
|
@ -438,16 +438,17 @@ struct TUnop {
|
|||
|
||||
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 == CPP_IDENTIFIER) {
|
||||
if (ppToken->atom == definedAtom) {
|
||||
bool needclose = 0;
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
if (token == '(') {
|
||||
needclose = true;
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
}
|
||||
if (token != CPP_IDENTIFIER) {
|
||||
parseContext.error(ppToken->loc, "incorrect directive, expected identifier", "preprocessor evaluation", "");
|
||||
parseContext.error(loc, "incorrect directive, expected identifier", "preprocessor evaluation", "");
|
||||
err = true;
|
||||
res = 0;
|
||||
|
||||
|
|
@ -455,16 +456,16 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
|
|||
}
|
||||
Symbol* s;
|
||||
res = (s = LookUpSymbol(ppToken->atom)) ? !s->mac.undef : 0;
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
if (needclose) {
|
||||
if (token != ')') {
|
||||
parseContext.error(ppToken->loc, "#else after #else", "preprocessor evaluation", "");
|
||||
parseContext.error(loc, "expected ')'", "preprocessor evaluation", "");
|
||||
err = true;
|
||||
res = 0;
|
||||
|
||||
return token;
|
||||
}
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
}
|
||||
} else {
|
||||
token = evalToToken(token, shortCircuit, res, err, ppToken);
|
||||
|
|
@ -472,19 +473,19 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
|
|||
}
|
||||
} else if (token == CPP_INTCONSTANT) {
|
||||
res = ppToken->ival;
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
} else if (token == '(') {
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
token = eval(token, MIN_PRECEDENCE, shortCircuit, res, err, ppToken);
|
||||
if (! err) {
|
||||
if (token != ')') {
|
||||
parseContext.error(ppToken->loc, "expected ')'", "preprocessor evaluation", "");
|
||||
parseContext.error(loc, "expected ')'", "preprocessor evaluation", "");
|
||||
err = true;
|
||||
res = 0;
|
||||
|
||||
return token;
|
||||
}
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
}
|
||||
} else {
|
||||
int op;
|
||||
|
|
@ -493,11 +494,11 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
|
|||
break;
|
||||
}
|
||||
if (op >= 0) {
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
token = eval(token, UNARY, shortCircuit, res, err, ppToken);
|
||||
res = unop[op].op(res);
|
||||
} else {
|
||||
parseContext.error(ppToken->loc, "bad expression", "preprocessor evaluation", "");
|
||||
parseContext.error(loc, "bad expression", "preprocessor evaluation", "");
|
||||
err = true;
|
||||
res = 0;
|
||||
|
||||
|
|
@ -528,7 +529,7 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
|
|||
shortCircuit = true;
|
||||
}
|
||||
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
token = eval(token, binop[op].precedence, shortCircuit, res, err, ppToken);
|
||||
res = binop[op].op(leftSide, res);
|
||||
}
|
||||
|
|
@ -540,11 +541,12 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
|
|||
int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken* ppToken)
|
||||
{
|
||||
while (token == CPP_IDENTIFIER && ppToken->atom != definedAtom) {
|
||||
int macroReturn = MacroExpand(ppToken->atom, ppToken, true);
|
||||
int macroReturn = MacroExpand(ppToken->atom, ppToken, true, false);
|
||||
if (macroReturn == 0) {
|
||||
parseContext.error(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", "");
|
||||
err = true;
|
||||
res = 0;
|
||||
token = scanToken(ppToken);
|
||||
break;
|
||||
}
|
||||
if (macroReturn == -1) {
|
||||
|
|
@ -557,7 +559,7 @@ int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, T
|
|||
parseContext.error(ppToken->loc, message, "preprocessor evaluation", name);
|
||||
}
|
||||
}
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
}
|
||||
|
||||
return token;
|
||||
|
|
@ -566,7 +568,7 @@ int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, T
|
|||
// Handle #if
|
||||
int TPpContext::CPPif(TPpToken* ppToken)
|
||||
{
|
||||
int token = currentInput->scan(this, currentInput, ppToken);
|
||||
int token = scanToken(ppToken);
|
||||
elsetracker++;
|
||||
if (! ifdepth++)
|
||||
ifloc = ppToken->loc;
|
||||
|
|
@ -587,7 +589,7 @@ int TPpContext::CPPif(TPpToken* ppToken)
|
|||
// Handle #ifdef
|
||||
int TPpContext::CPPifdef(int defined, TPpToken* ppToken)
|
||||
{
|
||||
int token = currentInput->scan(this, currentInput, ppToken);
|
||||
int token = scanToken(ppToken);
|
||||
int name = ppToken->atom;
|
||||
if (++ifdepth > maxIfNesting) {
|
||||
parseContext.error(ppToken->loc, "maximum nesting depth exceeded", "#ifdef", "");
|
||||
|
|
@ -601,11 +603,11 @@ int TPpContext::CPPifdef(int defined, TPpToken* ppToken)
|
|||
parseContext.error(ppToken->loc, "must be followed by macro name", "#ifndef", "");
|
||||
} else {
|
||||
Symbol *s = LookUpSymbol(name);
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
if (token != '\n') {
|
||||
parseContext.error(ppToken->loc, "unexpected tokens following #ifdef directive - expected a newline", "#ifdef", "");
|
||||
while (token != '\n')
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
}
|
||||
if (((s && !s->mac.undef) ? 1 : 0) != defined)
|
||||
token = CPPelse(1, ppToken);
|
||||
|
|
@ -621,7 +623,7 @@ int TPpContext::CPPline(TPpToken* ppToken)
|
|||
// "#line line
|
||||
// "#line line source-string-number"
|
||||
|
||||
int token = currentInput->scan(this, currentInput, ppToken);
|
||||
int token = scanToken(ppToken);
|
||||
if (token == '\n') {
|
||||
parseContext.error(ppToken->loc, "must by followed by an integral literal", "#line", "");
|
||||
return token;
|
||||
|
|
@ -651,7 +653,7 @@ int TPpContext::CPPline(TPpToken* ppToken)
|
|||
// Handle #error
|
||||
int TPpContext::CPPerror(TPpToken* ppToken)
|
||||
{
|
||||
int token = currentInput->scan(this, currentInput, ppToken);
|
||||
int token = scanToken(ppToken);
|
||||
std::string message;
|
||||
TSourceLoc loc = ppToken->loc;
|
||||
|
||||
|
|
@ -665,7 +667,7 @@ int TPpContext::CPPerror(TPpToken* ppToken)
|
|||
message.append(GetAtomString(token));
|
||||
}
|
||||
message.append(" ");
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
}
|
||||
//store this msg into the shader's information log..set the Compile Error flag!!!!
|
||||
parseContext.error(loc, message.c_str(), "#error", "");
|
||||
|
|
@ -683,7 +685,7 @@ int TPpContext::CPPpragma(TPpToken* ppToken)
|
|||
TVector<TString> tokens;
|
||||
|
||||
TSourceLoc loc = ppToken->loc; // because we go to the next line before processing
|
||||
int token = currentInput->scan(this, currentInput, ppToken);
|
||||
int token = scanToken(ppToken);
|
||||
while (token != '\n' && token != EOF) {
|
||||
switch (token) {
|
||||
case CPP_IDENTIFIER:
|
||||
|
|
@ -702,7 +704,7 @@ int TPpContext::CPPpragma(TPpToken* ppToken)
|
|||
SrcStrName[1] = '\0';
|
||||
tokens.push_back(SrcStrName);
|
||||
}
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
}
|
||||
|
||||
if (token == EOF)
|
||||
|
|
@ -716,7 +718,7 @@ int TPpContext::CPPpragma(TPpToken* ppToken)
|
|||
// #version: This is just for error checking: the version and profile are decided before preprocessing starts
|
||||
int TPpContext::CPPversion(TPpToken* ppToken)
|
||||
{
|
||||
int token = currentInput->scan(this, currentInput, ppToken);
|
||||
int token = scanToken(ppToken);
|
||||
|
||||
if (errorOnVersion || versionSeen)
|
||||
parseContext.error(ppToken->loc, "must occur first in shader", "#version", "");
|
||||
|
|
@ -733,7 +735,7 @@ int TPpContext::CPPversion(TPpToken* ppToken)
|
|||
|
||||
ppToken->ival = atoi(ppToken->name);
|
||||
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
|
||||
if (token == '\n')
|
||||
return token;
|
||||
|
|
@ -743,7 +745,7 @@ int TPpContext::CPPversion(TPpToken* ppToken)
|
|||
ppToken->atom != esAtom)
|
||||
parseContext.error(ppToken->loc, "bad profile name; use es, core, or compatibility", "#version", "");
|
||||
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
|
||||
if (token == '\n')
|
||||
return token;
|
||||
|
|
@ -757,7 +759,7 @@ int TPpContext::CPPversion(TPpToken* ppToken)
|
|||
// Handle #extension
|
||||
int TPpContext::CPPextension(TPpToken* ppToken)
|
||||
{
|
||||
int token = currentInput->scan(this, currentInput, ppToken);
|
||||
int token = scanToken(ppToken);
|
||||
char extensionName[80];
|
||||
|
||||
if (token=='\n') {
|
||||
|
|
@ -770,13 +772,13 @@ int TPpContext::CPPextension(TPpToken* ppToken)
|
|||
|
||||
strcpy(extensionName, GetAtomString(ppToken->atom));
|
||||
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
if (token != ':') {
|
||||
parseContext.error(ppToken->loc, "':' missing after extension name", "#extension", "");
|
||||
return token;
|
||||
}
|
||||
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
if (token != CPP_IDENTIFIER) {
|
||||
parseContext.error(ppToken->loc, "behavior for extension not specified", "#extension", "");
|
||||
return token;
|
||||
|
|
@ -784,7 +786,7 @@ int TPpContext::CPPextension(TPpToken* ppToken)
|
|||
|
||||
parseContext.updateExtensionBehavior(extensionName, GetAtomString(ppToken->atom));
|
||||
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
if (token == '\n')
|
||||
return token;
|
||||
else
|
||||
|
|
@ -795,7 +797,7 @@ int TPpContext::CPPextension(TPpToken* ppToken)
|
|||
|
||||
int TPpContext::readCPPline(TPpToken* ppToken)
|
||||
{
|
||||
int token = currentInput->scan(this, currentInput, ppToken);
|
||||
int token = scanToken(ppToken);
|
||||
bool isVersion = false;
|
||||
|
||||
if (token == CPP_IDENTIFIER) {
|
||||
|
|
@ -807,7 +809,7 @@ int TPpContext::readCPPline(TPpToken* ppToken)
|
|||
elsetracker[elseSeen] = true;
|
||||
if (! ifdepth)
|
||||
parseContext.error(ppToken->loc, "mismatched statements", "#else", "");
|
||||
token = extraTokenCheck(elseAtom, ppToken, currentInput->scan(this, currentInput, ppToken));
|
||||
token = extraTokenCheck(elseAtom, ppToken, scanToken(ppToken));
|
||||
token = CPPelse(0, ppToken);
|
||||
} else if (ppToken->atom == elifAtom) {
|
||||
if (! ifdepth)
|
||||
|
|
@ -815,9 +817,9 @@ int TPpContext::readCPPline(TPpToken* ppToken)
|
|||
if (elseSeen[elsetracker])
|
||||
parseContext.error(ppToken->loc, "#elif after #else", "#elif", "");
|
||||
// this token is really a dont care, but we still need to eat the tokens
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
while (token != '\n')
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
token = CPPelse(0, ppToken);
|
||||
} else if (ppToken->atom == endifAtom) {
|
||||
elseSeen[elsetracker] = false;
|
||||
|
|
@ -826,7 +828,7 @@ int TPpContext::readCPPline(TPpToken* ppToken)
|
|||
parseContext.error(ppToken->loc, "mismatched statements", "#endif", "");
|
||||
else
|
||||
--ifdepth;
|
||||
token = extraTokenCheck(endifAtom, ppToken, currentInput->scan(this, currentInput, ppToken));
|
||||
token = extraTokenCheck(endifAtom, ppToken, scanToken(ppToken));
|
||||
} else if (ppToken->atom == ifAtom) {
|
||||
token = CPPif (ppToken);
|
||||
} else if (ppToken->atom == ifdefAtom) {
|
||||
|
|
@ -849,38 +851,16 @@ int TPpContext::readCPPline(TPpToken* ppToken)
|
|||
} else {
|
||||
parseContext.error(ppToken->loc, "invalid directive:", "#", GetAtomString(ppToken->atom));
|
||||
}
|
||||
} else if (token != '\n' && token > 0)
|
||||
} else if (token != '\n' && token != EOF)
|
||||
parseContext.error(ppToken->loc, "invalid directive", "#", "");
|
||||
|
||||
while (token != '\n' && token != 0 && token != EOF)
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
int eof_scan(TPpContext*, TPpContext::InputSrc* in, TPpToken* ppToken) { return -1; }
|
||||
void noop(TPpContext*, TPpContext::InputSrc* in, int ch, TPpToken* ppToken) { }
|
||||
|
||||
void TPpContext::PushEofSrc()
|
||||
{
|
||||
InputSrc *in = new InputSrc;
|
||||
in->scan = eof_scan;
|
||||
in->getch = eof_scan;
|
||||
in->ungetch = noop;
|
||||
in->prev = currentInput;
|
||||
currentInput = in;
|
||||
}
|
||||
|
||||
void TPpContext::PopEofSrc()
|
||||
{
|
||||
if (currentInput->scan == eof_scan) {
|
||||
InputSrc *in = currentInput;
|
||||
currentInput = in->prev;
|
||||
delete in;
|
||||
}
|
||||
}
|
||||
|
||||
TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream *a, TPpToken* ppToken)
|
||||
TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream* a, TPpToken* ppToken, bool newLineOkay)
|
||||
{
|
||||
int token;
|
||||
TokenStream *n;
|
||||
|
|
@ -889,89 +869,79 @@ TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream *a, TPpToken* p
|
|||
token = ReadToken(a, ppToken);
|
||||
if (token == CPP_IDENTIFIER && LookUpSymbol(ppToken->atom))
|
||||
break;
|
||||
} while (token != EOF);
|
||||
if (token == EOF)
|
||||
} while (token != tInput::endOfInput);
|
||||
|
||||
if (token == tInput::endOfInput)
|
||||
return a;
|
||||
|
||||
n = new TokenStream;
|
||||
PushEofSrc();
|
||||
ReadFromTokenStream(a, 0, 0);
|
||||
while ((token = currentInput->scan(this, currentInput, ppToken)) > 0) {
|
||||
if (token == CPP_IDENTIFIER && MacroExpand(ppToken->atom, ppToken, false) == 1)
|
||||
pushInput(new tMarkerInput(this));
|
||||
pushTokenStreamInput(a, 0);
|
||||
while ((token = scanToken(ppToken)) != tMarkerInput::marker) {
|
||||
if (token == CPP_IDENTIFIER && MacroExpand(ppToken->atom, ppToken, false, newLineOkay) != 0)
|
||||
continue;
|
||||
RecordToken(n, token, ppToken);
|
||||
}
|
||||
PopEofSrc();
|
||||
popInput();
|
||||
delete a;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
//
|
||||
// Return the next token for a macro expansion, handling macro args.
|
||||
//
|
||||
// These are called through function pointers
|
||||
//
|
||||
|
||||
/*
|
||||
** return the next token for a macro expansion, handling macro args
|
||||
*/
|
||||
int TPpContext::macro_scan(TPpContext* pp, InputSrc* inInput, TPpToken* ppToken)
|
||||
int TPpContext::tMacroInput::scan(TPpToken* ppToken)
|
||||
{
|
||||
MacroInputSrc* in = (TPpContext::MacroInputSrc*)inInput;
|
||||
|
||||
int i;
|
||||
int token;
|
||||
do {
|
||||
token = pp->ReadToken(in->mac->body, ppToken);
|
||||
token = pp->ReadToken(mac->body, ppToken);
|
||||
} while (token == ' '); // handle white space in macro
|
||||
|
||||
// TODO: preprocessor: properly handle whitespace (or lack of it) between tokens when expanding
|
||||
if (token == CPP_IDENTIFIER) {
|
||||
for (i = in->mac->argc-1; i>=0; i--)
|
||||
if (in->mac->args[i] == ppToken->atom)
|
||||
int i;
|
||||
for (i = mac->argc - 1; i >= 0; i--)
|
||||
if (mac->args[i] == ppToken->atom)
|
||||
break;
|
||||
if (i >= 0) {
|
||||
pp->ReadFromTokenStream(in->args[i], ppToken->atom, 0);
|
||||
pp->pushTokenStreamInput(args[i], ppToken->atom);
|
||||
|
||||
return pp->currentInput->scan(pp, pp->currentInput, ppToken);
|
||||
return pp->scanToken(ppToken);
|
||||
}
|
||||
}
|
||||
|
||||
if (token != EOF)
|
||||
return token;
|
||||
|
||||
in->mac->busy = 0;
|
||||
pp->currentInput = in->prev;
|
||||
delete in;
|
||||
|
||||
return pp->currentInput->scan(pp, pp->currentInput, ppToken);
|
||||
if (token == endOfInput)
|
||||
mac->busy = 0;
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
// return a zero, for scanning a macro that was never defined
|
||||
int TPpContext::zero_scan(TPpContext* pp, InputSrc *inInput, TPpToken* ppToken)
|
||||
int TPpContext::tZeroInput::scan(TPpToken* ppToken)
|
||||
{
|
||||
MacroInputSrc* in = (MacroInputSrc*)inInput;
|
||||
if (done)
|
||||
return endOfInput;
|
||||
|
||||
strcpy(ppToken->name, "0");
|
||||
ppToken->ival = 0;
|
||||
ppToken->space = false;
|
||||
|
||||
// pop input
|
||||
pp->currentInput = in->prev;
|
||||
delete in;
|
||||
done = true;
|
||||
|
||||
return CPP_INTCONSTANT;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check an identifier (atom) to see if it is a macro that should be expanded.
|
||||
** If it is, and defined, push an InputSrc that will produce the appropriate expansion
|
||||
** and return 1.
|
||||
** If it is, but undefined, and expandUndef is requested, push an InputSrc that will
|
||||
** expand to 0 and return -1.
|
||||
** Otherwise, return 0.
|
||||
*/
|
||||
int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef)
|
||||
//
|
||||
// Check an identifier (atom) to see if it is a macro that should be expanded.
|
||||
// If it is, and defined, push an tInput that will produce the appropriate expansion
|
||||
// and return 1.
|
||||
// If it is, but undefined, and expandUndef is requested, push an tInput that will
|
||||
// expand to 0 and return -1.
|
||||
// Otherwise, return 0 to indicate no expansion, which is not necessarily an error.
|
||||
//
|
||||
int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool newLineOkay)
|
||||
{
|
||||
Symbol *sym = LookUpSymbol(atom);
|
||||
MacroInputSrc *in;
|
||||
int token;
|
||||
int depth = 0;
|
||||
|
||||
|
|
@ -1004,30 +974,32 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef)
|
|||
if (sym && sym->mac.busy)
|
||||
return 0;
|
||||
|
||||
// not expanding of undefined symbols
|
||||
// not expanding undefined macros
|
||||
if ((! sym || sym->mac.undef) && ! expandUndef)
|
||||
return 0;
|
||||
|
||||
in = new MacroInputSrc;
|
||||
|
||||
// 0 is the value of an undefined macro
|
||||
if ((! sym || sym->mac.undef) && expandUndef) {
|
||||
// push input
|
||||
in->scan = zero_scan;
|
||||
in->prev = currentInput;
|
||||
currentInput = in;
|
||||
|
||||
pushInput(new tZeroInput(this));
|
||||
return -1;
|
||||
}
|
||||
|
||||
tMacroInput *in = new tMacroInput(this);
|
||||
|
||||
TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error
|
||||
in->scan = macro_scan;
|
||||
in->mac = &sym->mac;
|
||||
if (sym->mac.args) {
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
if (newLineOkay) {
|
||||
while (token == '\n')
|
||||
token = scanToken(ppToken);
|
||||
}
|
||||
if (token != '(') {
|
||||
parseContext.error(loc, "expected '(' following", "macro expansion", GetAtomString(atom));
|
||||
UngetToken(token, ppToken);
|
||||
ppToken->atom = atom;
|
||||
|
||||
delete in;
|
||||
return 0;
|
||||
}
|
||||
in->args.resize(in->mac->argc);
|
||||
|
|
@ -1038,23 +1010,24 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef)
|
|||
do {
|
||||
depth = 0;
|
||||
while (1) {
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
if (token <= 0) {
|
||||
token = scanToken(ppToken);
|
||||
if (token == EOF) {
|
||||
parseContext.error(loc, "EOF in macro", "macro expansion", GetAtomString(atom));
|
||||
return 1;
|
||||
delete in;
|
||||
return 0;
|
||||
}
|
||||
if (token == '\n') {
|
||||
// TODO: Preprocessor functionality: Correctly handle new line and escaped new line, for expansions that are both in and not in another preprocessor directive
|
||||
|
||||
//if (in a pp line) {
|
||||
// parseContext.error(loc, "missing ')':", "macro expansion", GetAtomString(atom));
|
||||
// return 1;
|
||||
//}
|
||||
if (! newLineOkay) {
|
||||
parseContext.error(loc, "end of line in macro substitution:", "macro expansion", GetAtomString(atom));
|
||||
delete in;
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (token == '#') {
|
||||
parseContext.error(ppToken->loc, "unexpected '#'", "macro expansion", GetAtomString(atom));
|
||||
return 1;
|
||||
delete in;
|
||||
return 0;
|
||||
}
|
||||
if (in->mac->argc == 0 && token != ')')
|
||||
break;
|
||||
|
|
@ -1080,31 +1053,30 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef)
|
|||
parseContext.error(loc, "Too few args in Macro", "macro expansion", GetAtomString(atom));
|
||||
else if (token != ')') {
|
||||
depth=0;
|
||||
while (token >= 0 && (depth > 0 || token != ')')) {
|
||||
while (token != EOF && (depth > 0 || token != ')')) {
|
||||
if (token == ')')
|
||||
depth--;
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
token = scanToken(ppToken);
|
||||
if (token == '(')
|
||||
depth++;
|
||||
}
|
||||
|
||||
if (token <= 0) {
|
||||
if (token == EOF) {
|
||||
parseContext.error(loc, "EOF in macro", "macro expansion", GetAtomString(atom));
|
||||
return 1;
|
||||
delete in;
|
||||
return 0;
|
||||
}
|
||||
parseContext.error(loc, "Too many args in macro", "macro expansion", GetAtomString(atom));
|
||||
}
|
||||
for (int i = 0; i < in->mac->argc; i++)
|
||||
in->args[i] = PrescanMacroArg(in->args[i], ppToken);
|
||||
in->args[i] = PrescanMacroArg(in->args[i], ppToken, newLineOkay);
|
||||
}
|
||||
|
||||
/*retain the input source*/
|
||||
in->prev = currentInput;
|
||||
pushInput(in);
|
||||
sym->mac.busy = 1;
|
||||
RewindTokenStream(sym->mac.body);
|
||||
currentInput = in;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // end namespace glslang
|
||||
} // end namespace glslang
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue