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:
John Kessenich 2013-12-30 20:34:28 +00:00
parent 08d182470b
commit fcb4ed054c
16 changed files with 750 additions and 479 deletions

View File

@ -5,14 +5,22 @@ ERROR: 0:66: '#define' : Macro redefined; different substitutions: BIG
ERROR: 0:81: 'preprocessor evaluation' : bad expression ERROR: 0:81: 'preprocessor evaluation' : bad expression
ERROR: 0:81: '#if' : unexpected tokens following directive ERROR: 0:81: '#if' : unexpected tokens following directive
ERROR: 0:82: '#error' : good macro ERROR: 0:82: '#error' : good macro
ERROR: 0:89: 'macro expansion' : unexpected '#' foobar ERROR: 0:87: 'macro expansion' : end of line in macro substitution: foobar
ERROR: 0:90: 'preprocessor evaluation' : bad expression ERROR: 0:88: 'preprocessor evaluation' : can't evaluate expression
ERROR: 0:94: 'macro expansion' : unexpected '#' foobar ERROR: 0:88: 'preprocessor evaluation' : bad expression
ERROR: 0:95: 'preprocessor evaluation' : bad expression ERROR: 0:88: '#if' : unexpected tokens following directive
ERROR: 0:92: 'macro expansion' : end of line in macro substitution: foobar
ERROR: 0:93: 'preprocessor evaluation' : can't evaluate expression
ERROR: 0:93: 'preprocessor evaluation' : bad expression
ERROR: 0:93: '#if' : unexpected tokens following directive
ERROR: 0:99: 'macro expansion' : end of line in macro substitution: foobar
ERROR: 0:100: 'preprocessor evaluation' : can't evaluate expression
ERROR: 0:100: 'preprocessor evaluation' : bad expression ERROR: 0:100: 'preprocessor evaluation' : bad expression
ERROR: 0:100: '#if' : unexpected tokens following directive ERROR: 0:100: '#if' : unexpected tokens following directive
ERROR: 0:102: 'macro expansion' : unexpected '#' foobar ERROR: 0:101: 'macro expansion' : end of line in macro substitution: foobar
ERROR: 0:102: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile endif ERROR: 0:102: 'preprocessor evaluation' : can't evaluate expression
ERROR: 0:102: 'preprocessor evaluation' : bad expression
ERROR: 0:102: '#if' : unexpected tokens following directive
ERROR: 0:108: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile UNDEF ERROR: 0:108: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile UNDEF
ERROR: 0:111: '#error' : good 0 ERROR: 0:111: '#error' : good 0
ERROR: 0:115: '#error' : good 1 ERROR: 0:115: '#error' : good 1
@ -26,7 +34,7 @@ ERROR: 0:153: 'preprocessor evaluation' : undefined macro in expression not allo
ERROR: 0:156: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile UNDEF2 ERROR: 0:156: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile UNDEF2
ERROR: 0:159: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile UNDEF2 ERROR: 0:159: 'preprocessor evaluation' : undefined macro in expression not allowed in es profile UNDEF2
ERROR: 0:10002: '' : missing #endif ERROR: 0:10002: '' : missing #endif
ERROR: 27 compilation errors. No code generated. ERROR: 35 compilation errors. No code generated.
ERROR: node is still EOpNull! ERROR: node is still EOpNull!

View File

@ -1,6 +1,10 @@
cppIndent.vert cppIndent.vert
ERROR: 0:61: 'macro expansion' : Too few args in Macro FUNC
ERROR: 0:61: '' : syntax error
ERROR: 2 compilation errors. No code generated.
0:? Sequence
ERROR: node is still EOpNull!
0:5 Sequence 0:5 Sequence
0:5 move second child to first child (float) 0:5 move second child to first child (float)
0:5 'sum' (float) 0:5 'sum' (float)

View File

@ -3,7 +3,9 @@ ERROR: 0:144: '#elif' : #elif after #else
ERROR: 0:152: '#else' : #else after #else ERROR: 0:152: '#else' : #else after #else
ERROR: 0:161: '#elif' : #elif after #else ERROR: 0:161: '#elif' : #elif after #else
ERROR: 0:169: '#else' : #else after #else ERROR: 0:169: '#else' : #else after #else
ERROR: 4 compilation errors. No code generated. ERROR: 0:177: 'macro expansion' : EOF in macro FUNC
ERROR: 0:178: '' : syntax error
ERROR: 6 compilation errors. No code generated.
ERROR: node is still EOpNull! ERROR: node is still EOpNull!
@ -58,6 +60,11 @@ ERROR: node is still EOpNull!
0:133 'selected3' (int) 0:133 'selected3' (int)
0:133 Constant: 0:133 Constant:
0:133 3 (const int) 0:133 3 (const int)
0:175 Function Definition: foo985( (void)
0:175 Function Parameters:
0:175 Sequence
0:175 Constant:
0:175 6 (const int)
0:? Linker Objects 0:? Linker Objects
0:? 'sum' (float) 0:? 'sum' (float)
0:? 'selected4' (int) 0:? 'selected4' (int)

View File

@ -6,15 +6,15 @@ ERROR: 0:85: '#error' : good3
ERROR: 0:89: '#error' : good4 ERROR: 0:89: '#error' : good4
ERROR: 0:93: '#error' : good5 ERROR: 0:93: '#error' : good5
ERROR: 0:97: '#error' : good6 ERROR: 0:97: '#error' : good6
ERROR: 0:101: 'preprocessor evaluation' : expected ')' ERROR: 0:100: 'preprocessor evaluation' : expected ')'
ERROR: 0:101: '#error' : bad1 ERROR: 0:101: '#error' : bad1
ERROR: 0:104: '#if' : unexpected tokens following directive ERROR: 0:104: '#if' : unexpected tokens following directive
ERROR: 0:105: '#error' : bad2 ERROR: 0:105: '#error' : bad2
ERROR: 0:109: 'preprocessor evaluation' : expected ')' ERROR: 0:108: 'preprocessor evaluation' : expected ')'
ERROR: 0:109: '#error' : bad3 ERROR: 0:109: '#error' : bad3
ERROR: 0:112: '#if' : unexpected tokens following directive ERROR: 0:112: '#if' : unexpected tokens following directive
ERROR: 0:113: '#error' : bad4 ERROR: 0:113: '#error' : bad4
ERROR: 0:117: 'preprocessor evaluation' : expected ')' ERROR: 0:116: 'preprocessor evaluation' : expected ')'
ERROR: 0:117: '#error' : bad5 ERROR: 0:117: '#error' : bad5
ERROR: 0:120: '#if' : unexpected tokens following directive ERROR: 0:120: '#if' : unexpected tokens following directive
ERROR: 0:121: '#error' : bad6 ERROR: 0:121: '#error' : bad6
@ -74,8 +74,16 @@ ERROR: 12:20021: '#error' : line should be 20021
ERROR: 12:20046: '#define' : Macro redefined; different substitutions: SPACE_IN_MIDDLE ERROR: 12:20046: '#define' : Macro redefined; different substitutions: SPACE_IN_MIDDLE
ERROR: 12:20052: '#error' : good evaluation 1 ERROR: 12:20052: '#error' : good evaluation 1
ERROR: 12:20056: '#error' : good evaluation 2 ERROR: 12:20056: '#error' : good evaluation 2
ERROR: 12:9001: 'preprocessor evaluation' : expected ')'
ERROR: 12:9003: '#if' : unexpected tokens following directive
ERROR: 12:9015: 'macro expansion' : expected '(' following FOOOM
ERROR: 12:9015: 'FOOOM' : undeclared identifier
ERROR: 12:9015: '=' : cannot convert from 'float' to 'int'
ERROR: 12:9016: 'macro expansion' : expected '(' following FOOOM
ERROR: 12:9017: 'preprocessor evaluation' : can't evaluate expression
ERROR: 12:9017: 'preprocessor evaluation' : bad expression
ERROR: 12:10003: '' : missing #endif ERROR: 12:10003: '' : missing #endif
ERROR: 75 compilation errors. No code generated. ERROR: 83 compilation errors. No code generated.
ERROR: node is still EOpNull! ERROR: node is still EOpNull!
@ -165,6 +173,10 @@ ERROR: node is still EOpNull!
12:20034 6.000000 12:20034 6.000000
12:20034 6.000000 12:20034 6.000000
12:20034 6.000000 12:20034 6.000000
12:9012 Sequence
12:9012 move second child to first child (int)
12:9012 'R1' (int)
12:9012 'RECURSE' (int)
0:? Linker Objects 0:? Linker Objects
0:? 'sum' (float) 0:? 'sum' (float)
0:? 'linenumber' (int) 0:? 'linenumber' (int)
@ -174,6 +186,9 @@ ERROR: node is still EOpNull!
0:? 'a' (int) 0:? 'a' (int)
0:? 'n' (int) 0:? 'n' (int)
0:? 'f' (double) 0:? 'f' (double)
0:? 'RECURSE' (int)
0:? 'R1' (int)
0:? 'aoeua' (int)
0:? 'gl_VertexID' (gl_VertexId int) 0:? 'gl_VertexID' (gl_VertexId int)
0:? 'gl_InstanceID' (gl_InstanceId int) 0:? 'gl_InstanceID' (gl_InstanceId int)

View File

@ -12,7 +12,15 @@ ERROR: 0:48: '\' : illegal use of escape character
ERROR: 0:49: '$' : unexpected token ERROR: 0:49: '$' : unexpected token
ERROR: 0:50: '@' : unexpected token ERROR: 0:50: '@' : unexpected token
ERROR: 0:55: '#error' : good continuation ERROR: 0:55: '#error' : good continuation
ERROR: 12 compilation errors. No code generated. WARNING: 0:62: 'line continuation' : used at end of comment; the following line is still part of the comment
ERROR: 0:111: 'macro expansion' : end of line in macro substitution: FOOM
ERROR: 0:112: 'preprocessor evaluation' : can't evaluate expression
ERROR: 0:112: '#if' : unexpected tokens following directive
ERROR: 0:117: 'macro expansion' : end of line in macro substitution: FOOM
ERROR: 0:118: 'preprocessor evaluation' : can't evaluate expression
ERROR: 0:118: '#if' : unexpected tokens following directive
ERROR: 0:147: '' : syntax error
ERROR: 19 compilation errors. No code generated.
ERROR: node is still EOpNull! ERROR: node is still EOpNull!
@ -72,6 +80,84 @@ ERROR: node is still EOpNull!
0:50 'q4' (highp int) 0:50 'q4' (highp int)
0:50 Constant: 0:50 Constant:
0:50 1 (const int) 0:50 1 (const int)
0:65 Sequence
0:65 move second child to first child (highp int)
0:65 'abdece' (highp int)
0:65 Constant:
0:65 10 (const int)
0:66 Sequence
0:66 move second child to first child (highp int)
0:66 'aoeuntaoehu' (highp int)
0:66 'abdece' (highp int)
0:74 Sequence
0:74 move second child to first child (highp float)
0:74 'funkyf' (highp float)
0:75 Constant:
0:75 12300000000000000.000000
0:85 Sequence
0:84 move second child to first child (highp int)
0:84 'funkyh' (highp int)
0:86 Constant:
0:86 244 (const int)
0:91 Sequence
0:91 move second child to first child (highp int)
0:91 'funkyo' (highp int)
0:92 Constant:
0:92 34 (const int)
0:96 Sequence
0:96 move second child to first child (highp int)
0:96 'c' (highp int)
0:97 Constant:
0:97 11 (const int)
0:98 Sequence
0:98 move second child to first child (highp int)
0:98 'd' (highp int)
0:98 Constant:
0:98 12 (const int)
0:107 Sequence
0:107 move second child to first child (highp int)
0:107 'bar103' (highp int)
0:107 Constant:
0:107 17 (const int)
0:113 Sequence
0:113 move second child to first child (highp int)
0:113 'bar104' (highp int)
0:113 Constant:
0:113 19 (const int)
0:119 Sequence
0:119 move second child to first child (highp int)
0:119 'bar105' (highp int)
0:119 Constant:
0:119 19 (const int)
0:122 Sequence
0:122 move second child to first child (highp int)
0:122 'bar106' (highp int)
0:122 Constant:
0:122 12 (const int)
0:123 Sequence
0:123 move second child to first child (highp int)
0:123 'bar107' (highp int)
0:128 Constant:
0:128 5 (const int)
0:131 Function Definition: foo203209409( (void)
0:131 Function Parameters:
0:134 Sequence
0:134 add second child into first child (highp int)
0:133 'bar107' (highp int)
0:134 Constant:
0:134 37 (const int)
0:135 multiply second child into first child (highp int)
0:135 'bar107' (highp int)
0:136 Constant:
0:136 38 (const int)
0:137 divide second child into first child (highp int)
0:137 'bar107' (highp int)
0:138 Constant:
0:138 39 (const int)
0:139 add (highp int)
0:139 'bar107' (highp int)
0:140 Constant:
0:140 41 (const int)
0:? Linker Objects 0:? Linker Objects
0:? 'foo' (highp float) 0:? 'foo' (highp float)
0:? 'goodDecl' (highp int) 0:? 'goodDecl' (highp int)
@ -83,6 +169,18 @@ ERROR: node is still EOpNull!
0:? 'q2' (highp int) 0:? 'q2' (highp int)
0:? 'q3' (highp int) 0:? 'q3' (highp int)
0:? 'q4' (highp int) 0:? 'q4' (highp int)
0:? 'abdece' (highp int)
0:? 'aoeuntaoehu' (highp int)
0:? 'funkyf' (highp float)
0:? 'funkyh' (highp int)
0:? 'funkyo' (highp int)
0:? 'c' (highp int)
0:? 'd' (highp int)
0:? 'bar103' (highp int)
0:? 'bar104' (highp int)
0:? 'bar105' (highp int)
0:? 'bar106' (highp int)
0:? 'bar107' (highp int)
0:? 'gl_VertexID' (gl_VertexId highp int) 0:? 'gl_VertexID' (gl_VertexId highp int)
0:? 'gl_InstanceID' (gl_InstanceId highp int) 0:? 'gl_InstanceID' (gl_InstanceId highp int)

View File

@ -55,3 +55,7 @@ sum += 900000000.0;
// sum should be 980600301.0 // sum should be 980600301.0
gl_Position = vec4(sum); gl_Position = vec4(sum);
} }
#define FUNC(a,b) a+b
// needs to be last test in file due to syntax error
void foo986(){ FUNC( (((2)))), 4); } // ERROR, too many )

View File

@ -170,3 +170,8 @@ int;
int; int;
#endif #endif
#endif #endif
#define FUNC(a,b) a+b
void foo985(){ FUNC( (((2))), ((3),4)); }
// needs to be last test in file
void foo987(){ FUNC(((); } // ERROR, EOF in argument

View File

@ -306,6 +306,26 @@ void foo234()
#error good evaluation 2 #error good evaluation 2
#endif #endif
// ERRORS...
#line 9000
#if defined(OUNH
#endif
#if defined OUNH)
#endif
// recursion (okay)
#define RECURSE RECURSE
int RECURSE;
#define R2 R1
#define R1 R2
#undef RECURSE
int R1 = RECURSE;
#define FOOOM(a,b) a + b
int aoeua = FOOOM;
#if FOOOM
#endif
#line 10000 #line 10000
#if 1 #if 1
#else #else

View File

@ -54,4 +54,95 @@ D;
# \ # \
error good continuation error good continuation
#define AA a \ b #define AA1 a \ b
#define AA2 a \\ b
#define AA3 a \\\ b
#define AA4 a \\\\ b
// anoetuh nonaetu \\\\\\
still in comment
int abdece = 10;
int aoeuntaoehu = abd\
\
\
\
\
\
ece;
float funkyf = \
.\
1\
2\
3\
e\
+\
1\
7\
;\
int funkyh\
=\
0\
x\
f\
4\
;
int funkyo =\
0\
4\
2\
;
int c = \
11;
int d = 1\
2;
#define FOOM(a,b) a + b
#if FO\
OM(2\
,\
3)
int bar103 = 17;
#endif
// ERROR
#if FOOM(2,
3)
int bar104 = 19;
#endif
// ERROR
#if FOOM(
2,3)
int bar105 = 19;
#endif
int bar106 = FOOM(5,7);
int bar107 = FOOM // okay
(
2
,
3
)
;
void foo203209409()
{
bar107 \
+= 37;
bar107 *\
= 38;
bar107 /=\
39;
bar107 +\
41;
}
void foo230920394()
{
// syntax error
bar107 +\
= 42;
}

View File

@ -9,5 +9,5 @@
// source have to figure out how to create revision.h just to get a build // source have to figure out how to create revision.h just to get a build
// going. However, if it is not updated, it can be a version behind. // going. However, if it is not updated, it can be a version behind.
#define GLSLANG_REVISION "24569" #define GLSLANG_REVISION "24594"
#define GLSLANG_DATE "2013/12/18 11:47:12" #define GLSLANG_DATE "2013/12/20 11:36:27"

View File

@ -132,7 +132,7 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
Symbol *symb; Symbol *symb;
// get macro name // get macro name
int token = currentInput->scan(this, currentInput, ppToken); int token = scanToken(ppToken);
if (token != CPP_IDENTIFIER) { if (token != CPP_IDENTIFIER) {
parseContext.error(ppToken->loc, "must be followed by macro name", "#define", ""); parseContext.error(ppToken->loc, "must be followed by macro name", "#define", "");
return token; return token;
@ -145,12 +145,12 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
} }
// gather parameters to the macro, between (...) // gather parameters to the macro, between (...)
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (token == '(' && ! ppToken->space) { if (token == '(' && ! ppToken->space) {
int argc = 0; int argc = 0;
int args[maxMacroArgs]; int args[maxMacroArgs];
do { do {
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (argc == 0 && token == ')') if (argc == 0 && token == ')')
break; break;
if (token != CPP_IDENTIFIER) { if (token != CPP_IDENTIFIER) {
@ -173,7 +173,7 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
else else
parseContext.error(ppToken->loc, "too many macro parameters", "#define", ""); parseContext.error(ppToken->loc, "too many macro parameters", "#define", "");
} }
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
} while (token == ','); } while (token == ',');
if (token != ')') { if (token != ')') {
parseContext.error(ppToken->loc, "missing parenthesis", "#define", ""); parseContext.error(ppToken->loc, "missing parenthesis", "#define", "");
@ -183,7 +183,7 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
mac.argc = argc; mac.argc = argc;
mac.args = (int*)mem_Alloc(pool, argc * sizeof(int)); mac.args = (int*)mem_Alloc(pool, argc * sizeof(int));
memcpy(mac.args, args, 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 // record the definition of the macro
@ -191,7 +191,7 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
mac.body = new TokenStream; mac.body = new TokenStream;
while (token != '\n') { while (token != '\n') {
RecordToken(mac.body, token, ppToken); RecordToken(mac.body, token, ppToken);
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (token != '\n' && ppToken->space) if (token != '\n' && ppToken->space)
RecordToken(mac.body, ' ', ppToken); RecordToken(mac.body, ' ', ppToken);
} }
@ -238,7 +238,7 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
// Handle #undef // Handle #undef
int TPpContext::CPPundef(TPpToken* ppToken) int TPpContext::CPPundef(TPpToken* ppToken)
{ {
int token = currentInput->scan(this, currentInput, ppToken); int token = scanToken(ppToken);
Symbol *symb; Symbol *symb;
if (token != CPP_IDENTIFIER) { if (token != CPP_IDENTIFIER) {
parseContext.error(ppToken->loc, "must be followed by macro name", "#undef", ""); parseContext.error(ppToken->loc, "must be followed by macro name", "#undef", "");
@ -246,14 +246,14 @@ int TPpContext::CPPundef(TPpToken* ppToken)
return token; 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"); parseContext.reservedPpErrorCheck(ppToken->loc, name, "#undef");
symb = LookUpSymbol(ppToken->atom); symb = LookUpSymbol(ppToken->atom);
if (symb) { if (symb) {
symb->mac.undef = 1; symb->mac.undef = 1;
} }
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (token != '\n') if (token != '\n')
parseContext.error(ppToken->loc, "can only be followed by a single macro name", "#undef", ""); 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 atom;
int depth = 0; int depth = 0;
int token = currentInput->scan(this, currentInput, ppToken); int token = scanToken(ppToken);
while (token != EOF) { while (token != EOF) {
if (token != '#') { if (token != '#') {
while (token != '\n' && token != EOF) while (token != '\n' && token != EOF)
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (token == EOF) if (token == EOF)
return EOF; return EOF;
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
continue; continue;
} }
if ((token = currentInput->scan(this, currentInput, ppToken)) != CPP_IDENTIFIER) if ((token = scanToken(ppToken)) != CPP_IDENTIFIER)
continue; continue;
atom = ppToken->atom; atom = ppToken->atom;
@ -292,7 +292,7 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
ifdepth++; ifdepth++;
elsetracker++; elsetracker++;
} else if (atom == endifAtom) { } else if (atom == endifAtom) {
token = extraTokenCheck(atom, ppToken, currentInput->scan(this, currentInput, ppToken)); token = extraTokenCheck(atom, ppToken, scanToken(ppToken));
elseSeen[elsetracker] = false; elseSeen[elsetracker] = false;
--elsetracker; --elsetracker;
if (depth == 0) { if (depth == 0) {
@ -306,7 +306,7 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
} else if (matchelse && depth == 0) { } else if (matchelse && depth == 0) {
if (atom == elseAtom) { if (atom == elseAtom) {
elseSeen[elsetracker] = true; 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 // found the #else we are looking for
break; break;
} else if (atom == elifAtom) { } else if (atom == elifAtom) {
@ -327,7 +327,7 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
parseContext.error(ppToken->loc, "#else after #else", "#else", ""); parseContext.error(ppToken->loc, "#else after #else", "#else", "");
else else
elseSeen[elsetracker] = true; elseSeen[elsetracker] = true;
token = extraTokenCheck(atom, ppToken, currentInput->scan(this, currentInput, ppToken)); token = extraTokenCheck(atom, ppToken, scanToken(ppToken));
} else if (atom == elifAtom) { } else if (atom == elifAtom) {
if (elseSeen[elsetracker]) if (elseSeen[elsetracker])
parseContext.error(ppToken->loc, "#elif after #else", "#elif", ""); 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, ""); parseContext.error(ppToken->loc, message, label, "");
while (token != '\n') while (token != '\n')
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
} }
return token; return token;
@ -438,16 +438,17 @@ struct TUnop {
int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken* ppToken) 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 (token == CPP_IDENTIFIER) {
if (ppToken->atom == definedAtom) { if (ppToken->atom == definedAtom) {
bool needclose = 0; bool needclose = 0;
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (token == '(') { if (token == '(') {
needclose = true; needclose = true;
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
} }
if (token != CPP_IDENTIFIER) { 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; err = true;
res = 0; res = 0;
@ -455,16 +456,16 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
} }
Symbol* s; Symbol* s;
res = (s = LookUpSymbol(ppToken->atom)) ? !s->mac.undef : 0; res = (s = LookUpSymbol(ppToken->atom)) ? !s->mac.undef : 0;
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (needclose) { if (needclose) {
if (token != ')') { if (token != ')') {
parseContext.error(ppToken->loc, "#else after #else", "preprocessor evaluation", ""); parseContext.error(loc, "expected ')'", "preprocessor evaluation", "");
err = true; err = true;
res = 0; res = 0;
return token; return token;
} }
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
} }
} else { } else {
token = evalToToken(token, shortCircuit, res, err, ppToken); 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) { } else if (token == CPP_INTCONSTANT) {
res = ppToken->ival; res = ppToken->ival;
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
} else if (token == '(') { } else if (token == '(') {
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
token = eval(token, MIN_PRECEDENCE, shortCircuit, res, err, ppToken); token = eval(token, MIN_PRECEDENCE, shortCircuit, res, err, ppToken);
if (! err) { if (! err) {
if (token != ')') { if (token != ')') {
parseContext.error(ppToken->loc, "expected ')'", "preprocessor evaluation", ""); parseContext.error(loc, "expected ')'", "preprocessor evaluation", "");
err = true; err = true;
res = 0; res = 0;
return token; return token;
} }
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
} }
} else { } else {
int op; int op;
@ -493,11 +494,11 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
break; break;
} }
if (op >= 0) { if (op >= 0) {
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
token = eval(token, UNARY, shortCircuit, res, err, ppToken); token = eval(token, UNARY, shortCircuit, res, err, ppToken);
res = unop[op].op(res); res = unop[op].op(res);
} else { } else {
parseContext.error(ppToken->loc, "bad expression", "preprocessor evaluation", ""); parseContext.error(loc, "bad expression", "preprocessor evaluation", "");
err = true; err = true;
res = 0; res = 0;
@ -528,7 +529,7 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
shortCircuit = true; shortCircuit = true;
} }
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
token = eval(token, binop[op].precedence, shortCircuit, res, err, ppToken); token = eval(token, binop[op].precedence, shortCircuit, res, err, ppToken);
res = binop[op].op(leftSide, res); 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) int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken* ppToken)
{ {
while (token == CPP_IDENTIFIER && ppToken->atom != definedAtom) { 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) { if (macroReturn == 0) {
parseContext.error(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", ""); parseContext.error(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", "");
err = true; err = true;
res = 0; res = 0;
token = scanToken(ppToken);
break; break;
} }
if (macroReturn == -1) { 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); parseContext.error(ppToken->loc, message, "preprocessor evaluation", name);
} }
} }
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
} }
return token; return token;
@ -566,7 +568,7 @@ int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, T
// Handle #if // Handle #if
int TPpContext::CPPif(TPpToken* ppToken) int TPpContext::CPPif(TPpToken* ppToken)
{ {
int token = currentInput->scan(this, currentInput, ppToken); int token = scanToken(ppToken);
elsetracker++; elsetracker++;
if (! ifdepth++) if (! ifdepth++)
ifloc = ppToken->loc; ifloc = ppToken->loc;
@ -587,7 +589,7 @@ int TPpContext::CPPif(TPpToken* ppToken)
// Handle #ifdef // Handle #ifdef
int TPpContext::CPPifdef(int defined, TPpToken* ppToken) int TPpContext::CPPifdef(int defined, TPpToken* ppToken)
{ {
int token = currentInput->scan(this, currentInput, ppToken); int token = scanToken(ppToken);
int name = ppToken->atom; int name = ppToken->atom;
if (++ifdepth > maxIfNesting) { if (++ifdepth > maxIfNesting) {
parseContext.error(ppToken->loc, "maximum nesting depth exceeded", "#ifdef", ""); 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", ""); parseContext.error(ppToken->loc, "must be followed by macro name", "#ifndef", "");
} else { } else {
Symbol *s = LookUpSymbol(name); Symbol *s = LookUpSymbol(name);
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (token != '\n') { if (token != '\n') {
parseContext.error(ppToken->loc, "unexpected tokens following #ifdef directive - expected a newline", "#ifdef", ""); parseContext.error(ppToken->loc, "unexpected tokens following #ifdef directive - expected a newline", "#ifdef", "");
while (token != '\n') while (token != '\n')
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
} }
if (((s && !s->mac.undef) ? 1 : 0) != defined) if (((s && !s->mac.undef) ? 1 : 0) != defined)
token = CPPelse(1, ppToken); token = CPPelse(1, ppToken);
@ -621,7 +623,7 @@ int TPpContext::CPPline(TPpToken* ppToken)
// "#line line // "#line line
// "#line line source-string-number" // "#line line source-string-number"
int token = currentInput->scan(this, currentInput, ppToken); int token = scanToken(ppToken);
if (token == '\n') { if (token == '\n') {
parseContext.error(ppToken->loc, "must by followed by an integral literal", "#line", ""); parseContext.error(ppToken->loc, "must by followed by an integral literal", "#line", "");
return token; return token;
@ -651,7 +653,7 @@ int TPpContext::CPPline(TPpToken* ppToken)
// Handle #error // Handle #error
int TPpContext::CPPerror(TPpToken* ppToken) int TPpContext::CPPerror(TPpToken* ppToken)
{ {
int token = currentInput->scan(this, currentInput, ppToken); int token = scanToken(ppToken);
std::string message; std::string message;
TSourceLoc loc = ppToken->loc; TSourceLoc loc = ppToken->loc;
@ -665,7 +667,7 @@ int TPpContext::CPPerror(TPpToken* ppToken)
message.append(GetAtomString(token)); message.append(GetAtomString(token));
} }
message.append(" "); 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!!!! //store this msg into the shader's information log..set the Compile Error flag!!!!
parseContext.error(loc, message.c_str(), "#error", ""); parseContext.error(loc, message.c_str(), "#error", "");
@ -683,7 +685,7 @@ int TPpContext::CPPpragma(TPpToken* ppToken)
TVector<TString> tokens; TVector<TString> tokens;
TSourceLoc loc = ppToken->loc; // because we go to the next line before processing 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) { while (token != '\n' && token != EOF) {
switch (token) { switch (token) {
case CPP_IDENTIFIER: case CPP_IDENTIFIER:
@ -702,7 +704,7 @@ int TPpContext::CPPpragma(TPpToken* ppToken)
SrcStrName[1] = '\0'; SrcStrName[1] = '\0';
tokens.push_back(SrcStrName); tokens.push_back(SrcStrName);
} }
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
} }
if (token == EOF) 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 // #version: This is just for error checking: the version and profile are decided before preprocessing starts
int TPpContext::CPPversion(TPpToken* ppToken) int TPpContext::CPPversion(TPpToken* ppToken)
{ {
int token = currentInput->scan(this, currentInput, ppToken); int token = scanToken(ppToken);
if (errorOnVersion || versionSeen) if (errorOnVersion || versionSeen)
parseContext.error(ppToken->loc, "must occur first in shader", "#version", ""); parseContext.error(ppToken->loc, "must occur first in shader", "#version", "");
@ -733,7 +735,7 @@ int TPpContext::CPPversion(TPpToken* ppToken)
ppToken->ival = atoi(ppToken->name); ppToken->ival = atoi(ppToken->name);
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (token == '\n') if (token == '\n')
return token; return token;
@ -743,7 +745,7 @@ int TPpContext::CPPversion(TPpToken* ppToken)
ppToken->atom != esAtom) ppToken->atom != esAtom)
parseContext.error(ppToken->loc, "bad profile name; use es, core, or compatibility", "#version", ""); 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') if (token == '\n')
return token; return token;
@ -757,7 +759,7 @@ int TPpContext::CPPversion(TPpToken* ppToken)
// Handle #extension // Handle #extension
int TPpContext::CPPextension(TPpToken* ppToken) int TPpContext::CPPextension(TPpToken* ppToken)
{ {
int token = currentInput->scan(this, currentInput, ppToken); int token = scanToken(ppToken);
char extensionName[80]; char extensionName[80];
if (token=='\n') { if (token=='\n') {
@ -770,13 +772,13 @@ int TPpContext::CPPextension(TPpToken* ppToken)
strcpy(extensionName, GetAtomString(ppToken->atom)); strcpy(extensionName, GetAtomString(ppToken->atom));
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (token != ':') { if (token != ':') {
parseContext.error(ppToken->loc, "':' missing after extension name", "#extension", ""); parseContext.error(ppToken->loc, "':' missing after extension name", "#extension", "");
return token; return token;
} }
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (token != CPP_IDENTIFIER) { if (token != CPP_IDENTIFIER) {
parseContext.error(ppToken->loc, "behavior for extension not specified", "#extension", ""); parseContext.error(ppToken->loc, "behavior for extension not specified", "#extension", "");
return token; return token;
@ -784,7 +786,7 @@ int TPpContext::CPPextension(TPpToken* ppToken)
parseContext.updateExtensionBehavior(extensionName, GetAtomString(ppToken->atom)); parseContext.updateExtensionBehavior(extensionName, GetAtomString(ppToken->atom));
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (token == '\n') if (token == '\n')
return token; return token;
else else
@ -795,7 +797,7 @@ int TPpContext::CPPextension(TPpToken* ppToken)
int TPpContext::readCPPline(TPpToken* ppToken) int TPpContext::readCPPline(TPpToken* ppToken)
{ {
int token = currentInput->scan(this, currentInput, ppToken); int token = scanToken(ppToken);
bool isVersion = false; bool isVersion = false;
if (token == CPP_IDENTIFIER) { if (token == CPP_IDENTIFIER) {
@ -807,7 +809,7 @@ int TPpContext::readCPPline(TPpToken* ppToken)
elsetracker[elseSeen] = true; elsetracker[elseSeen] = true;
if (! ifdepth) if (! ifdepth)
parseContext.error(ppToken->loc, "mismatched statements", "#else", ""); 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); token = CPPelse(0, ppToken);
} else if (ppToken->atom == elifAtom) { } else if (ppToken->atom == elifAtom) {
if (! ifdepth) if (! ifdepth)
@ -815,9 +817,9 @@ int TPpContext::readCPPline(TPpToken* ppToken)
if (elseSeen[elsetracker]) if (elseSeen[elsetracker])
parseContext.error(ppToken->loc, "#elif after #else", "#elif", ""); parseContext.error(ppToken->loc, "#elif after #else", "#elif", "");
// this token is really a dont care, but we still need to eat the tokens // 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') while (token != '\n')
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
token = CPPelse(0, ppToken); token = CPPelse(0, ppToken);
} else if (ppToken->atom == endifAtom) { } else if (ppToken->atom == endifAtom) {
elseSeen[elsetracker] = false; elseSeen[elsetracker] = false;
@ -826,7 +828,7 @@ int TPpContext::readCPPline(TPpToken* ppToken)
parseContext.error(ppToken->loc, "mismatched statements", "#endif", ""); parseContext.error(ppToken->loc, "mismatched statements", "#endif", "");
else else
--ifdepth; --ifdepth;
token = extraTokenCheck(endifAtom, ppToken, currentInput->scan(this, currentInput, ppToken)); token = extraTokenCheck(endifAtom, ppToken, scanToken(ppToken));
} else if (ppToken->atom == ifAtom) { } else if (ppToken->atom == ifAtom) {
token = CPPif (ppToken); token = CPPif (ppToken);
} else if (ppToken->atom == ifdefAtom) { } else if (ppToken->atom == ifdefAtom) {
@ -849,38 +851,16 @@ int TPpContext::readCPPline(TPpToken* ppToken)
} else { } else {
parseContext.error(ppToken->loc, "invalid directive:", "#", GetAtomString(ppToken->atom)); 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", "#", ""); parseContext.error(ppToken->loc, "invalid directive", "#", "");
while (token != '\n' && token != 0 && token != EOF) while (token != '\n' && token != 0 && token != EOF)
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
return token; return token;
} }
int eof_scan(TPpContext*, TPpContext::InputSrc* in, TPpToken* ppToken) { return -1; } TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream* a, TPpToken* ppToken, bool newLineOkay)
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)
{ {
int token; int token;
TokenStream *n; TokenStream *n;
@ -889,89 +869,79 @@ TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream *a, TPpToken* p
token = ReadToken(a, ppToken); token = ReadToken(a, ppToken);
if (token == CPP_IDENTIFIER && LookUpSymbol(ppToken->atom)) if (token == CPP_IDENTIFIER && LookUpSymbol(ppToken->atom))
break; break;
} while (token != EOF); } while (token != tInput::endOfInput);
if (token == EOF)
if (token == tInput::endOfInput)
return a; return a;
n = new TokenStream; n = new TokenStream;
PushEofSrc(); pushInput(new tMarkerInput(this));
ReadFromTokenStream(a, 0, 0); pushTokenStreamInput(a, 0);
while ((token = currentInput->scan(this, currentInput, ppToken)) > 0) { while ((token = scanToken(ppToken)) != tMarkerInput::marker) {
if (token == CPP_IDENTIFIER && MacroExpand(ppToken->atom, ppToken, false) == 1) if (token == CPP_IDENTIFIER && MacroExpand(ppToken->atom, ppToken, false, newLineOkay) != 0)
continue; continue;
RecordToken(n, token, ppToken); RecordToken(n, token, ppToken);
} }
PopEofSrc(); popInput();
delete a; delete a;
return n; return n;
} }
// //
// These are called through function pointers // Return the next token for a macro expansion, handling macro args.
// //
int TPpContext::tMacroInput::scan(TPpToken* ppToken)
/*
** return the next token for a macro expansion, handling macro args
*/
int TPpContext::macro_scan(TPpContext* pp, InputSrc* inInput, TPpToken* ppToken)
{ {
MacroInputSrc* in = (TPpContext::MacroInputSrc*)inInput;
int i;
int token; int token;
do { do {
token = pp->ReadToken(in->mac->body, ppToken); token = pp->ReadToken(mac->body, ppToken);
} while (token == ' '); // handle white space in macro } while (token == ' '); // handle white space in macro
// TODO: preprocessor: properly handle whitespace (or lack of it) between tokens when expanding // TODO: preprocessor: properly handle whitespace (or lack of it) between tokens when expanding
if (token == CPP_IDENTIFIER) { if (token == CPP_IDENTIFIER) {
for (i = in->mac->argc-1; i>=0; i--) int i;
if (in->mac->args[i] == ppToken->atom) for (i = mac->argc - 1; i >= 0; i--)
if (mac->args[i] == ppToken->atom)
break; break;
if (i >= 0) { 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) if (token == endOfInput)
mac->busy = 0;
return token; return token;
in->mac->busy = 0;
pp->currentInput = in->prev;
delete in;
return pp->currentInput->scan(pp, pp->currentInput, ppToken);
} }
// return a zero, for scanning a macro that was never defined // 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"); strcpy(ppToken->name, "0");
ppToken->ival = 0; ppToken->ival = 0;
ppToken->space = false; ppToken->space = false;
done = true;
// pop input
pp->currentInput = in->prev;
delete in;
return CPP_INTCONSTANT; return CPP_INTCONSTANT;
} }
/* //
** Check an identifier (atom) to see if it is a macro that should be expanded. // 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 // If it is, and defined, push an tInput that will produce the appropriate expansion
** and return 1. // and return 1.
** If it is, but undefined, and expandUndef is requested, push an InputSrc that will // If it is, but undefined, and expandUndef is requested, push an tInput that will
** expand to 0 and return -1. // expand to 0 and return -1.
** Otherwise, return 0. // Otherwise, return 0 to indicate no expansion, which is not necessarily an error.
*/ //
int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef) int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool newLineOkay)
{ {
Symbol *sym = LookUpSymbol(atom); Symbol *sym = LookUpSymbol(atom);
MacroInputSrc *in;
int token; int token;
int depth = 0; int depth = 0;
@ -1004,30 +974,32 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef)
if (sym && sym->mac.busy) if (sym && sym->mac.busy)
return 0; return 0;
// not expanding of undefined symbols // not expanding undefined macros
if ((! sym || sym->mac.undef) && ! expandUndef) if ((! sym || sym->mac.undef) && ! expandUndef)
return 0; return 0;
in = new MacroInputSrc; // 0 is the value of an undefined macro
if ((! sym || sym->mac.undef) && expandUndef) { if ((! sym || sym->mac.undef) && expandUndef) {
// push input pushInput(new tZeroInput(this));
in->scan = zero_scan;
in->prev = currentInput;
currentInput = in;
return -1; return -1;
} }
tMacroInput *in = new tMacroInput(this);
TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error
in->scan = macro_scan;
in->mac = &sym->mac; in->mac = &sym->mac;
if (sym->mac.args) { if (sym->mac.args) {
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (newLineOkay) {
while (token == '\n')
token = scanToken(ppToken);
}
if (token != '(') { if (token != '(') {
parseContext.error(loc, "expected '(' following", "macro expansion", GetAtomString(atom));
UngetToken(token, ppToken); UngetToken(token, ppToken);
ppToken->atom = atom; ppToken->atom = atom;
delete in;
return 0; return 0;
} }
in->args.resize(in->mac->argc); in->args.resize(in->mac->argc);
@ -1038,23 +1010,24 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef)
do { do {
depth = 0; depth = 0;
while (1) { while (1) {
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (token <= 0) { if (token == EOF) {
parseContext.error(loc, "EOF in macro", "macro expansion", GetAtomString(atom)); parseContext.error(loc, "EOF in macro", "macro expansion", GetAtomString(atom));
return 1; delete in;
return 0;
} }
if (token == '\n') { 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 (! newLineOkay) {
parseContext.error(loc, "end of line in macro substitution:", "macro expansion", GetAtomString(atom));
//if (in a pp line) { delete in;
// parseContext.error(loc, "missing ')':", "macro expansion", GetAtomString(atom)); return 0;
// return 1; }
//}
continue; continue;
} }
if (token == '#') { if (token == '#') {
parseContext.error(ppToken->loc, "unexpected '#'", "macro expansion", GetAtomString(atom)); parseContext.error(ppToken->loc, "unexpected '#'", "macro expansion", GetAtomString(atom));
return 1; delete in;
return 0;
} }
if (in->mac->argc == 0 && token != ')') if (in->mac->argc == 0 && token != ')')
break; break;
@ -1080,29 +1053,28 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef)
parseContext.error(loc, "Too few args in Macro", "macro expansion", GetAtomString(atom)); parseContext.error(loc, "Too few args in Macro", "macro expansion", GetAtomString(atom));
else if (token != ')') { else if (token != ')') {
depth=0; depth=0;
while (token >= 0 && (depth > 0 || token != ')')) { while (token != EOF && (depth > 0 || token != ')')) {
if (token == ')') if (token == ')')
depth--; depth--;
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
if (token == '(') if (token == '(')
depth++; depth++;
} }
if (token <= 0) { if (token == EOF) {
parseContext.error(loc, "EOF in macro", "macro expansion", GetAtomString(atom)); 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)); parseContext.error(loc, "Too many args in macro", "macro expansion", GetAtomString(atom));
} }
for (int i = 0; i < in->mac->argc; i++) 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*/ pushInput(in);
in->prev = currentInput;
sym->mac.busy = 1; sym->mac.busy = 1;
RewindTokenStream(sym->mac.body); RewindTokenStream(sym->mac.body);
currentInput = in;
return 1; return 1;
} }

View File

@ -84,7 +84,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace glslang { namespace glslang {
TPpContext::TPpContext(TParseContext& pc) : TPpContext::TPpContext(TParseContext& pc) :
preamble(0), strings(0), parseContext(pc) preamble(0), strings(0), parseContext(pc), inComment(false)
{ {
InitAtomTable(); InitAtomTable();
InitScanner(this); InitScanner(this);
@ -143,17 +143,18 @@ TPpContext::~TPpContext()
delete it->second->mac.body; delete it->second->mac.body;
mem_FreePool(pool); mem_FreePool(pool);
delete [] preamble; delete [] preamble;
// free up the inputStack
while (! inputStack.empty())
popInput();
} }
void TPpContext::setInput(TInputScanner& input, bool versionWillBeError) void TPpContext::setInput(TInputScanner& input, bool versionWillBeError)
{ {
StringInputSrc* in = new StringInputSrc; assert(inputStack.size() == 0);
in->input = &input;
in->scan = sourceScan; pushInput(new tStringInput(this, input));
in->getch = (int (*)(TPpContext*, InputSrc *, TPpToken *))sourceGetCh;
in->ungetch = (void (*)(TPpContext*, InputSrc *, int, TPpToken *))sourceUngetCh;
in->prev = currentInput;
currentInput = in;
errorOnVersion = versionWillBeError; errorOnVersion = versionWillBeError;
versionSeen = false; versionSeen = false;
} }

View File

@ -121,19 +121,37 @@ public:
virtual ~TPpContext(); virtual ~TPpContext();
void setPreamble(const char* preamble, size_t length); void setPreamble(const char* preamble, size_t length);
void setInput(TInputScanner& input, bool versionWillBeError);
const char* tokenize(TPpToken* ppToken); const char* tokenize(TPpToken* ppToken);
// TODO: preprocessor simplification: this should be a base class, not a set of function pointers class tInput {
struct InputSrc { public:
InputSrc() : prev(0), scan(0), getch(0), ungetch(0) { } tInput(TPpContext* p) : done(false), pp(p) { }
struct InputSrc *prev; virtual ~tInput() { }
int (*scan)(TPpContext*, struct InputSrc *, TPpToken *);
int (*getch)(TPpContext*, struct InputSrc *, TPpToken *); virtual int scan(TPpToken*) = 0;
void (*ungetch)(TPpContext*, struct InputSrc *, int, TPpToken *); virtual int getch() = 0;
virtual void ungetch() = 0;
static const int endOfInput = -2;
protected:
bool done;
TPpContext* pp;
}; };
void setInput(TInputScanner& input, bool versionWillBeError);
void TPpContext::pushInput(tInput* in)
{
inputStack.push_back(in);
}
void TPpContext::popInput()
{
delete inputStack.back();
inputStack.pop_back();
}
struct TokenStream { struct TokenStream {
TokenStream() : current(0) { } TokenStream() : current(0) { }
TVector<unsigned char> data; TVector<unsigned char> data;
@ -145,7 +163,6 @@ public:
uintptr_t free, end; uintptr_t free, end;
size_t chunksize; size_t chunksize;
uintptr_t alignmask; uintptr_t alignmask;
struct cleanup *cleanup;
}; };
// //
@ -184,10 +201,31 @@ protected:
int currentString; // which string we're currently parsing (-1 for preamble) int currentString; // which string we're currently parsing (-1 for preamble)
// Scanner data: // Scanner data:
int mostRecentToken; // Most recent token seen by the scanner
int previous_token; int previous_token;
TParseContext& parseContext; TParseContext& parseContext;
// Get the next token from *stack* of input sources, popping input sources
// that are out of tokens, down until an input sources is found that has a token.
// Return EOF when there are no more tokens to be found by doing this.
int scanToken(TPpToken* ppToken)
{
int token = EOF;
while (! inputStack.empty()) {
token = inputStack.back()->scan(ppToken);
if (token != tInput::endOfInput)
break;
popInput();
}
if (token == tInput::endOfInput)
return EOF;
return token;
}
int getChar() { return inputStack.back()->getch(); }
void ungetChar() { inputStack.back()->ungetch(); }
static const int maxMacroArgs = 64; static const int maxMacroArgs = 64;
static const int maxIfNesting = 64; static const int maxIfNesting = 64;
@ -196,18 +234,47 @@ protected:
int elsetracker; // #if-#else and #endif constructs...Counter. int elsetracker; // #if-#else and #endif constructs...Counter.
const char *ErrMsg; const char *ErrMsg;
struct MacroInputSrc : public InputSrc { class tMacroInput : public tInput {
MacroInputSrc() : mac(0) { } public:
virtual ~MacroInputSrc() tMacroInput(TPpContext* pp) : tInput(pp) { }
virtual ~tMacroInput()
{ {
for (size_t i = 0; i < args.size(); ++i) for (size_t i = 0; i < args.size(); ++i)
delete args[i]; delete args[i];
} }
virtual int scan(TPpToken*);
virtual int getch() { assert(0); return endOfInput; }
virtual void ungetch() { assert(0); }
MacroSymbol *mac; MacroSymbol *mac;
TVector<TokenStream*> args; TVector<TokenStream*> args;
}; };
InputSrc *currentInput; class tMarkerInput : public tInput {
public:
tMarkerInput(TPpContext* pp) : tInput(pp) { }
virtual int scan(TPpToken*)
{
if (done)
return endOfInput;
done = true;
return marker;
}
virtual int getch() { assert(0); return endOfInput; }
virtual void ungetch() { assert(0); }
static const int marker = -3;
};
class tZeroInput : public tInput {
public:
tZeroInput(TPpContext* pp) : tInput(pp) { }
virtual int scan(TPpToken*);
virtual int getch() { assert(0); return endOfInput; }
virtual void ungetch() { assert(0); }
};
std::vector<tInput*> inputStack;
bool errorOnVersion; bool errorOnVersion;
bool versionSeen; bool versionSeen;
@ -256,12 +323,8 @@ protected:
int CPPversion(TPpToken * ppToken); int CPPversion(TPpToken * ppToken);
int CPPextension(TPpToken * ppToken); int CPPextension(TPpToken * ppToken);
int readCPPline(TPpToken * ppToken); int readCPPline(TPpToken * ppToken);
void PushEofSrc(); TokenStream* PrescanMacroArg(TokenStream *a, TPpToken * ppToken, bool newLineOkay);
void PopEofSrc(); int MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool newLineOkay);
TokenStream* PrescanMacroArg(TokenStream *a, TPpToken * ppToken);
static int macro_scan(TPpContext* pp, InputSrc *inInput, TPpToken * ppToken);
static int zero_scan(TPpContext* pp, InputSrc *inInput, TPpToken * ppToken);
int MacroExpand(int atom, TPpToken* ppToken, bool expandUndef);
// //
// from PpSymbols.cpp // from PpSymbols.cpp
@ -278,32 +341,49 @@ protected:
void RecordToken(TokenStream* pTok, int token, TPpToken* ppToken); void RecordToken(TokenStream* pTok, int token, TPpToken* ppToken);
void RewindTokenStream(TokenStream *pTok); void RewindTokenStream(TokenStream *pTok);
int ReadToken(TokenStream* pTok, TPpToken* ppToken); int ReadToken(TokenStream* pTok, TPpToken* ppToken);
int ReadFromTokenStream(TokenStream *ts, int name, int (*final)(TPpContext *)); void pushTokenStreamInput(TokenStream *ts, int name);
void UngetToken(int token, TPpToken* ppToken); void UngetToken(int token, TPpToken* ppToken);
struct TokenInputSrc : public InputSrc {
class tTokenInput : public tInput {
public:
tTokenInput(TPpContext* pp, TokenStream* t) : tInput(pp), tokens(t) { }
virtual int scan(TPpToken *);
virtual int getch() { assert(0); return endOfInput; }
virtual void ungetch() { assert(0); }
protected:
TokenStream *tokens; TokenStream *tokens;
int (*final)(TPpContext *);
}; };
static int scan_token(TPpContext*, TokenInputSrc *in, TPpToken * ppToken);
struct UngotToken : public InputSrc { class tUngotTokenInput : public tInput {
public:
tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { }
virtual int scan(TPpToken *);
virtual int getch() { assert(0); return endOfInput; }
virtual void ungetch() { assert(0); }
protected:
int token; int token;
TPpToken lval; TPpToken lval;
}; };
static int reget_token(TPpContext *, UngotToken *t, TPpToken * ppToken);
// //
// From PpScanner.cpp // From PpScanner.cpp
// //
struct StringInputSrc : public InputSrc { class tStringInput : public tInput {
public:
tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { }
virtual int scan(TPpToken *);
virtual int getch();
virtual void ungetch();
protected:
TInputScanner* input; TInputScanner* input;
}; };
int InitScanner(TPpContext *cpp); int InitScanner(TPpContext *cpp);
static int sourceGetCh(TPpContext*, StringInputSrc *in);
static void sourceUngetCh(TPpContext*, StringInputSrc *in, int ch, TPpToken *type);
int ScanFromString(char *s); int ScanFromString(char *s);
bool check_EOF(int token); void missingEndifCheck();
int lFloatConst(char *str, int len, int ch, TPpToken * ppToken); int lFloatConst(char *str, int len, int ch, TPpToken * ppToken);
static int sourceScan(TPpContext*, InputSrc *in, TPpToken * ppToken);
bool inComment;
// //
// From PpAtom.cpp // From PpAtom.cpp

View File

@ -75,7 +75,7 @@ NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\****************************************************************************/ \****************************************************************************/
//
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -93,13 +93,6 @@ struct chunk {
struct chunk *next; struct chunk *next;
}; };
struct cleanup {
struct cleanup *next;
void (*fn)(void *, void *);
void *arg1;
void *arg2;
};
TPpContext::MemoryPool* TPpContext::mem_CreatePool(size_t chunksize, unsigned int align) TPpContext::MemoryPool* TPpContext::mem_CreatePool(size_t chunksize, unsigned int align)
{ {
MemoryPool *pool; MemoryPool *pool;
@ -108,32 +101,28 @@ TPpContext::MemoryPool* TPpContext::mem_CreatePool(size_t chunksize, unsigned in
align = ALIGN; align = ALIGN;
if (chunksize == 0) if (chunksize == 0)
chunksize = CHUNKSIZE; chunksize = CHUNKSIZE;
if (align & (align-1)) if (align & (align - 1))
return 0; return 0;
if (chunksize < sizeof(MemoryPool)) if (chunksize < sizeof(MemoryPool))
return 0; return 0;
if (chunksize & (align-1)) if (chunksize & (align - 1))
return 0; return 0;
if (!(pool = (MemoryPool*)malloc(chunksize))) if (!(pool = (MemoryPool*)malloc(chunksize)))
return 0; return 0;
pool->next = 0; pool->next = 0;
pool->chunksize = chunksize; pool->chunksize = chunksize;
pool->alignmask = (uintptr_t)(align)-1; pool->alignmask = (uintptr_t)(align) - 1;
pool->free = ((uintptr_t)(pool + 1) + pool->alignmask) & ~pool->alignmask; pool->free = ((uintptr_t)(pool + 1) + pool->alignmask) & ~pool->alignmask;
pool->end = (uintptr_t)pool + chunksize; pool->end = (uintptr_t)pool + chunksize;
pool->cleanup = 0;
return pool; return pool;
} }
void TPpContext::mem_FreePool(MemoryPool *pool) void TPpContext::mem_FreePool(MemoryPool *pool)
{ {
struct cleanup *cleanup;
struct chunk *p, *next; struct chunk *p, *next;
for (cleanup = pool->cleanup; cleanup; cleanup = cleanup->next) {
cleanup->fn(cleanup->arg1, cleanup->arg2);
}
for (p = (struct chunk *)pool; p; p = next) { for (p = (struct chunk *)pool; p; p = next) {
next = p->next; next = p->next;
free(p); free(p);
@ -168,19 +157,4 @@ void* TPpContext::mem_Alloc(MemoryPool *pool, size_t size)
return rv; return rv;
} }
int TPpContext::mem_AddCleanup(MemoryPool *pool, void (*fn)(void *, void*), void* arg1, void* arg2)
{
struct cleanup *cleanup;
pool->free = (pool->free + sizeof(void *) - 1) & ~(sizeof(void *)-1);
cleanup = (struct cleanup *)(mem_Alloc(pool, sizeof(struct cleanup)));
if (!cleanup) return -1;
cleanup->next = pool->cleanup;
cleanup->fn = fn;
cleanup->arg1 = arg1;
cleanup->arg2 = arg2;
pool->cleanup = cleanup;
return 0;
}
} // end namespace glslang } // end namespace glslang

View File

@ -98,28 +98,11 @@ int TPpContext::InitScanner(TPpContext *cpp)
if (!InitCPP()) if (!InitCPP())
return 0; return 0;
mostRecentToken = 0;
currentInput = 0;
previous_token = '\n'; previous_token = '\n';
return 1; return 1;
} }
int TPpContext::sourceGetCh(TPpContext* pp, StringInputSrc *in)
{
int ch = in->input->get();
if (ch == EOF)
delete in;
return ch;
}
void TPpContext::sourceUngetCh(TPpContext* pp, StringInputSrc *in, int ch, TPpToken *type)
{
in->input->unget();
}
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// Floating point constants: ///////////////////////////////// /////////////////////////////////// Floating point constants: /////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
@ -144,7 +127,7 @@ int TPpContext::lFloatConst(char* str, int len, int ch, TPpToken* ppToken)
if (ch == '.') { if (ch == '.') {
HasDecimalOrExponent = true; HasDecimalOrExponent = true;
str[len++]=ch; str[len++]=ch;
ch = currentInput->getch(this, currentInput, ppToken); ch = getChar();
while (ch >= '0' && ch <= '9') { while (ch >= '0' && ch <= '9') {
if (len < TPpToken::maxTokenLength) { if (len < TPpToken::maxTokenLength) {
declen++; declen++;
@ -152,7 +135,7 @@ int TPpContext::lFloatConst(char* str, int len, int ch, TPpToken* ppToken)
str[len] = ch; str[len] = ch;
len++;str_len++; len++;str_len++;
} }
ch = currentInput->getch(this, currentInput, ppToken); ch = getChar();
} else { } else {
parseContext.error(ppToken->loc, "float literal too long", "", ""); parseContext.error(ppToken->loc, "float literal too long", "", "");
len = 1,str_len=1; len = 1,str_len=1;
@ -170,21 +153,21 @@ int TPpContext::lFloatConst(char* str, int len, int ch, TPpToken* ppToken)
} else { } else {
ExpSign = 1; ExpSign = 1;
str[len++]=ch; str[len++]=ch;
ch = currentInput->getch(this, currentInput, ppToken); ch = getChar();
if (ch == '+') { if (ch == '+') {
str[len++]=ch; str[len++]=ch;
ch = currentInput->getch(this, currentInput, ppToken); ch = getChar();
} else if (ch == '-') { } else if (ch == '-') {
ExpSign = -1; ExpSign = -1;
str[len++]=ch; str[len++]=ch;
ch = currentInput->getch(this, currentInput, ppToken); ch = getChar();
} }
if (ch >= '0' && ch <= '9') { if (ch >= '0' && ch <= '9') {
while (ch >= '0' && ch <= '9') { while (ch >= '0' && ch <= '9') {
if (len < TPpToken::maxTokenLength) { if (len < TPpToken::maxTokenLength) {
exp = exp*10 + ch - '0'; exp = exp*10 + ch - '0';
str[len++]=ch; str[len++]=ch;
ch = currentInput->getch(this, currentInput, ppToken); ch = getChar();
} else { } else {
parseContext.error(ppToken->loc, "float literal too long", "", ""); parseContext.error(ppToken->loc, "float literal too long", "", "");
len = 1,str_len=1; len = 1,str_len=1;
@ -205,10 +188,10 @@ int TPpContext::lFloatConst(char* str, int len, int ch, TPpToken* ppToken)
parseContext.doubleCheck(ppToken->loc, "double floating-point suffix"); parseContext.doubleCheck(ppToken->loc, "double floating-point suffix");
if (! HasDecimalOrExponent) if (! HasDecimalOrExponent)
parseContext.error(ppToken->loc, "float literal needs a decimal point or exponent", "", ""); parseContext.error(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
int ch2 = currentInput->getch(this, currentInput, ppToken); int ch2 = getChar();
if (ch2 != 'f' && ch2 != 'F') { if (ch2 != 'f' && ch2 != 'F') {
currentInput->ungetch(this, currentInput, ch2, ppToken); ungetChar();
currentInput->ungetch(this, currentInput, ch, ppToken); ungetChar();
} else { } else {
if (len < TPpToken::maxTokenLength) { if (len < TPpToken::maxTokenLength) {
str[len++] = ch; str[len++] = ch;
@ -231,7 +214,7 @@ int TPpContext::lFloatConst(char* str, int len, int ch, TPpToken* ppToken)
len = 1,str_len=1; len = 1,str_len=1;
} }
} else } else
currentInput->ungetch(this, currentInput, ch, ppToken); ungetChar();
str[len]='\0'; str[len]='\0';
@ -249,7 +232,7 @@ int TPpContext::lFloatConst(char* str, int len, int ch, TPpToken* ppToken)
// //
// Scanner used to tokenize source stream. // Scanner used to tokenize source stream.
// //
int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken) int TPpContext::tStringInput::scan(TPpToken* ppToken)
{ {
char tokenText[TPpToken::maxTokenLength + 1]; char tokenText[TPpToken::maxTokenLength + 1];
int AlreadyComplained = 0; int AlreadyComplained = 0;
@ -258,18 +241,22 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
ppToken->ival = 0; ppToken->ival = 0;
ppToken->space = false; ppToken->space = false;
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
for (;;) { for (;;) {
while (ch == ' ' || ch == '\t' || ch == '\r') { while (ch == ' ' || ch == '\t') {
ppToken->space = true; ppToken->space = true;
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
} }
ppToken->loc = pp->parseContext.getCurrentLoc(); ppToken->loc = pp->parseContext.getCurrentLoc();
len = 0; len = 0;
switch (ch) { switch (ch) {
default: default:
return ch; // Single character token return ch; // Single character token, including '\' (escaped newlines are handled at a lower level, so this is just a '\' token)
case EOF:
return endOfInput;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J': case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O': case 'K': case 'L': case 'M': case 'N': case 'O':
@ -281,67 +268,45 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
case 'k': case 'l': case 'm': case 'n': case 'o': case 'k': case 'l': case 'm': case 'n': case 'o':
case 'p': case 'q': case 'r': case 's': case 't': case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y': case 'u': case 'v': case 'w': case 'x': case 'y':
case 'z': case '\\': case 'z':
do { do {
if (ch == '\\') { if (len < TPpToken::maxTokenLength) {
// escaped character
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
if (ch == '\r' || ch == '\n') {
pp->parseContext.lineContinuationCheck(ppToken->loc, false);
int nextch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
if (ch == '\r' && nextch == '\n')
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
else
ch = nextch;
} else {
// Not an escaped newline.
// Put back whatever it was
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken);
// If not in the middle of an identifier, the \ is our token
if (len == 0)
return '\\';
// Otherwise, put back the \ character, leave it for the next call
ch = '\\'; // for the upcoming unget(...ch...);
break;
}
} else if (len < TPpToken::maxTokenLength) {
tokenText[len++] = ch; tokenText[len++] = ch;
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
} else { } else {
if (! AlreadyComplained) { if (! AlreadyComplained) {
pp->parseContext.error(ppToken->loc, "name too long", "", ""); pp->parseContext.error(ppToken->loc, "name too long", "", "");
AlreadyComplained = 1; AlreadyComplained = 1;
} }
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
} }
} while ((ch >= 'a' && ch <= 'z') || } while ((ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') || (ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9') || (ch >= '0' && ch <= '9') ||
ch == '_' || ch == '_');
ch == '\\');
// line continuation with no token before or after makes len == 0, and need to start over skipping white space, etc. // line continuation with no token before or after makes len == 0, and need to start over skipping white space, etc.
if (len == 0) if (len == 0)
continue; continue;
tokenText[len] = '\0'; tokenText[len] = '\0';
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
ppToken->atom = pp->LookUpAddString(tokenText); ppToken->atom = pp->LookUpAddString(tokenText);
return CPP_IDENTIFIER; return CPP_IDENTIFIER;
case '0': case '0':
ppToken->name[len++] = ch; ppToken->name[len++] = ch;
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == 'x' || ch == 'X') { if (ch == 'x' || ch == 'X') {
// must be hexidecimal // must be hexidecimal
bool isUnsigned = false; bool isUnsigned = false;
ppToken->name[len++] = ch; ppToken->name[len++] = ch;
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if ((ch >= '0' && ch <= '9') || if ((ch >= '0' && ch <= '9') ||
(ch >= 'A' && ch <= 'F') || (ch >= 'A' && ch <= 'F') ||
(ch >= 'a' && ch <= 'f')) (ch >= 'a' && ch <= 'f')) {
{
ival = 0; ival = 0;
do { do {
if (ival <= 0x0fffffff) { if (ival <= 0x0fffffff) {
@ -362,7 +327,7 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
} }
ival = 0xffffffff; ival = 0xffffffff;
} }
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
} while ((ch >= '0' && ch <= '9') || } while ((ch >= '0' && ch <= '9') ||
(ch >= 'A' && ch <= 'F') || (ch >= 'A' && ch <= 'F') ||
(ch >= 'a' && ch <= 'f')); (ch >= 'a' && ch <= 'f'));
@ -374,7 +339,7 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
ppToken->name[len++] = ch; ppToken->name[len++] = ch;
isUnsigned = true; isUnsigned = true;
} else } else
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
ppToken->name[len] = '\0'; ppToken->name[len] = '\0';
ppToken->ival = (int)ival; ppToken->ival = (int)ival;
@ -403,7 +368,7 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
ival = (ival << 3) | ii; ival = (ival << 3) | ii;
} else } else
octalOverflow = true; octalOverflow = true;
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
} }
// could be part of a float... // could be part of a float...
@ -416,7 +381,7 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
pp->parseContext.error(ppToken->loc, "numeric literal too long", "", ""); pp->parseContext.error(ppToken->loc, "numeric literal too long", "", "");
AlreadyComplained = 1; AlreadyComplained = 1;
} }
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
} while (ch >= '0' && ch <= '9'); } while (ch >= '0' && ch <= '9');
} }
if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F' || ch == 'l' || ch == 'L') if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F' || ch == 'l' || ch == 'L')
@ -431,7 +396,7 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
ppToken->name[len++] = ch; ppToken->name[len++] = ch;
isUnsigned = true; isUnsigned = true;
} else } else
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
ppToken->name[len] = '\0'; ppToken->name[len] = '\0';
if (octalOverflow) if (octalOverflow)
@ -456,7 +421,7 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
pp->parseContext.error(ppToken->loc, "numeric literal too long", "", ""); pp->parseContext.error(ppToken->loc, "numeric literal too long", "", "");
AlreadyComplained = 1; AlreadyComplained = 1;
} }
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
} while (ch >= '0' && ch <= '9'); } while (ch >= '0' && ch <= '9');
if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F' || ch == 'l' || ch == 'L') { if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F' || ch == 'l' || ch == 'L') {
return pp->lFloatConst(ppToken->name, len, ch, ppToken); return pp->lFloatConst(ppToken->name, len, ch, ppToken);
@ -469,7 +434,7 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
ppToken->name[len++] = ch; ppToken->name[len++] = ch;
uint = 1; uint = 1;
} else } else
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
ppToken->name[len] = '\0'; ppToken->name[len] = '\0';
ival = 0; ival = 0;
@ -491,112 +456,112 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
} }
break; break;
case '-': case '-':
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '-') { if (ch == '-') {
return CPP_DEC_OP; return CPP_DEC_OP;
} else if (ch == '=') { } else if (ch == '=') {
return CPP_SUB_ASSIGN; return CPP_SUB_ASSIGN;
} else { } else {
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return '-'; return '-';
} }
case '+': case '+':
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '+') { if (ch == '+') {
return CPP_INC_OP; return CPP_INC_OP;
} else if (ch == '=') { } else if (ch == '=') {
return CPP_ADD_ASSIGN; return CPP_ADD_ASSIGN;
} else { } else {
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return '+'; return '+';
} }
case '*': case '*':
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '=') { if (ch == '=') {
return CPP_MUL_ASSIGN; return CPP_MUL_ASSIGN;
} else { } else {
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return '*'; return '*';
} }
case '%': case '%':
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '=') { if (ch == '=') {
return CPP_MOD_ASSIGN; return CPP_MOD_ASSIGN;
} else if (ch == '>'){ } else if (ch == '>'){
return CPP_RIGHT_BRACE; return CPP_RIGHT_BRACE;
} else { } else {
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return '%'; return '%';
} }
case ':': case ':':
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '>') { if (ch == '>') {
return CPP_RIGHT_BRACKET; return CPP_RIGHT_BRACKET;
} else { } else {
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return ':'; return ':';
} }
case '^': case '^':
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '^') { if (ch == '^') {
return CPP_XOR_OP; return CPP_XOR_OP;
} else { } else {
if (ch == '=') if (ch == '=')
return CPP_XOR_ASSIGN; return CPP_XOR_ASSIGN;
else{ else{
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return '^'; return '^';
} }
} }
case '=': case '=':
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '=') { if (ch == '=') {
return CPP_EQ_OP; return CPP_EQ_OP;
} else { } else {
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return '='; return '=';
} }
case '!': case '!':
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '=') { if (ch == '=') {
return CPP_NE_OP; return CPP_NE_OP;
} else { } else {
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return '!'; return '!';
} }
case '|': case '|':
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '|') { if (ch == '|') {
return CPP_OR_OP; return CPP_OR_OP;
} else { } else {
if (ch == '=') if (ch == '=')
return CPP_OR_ASSIGN; return CPP_OR_ASSIGN;
else{ else{
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return '|'; return '|';
} }
} }
case '&': case '&':
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '&') { if (ch == '&') {
return CPP_AND_OP; return CPP_AND_OP;
} else { } else {
if (ch == '=') if (ch == '=')
return CPP_AND_ASSIGN; return CPP_AND_ASSIGN;
else{ else{
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return '&'; return '&';
} }
} }
case '<': case '<':
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '<') { if (ch == '<') {
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '=') if (ch == '=')
return CPP_LEFT_ASSIGN; return CPP_LEFT_ASSIGN;
else{ else{
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return CPP_LEFT_OP; return CPP_LEFT_OP;
} }
} else { } else {
@ -608,78 +573,66 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
else if (ch == ':') else if (ch == ':')
return CPP_LEFT_BRACKET; return CPP_LEFT_BRACKET;
else{ else{
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return '<'; return '<';
} }
} }
} }
case '>': case '>':
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '>') { if (ch == '>') {
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '=') if (ch == '=')
return CPP_RIGHT_ASSIGN; return CPP_RIGHT_ASSIGN;
else{ else{
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return CPP_RIGHT_OP; return CPP_RIGHT_OP;
} }
} else { } else {
if (ch == '=') { if (ch == '=') {
return CPP_GE_OP; return CPP_GE_OP;
} else { } else {
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return '>'; return '>';
} }
} }
case '.': case '.':
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch >= '0' && ch <= '9') { if (ch >= '0' && ch <= '9') {
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return pp->lFloatConst(ppToken->name, 0, '.', ppToken); return pp->lFloatConst(ppToken->name, 0, '.', ppToken);
} else { } else {
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return '.'; return '.';
} }
case '/': case '/':
// TODO: preprocessor simplification: use the Scan.cpp comment scanner ch = pp->getChar();
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
if (ch == '/') { if (ch == '/') {
pp->inComment = true;
do { do {
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == '\\') {
// allow an escaped newline, otherwise escapes in comments are meaningless
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
if (ch == '\r' || ch == '\n') {
if (! pp->parseContext.lineContinuationCheck(ppToken->loc, true))
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken);
else {
int nextch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
if (ch == '\r' && nextch == '\n')
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
else
ch = nextch;
}
}
}
} while (ch != '\n' && ch != EOF); } while (ch != '\n' && ch != EOF);
ppToken->space = true; ppToken->space = true;
pp->inComment = false;
if (ch == EOF)
return endOfInput;
return ch; return ch;
} else if (ch == '*') { } else if (ch == '*') {
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
do { do {
while (ch != '*') { while (ch != '*') {
if (ch == EOF) { if (ch == EOF) {
pp->parseContext.error(ppToken->loc, "EOF in comment", "comment", ""); pp->parseContext.error(ppToken->loc, "EOF in comment", "comment", "");
return endOfInput;
return EOF;
} }
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
} }
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
if (ch == EOF) { if (ch == EOF) {
pp->parseContext.error(ppToken->loc, "EOF in comment", "comment", ""); pp->parseContext.error(ppToken->loc, "EOF in comment", "comment", "");
return endOfInput;
return EOF;
} }
} while (ch != '/'); } while (ch != '/');
ppToken->space = true; ppToken->space = true;
@ -688,23 +641,17 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
} else if (ch == '=') { } else if (ch == '=') {
return CPP_DIV_ASSIGN; return CPP_DIV_ASSIGN;
} else { } else {
pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken); pp->ungetChar();
return '/'; return '/';
} }
break; break;
case '"': case '"':
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
while (ch != '"' && ch != '\n' && ch != EOF) { while (ch != '"' && ch != '\n' && ch != EOF) {
if (ch == '\\') {
pp->parseContext.lineContinuationCheck(ppToken->loc, false);
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
if (ch == '\n' || ch == '\r' || ch == EOF)
break;
}
if (len < TPpToken::maxTokenLength) { if (len < TPpToken::maxTokenLength) {
tokenText[len] = ch; tokenText[len] = ch;
len++; len++;
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
} else } else
break; break;
}; };
@ -718,10 +665,84 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
} }
} }
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken); ch = pp->getChar();
} }
} }
//
// Scanner used to get source stream characters.
// - Escaped newlines are handled here, invisibly to the caller.
// - All forms of newline are handled, and turned into just a '\n'.
//
int TPpContext::tStringInput::getch()
{
int ch = input->get();
if (ch == '\\') {
// Move past escaped newlines, as many as sequentially exist
do {
if (input->peek() == '\r' || input->peek() == '\n') {
bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment);
if (! allowed && pp->inComment)
return '\\';
// escape one newline now
ch = input->get();
int nextch = input->get();
if (ch == '\r' && nextch == '\n')
ch = input->get();
else
ch = nextch;
} else
return '\\';
} while (ch == '\\');
}
// handle any non-escaped newline
if (ch == '\r' || ch == '\n') {
if (ch == '\r' && input->peek() == '\n')
ch = input->get();
return '\n';
}
return ch;
}
//
// Scanner used to backup the source stream characters. Newlines are
// handled here, invisibly to the caller, meaning have to undo exactly
// what getch() above does (e.g., don't leave things in the middle of a
// sequence of escaped newlines).
//
void TPpContext::tStringInput::ungetch()
{
input->unget();
do {
int ch = input->peek();
if (ch == '\r' || ch == '\n') {
if (ch == '\n') {
// correct for two-character newline
input->unget();
if (input->peek() != '\r')
input->get();
}
// now in front of a complete newline, move past an escape character
input->unget();
if (input->peek() == '\\')
input->unget();
else {
input->get();
break;
}
} else
break;
} while (true);
}
//
// The main functional entry-point into the preprocessor, which will
// scan the source strings to figure out and return the next processing token.
// //
// Return string pointer to next token. // Return string pointer to next token.
// Return 0 when no more tokens. // Return 0 when no more tokens.
@ -732,15 +753,19 @@ const char* TPpContext::tokenize(TPpToken* ppToken)
for(;;) { for(;;) {
const char* tokenString = 0; const char* tokenString = 0;
token = currentInput->scan(this, currentInput, ppToken); token = scanToken(ppToken);
ppToken->token = token; ppToken->token = token;
if (check_EOF(token)) if (token == EOF) {
missingEndifCheck();
return 0; return 0;
}
if (token == '#') { if (token == '#') {
if (previous_token == '\n' || previous_token == 0) { if (previous_token == '\n') {
token = readCPPline(ppToken); token = readCPPline(ppToken);
if (check_EOF(token)) if (token == EOF) {
missingEndifCheck();
return 0; return 0;
}
continue; continue;
} else { } else {
parseContext.error(ppToken->loc, "preprocessor directive cannot be preceded by another token", "#", ""); parseContext.error(ppToken->loc, "preprocessor directive cannot be preceded by another token", "#", "");
@ -753,7 +778,7 @@ const char* TPpContext::tokenize(TPpToken* ppToken)
continue; continue;
// expand macros // expand macros
if (token == CPP_IDENTIFIER && MacroExpand(ppToken->atom, ppToken, false) == 1) if (token == CPP_IDENTIFIER && MacroExpand(ppToken->atom, ppToken, false, true) != 0)
continue; continue;
if (token == CPP_IDENTIFIER) if (token == CPP_IDENTIFIER)
@ -779,17 +804,11 @@ const char* TPpContext::tokenize(TPpToken* ppToken)
} }
} }
//Checks if the token just read is EOF or not. // Checks if we've seen balanced #if...#endif
bool TPpContext::check_EOF(int token) void TPpContext::missingEndifCheck()
{ {
if (token == EOF) {
if (ifdepth > 0) if (ifdepth > 0)
parseContext.error(parseContext.getCurrentLoc(), "missing #endif", "", ""); parseContext.error(parseContext.getCurrentLoc(), "missing #endif", "", "");
return true;
}
return false;
} }
} // end namespace glslang } // end namespace glslang

View File

@ -109,7 +109,7 @@ int TPpContext::lReadByte(TokenStream *pTok)
if (pTok->current < pTok->data.size()) if (pTok->current < pTok->data.size())
return pTok->data[pTok->current++]; return pTok->data[pTok->current++];
else else
return -1; return tInput::endOfInput;
} }
/* /*
@ -124,6 +124,7 @@ void TPpContext::RecordToken(TokenStream *pTok, int token, TPpToken* ppToken)
lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80)); lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80));
else else
lAddByte(pTok, (unsigned char)(token & 0x7f)); lAddByte(pTok, (unsigned char)(token & 0x7f));
switch (token) { switch (token) {
case CPP_IDENTIFIER: case CPP_IDENTIFIER:
case CPP_STRCONSTANT: case CPP_STRCONSTANT:
@ -154,11 +155,6 @@ void TPpContext::RecordToken(TokenStream *pTok, int token, TPpToken* ppToken)
void TPpContext::RewindTokenStream(TokenStream *pTok) void TPpContext::RewindTokenStream(TokenStream *pTok)
{ {
pTok->current = 0; pTok->current = 0;
//if (pTok->head) {
// pTok->current = pTok->head;
// pTok->current->current = 0;
//}
} }
/* /*
@ -172,7 +168,6 @@ int TPpContext::ReadToken(TokenStream *pTok, TPpToken *ppToken)
ltoken = lReadByte(pTok); ltoken = lReadByte(pTok);
ppToken->loc = parseContext.getCurrentLoc(); ppToken->loc = parseContext.getCurrentLoc();
if (ltoken >= 0) {
if (ltoken > 127) if (ltoken > 127)
ltoken += 128; ltoken += 128;
switch (ltoken) { switch (ltoken) {
@ -219,58 +214,36 @@ int TPpContext::ReadToken(TokenStream *pTok, TPpToken *ppToken)
break; break;
} }
} }
return ltoken; return ltoken;
}
return EOF;
} }
int TPpContext::scan_token(TPpContext* pp, TokenInputSrc *in, TPpToken * ppToken) int TPpContext::tTokenInput::scan(TPpToken* ppToken)
{ {
int token = pp->ReadToken(in->tokens, ppToken); return pp->ReadToken(tokens, ppToken);
int (*final)(TPpContext *);
if (token > 0)
return token;
pp->currentInput = in->prev;
final = in->final;
delete in;
if (final && !final(pp))
return -1;
return pp->currentInput->scan(pp, pp->currentInput, ppToken);
} }
int TPpContext::ReadFromTokenStream(TokenStream *ts, int name, int (*final)(TPpContext *)) void TPpContext::pushTokenStreamInput(TokenStream* ts, int name)
{ {
TokenInputSrc* in = new TokenInputSrc; pushInput(new tTokenInput(this, ts));
in->prev = currentInput;
in->scan = (int (*)(TPpContext*, InputSrc*, TPpToken*))scan_token;
in->tokens = ts;
in->final = final;
RewindTokenStream(ts); RewindTokenStream(ts);
currentInput = in;
return 1;
} }
int TPpContext::reget_token(TPpContext* pp, UngotToken *t, TPpToken * ppToken) int TPpContext::tUngotTokenInput::scan(TPpToken* ppToken)
{ {
int token = t->token; if (done)
*ppToken = t->lval; return endOfInput;
pp->currentInput = t->prev;
delete t;
return token; int ret = token;
*ppToken = lval;
done = true;
return ret;
} }
void TPpContext::UngetToken(int token, TPpToken* ppToken) void TPpContext::UngetToken(int token, TPpToken* ppToken)
{ {
UngotToken *t = new UngotToken; pushInput(new tUngotTokenInput(this, token, ppToken));
t->token = token;
t->lval = *ppToken;
t->scan = (int(*)(TPpContext*, struct InputSrc *, TPpToken *))reget_token;
t->prev = currentInput;
currentInput = t;
} }
} // end namespace glslang } // end namespace glslang