ERROR: 0:46: 'xyxwx' : illegal vector field selection \r
ERROR: 0:46: 'xyxwx' : illegal vector field selection \r
-ERROR: 2 compilation errors. No code generated.\r
+ERROR: 0:51: '' : missing #endif \r
+ERROR: 3 compilation errors. No code generated.\r
\r
ERROR: node is still EOpNull!\r
0:4 Sequence\r
+Warning, version 400 is not yet complete; some version-specific features are present, but many are missing.\r
ERROR: 0:77: '#error' : good1 \r
ERROR: 0:81: '#error' : good2 \r
ERROR: 0:85: '#error' : good3 \r
ERROR: 0:97: '#error' : good6 \r
ERROR: 0:101: 'preprocessor' : expected ')' \r
ERROR: 0:101: '#error' : bad1 \r
-WARNING: 0:104: '#if' : unexpected tokens following #if directive - expected a newline \r
+ERROR: 0:104: '#if' : unexpected tokens following directive \r
ERROR: 0:105: '#error' : bad2 \r
ERROR: 0:109: 'preprocessor' : expected ')' \r
ERROR: 0:109: '#error' : bad3 \r
-WARNING: 0:112: '#if' : unexpected tokens following #if directive - expected a newline \r
+ERROR: 0:112: '#if' : unexpected tokens following directive \r
ERROR: 0:113: '#error' : bad4 \r
ERROR: 0:117: 'preprocessor' : expected ')' \r
ERROR: 0:117: '#error' : bad5 \r
-WARNING: 0:120: '#if' : unexpected tokens following #if directive - expected a newline \r
+ERROR: 0:120: '#if' : unexpected tokens following directive \r
ERROR: 0:121: '#error' : bad6 \r
-ERROR: 0:133: '#' : preprocessor directive cannot be preceded by another token \r
-INTERNAL ERROR: 0:133: Unknown PP token\r
-ERROR: 0:133: '' : syntax error\r
-ERROR: 17 compilation errors. No code generated.\r
+ERROR: 0:122: '#endif' : unexpected tokens following directive \r
+ERROR: 0:135: '""' : string literals not supported \r
+ERROR: 0:136: '""' : string literals not supported \r
+ERROR: 0:136: 'length' : no matching overloaded function found \r
+ERROR: 0:136: '=' : cannot convert from 'const float' to 'int'\r
+ERROR: 0:138: ''' : character literals not supported \r
+ERROR: 0:138: ''' : character literals not supported \r
+ERROR: 0:141: '#define' : reserved built-in name prefix: GL_\r
+ERROR: 0:142: '#define' : reserved built-in name prefix: GL_\r
+ERROR: 0:143: '#define' : names containing consecutive underscores are reserved \r
+ERROR: 0:144: '#define' : names containing consecutive underscores are reserved \r
+ERROR: 0:145: '#define' : names containing consecutive underscores are reserved \r
+ERROR: 0:148: '#else' : unexpected tokens following directive \r
+ERROR: 0:149: '#else' : #elif after #else \r
+ERROR: 0:155: '#else' : unexpected tokens following directive \r
+ERROR: 0:158: '#else' : #else after #else \r
+ERROR: 0:160: '#endif' : unexpected tokens following directive \r
+ERROR: 0:164: '#define' : duplicate macro parameter \r
+ERROR: 0:173: '#define' : Macro redefined; different number of arguments: m4\r
+ERROR: 0:178: '#define' : Macro redefined; different number of arguments: m5\r
+ERROR: 0:182: '#define' : Macro redefined; different number of arguments: m6\r
+ERROR: 0:185: '#define' : Macro redefined; different substitutions: m7\r
+ERROR: 0:192: '#define' : Macro redefined; different substitutions: m8\r
+ERROR: 0:196: '#define' : Macro redefined; different argument names: m9\r
+ERROR: 0:206: '' : missing #endif \r
+ERROR: 43 compilation errors. No code generated.\r
\r
ERROR: node is still EOpNull!\r
0:5 Sequence\r
0:65 Constant:\r
0:65 0.050000\r
0:69 move second child to first child (4-component vector of float)\r
-0:69 'gl_Position' (gl_Position 4-component vector of float)\r
+0:69 gl_Position: direct index for structure (gl_Position 4-component vector of float)\r
+0:69 '__anon__1' (out block{gl_Position,gl_PointSize,gl_ClipDistance,gl_ClipVertex,gl_FrontColor,gl_BackColor,gl_FrontSecondaryColor,gl_BackSecondaryColor,gl_TexCoord,gl_FogFragCoord})\r
+0:69 Constant:\r
+0:69 0 (const uint)\r
0:69 Construct vec4 (4-component vector of float)\r
0:69 'sum' (float)\r
0:124 Sequence\r
0:126 move second child to first child (int)\r
0:126 'version' (int)\r
0:126 Constant:\r
-0:126 110 (const int)\r
+0:126 400 (const int)\r
0:130 Sequence\r
0:130 move second child to first child (float)\r
0:130 'twoPi' (float)\r
0:130 Constant:\r
0:130 6.280000\r
+0:199 Sequence\r
+0:199 move second child to first child (int)\r
+0:199 'n' (int)\r
+0:199 Constant:\r
+0:199 15 (const int)\r
+0:202 Sequence\r
+0:202 move second child to first child (double)\r
+0:202 'f' (double)\r
+0:202 Constant:\r
+0:202 0.000800\r
0:? Linker Objects\r
0:? 'sum' (float)\r
0:? 'linenumber' (int)\r
0:? 'filenumber' (int)\r
0:? 'version' (int)\r
0:? 'twoPi' (float)\r
-0:? 'tod' (float)\r
+0:? 'a' (int)\r
+0:? 'n' (int)\r
+0:? 'f' (double)\r
+0:? 'gl_VertexID' (gl_VertexId int)\r
+0:? 'gl_InstanceID' (gl_InstanceId int)\r
\r
return ADD(gl_Position.xyxwx, 3.0) // ERROR, should be this line number
return ADD(gl_Position.y, 3.0)
}
+
+#if 0
+// ERROR, EOF
\ No newline at end of file
-#version 110
+#version 400
#define ON
#if ((AA == BB || (AA == CC))))
#error bad6
-#endif
+#endif extra tokens
int linenumber = __LINE__;
int filenumber = __FILE__;
#define TWOPI (2.0 * PI)
float twoPi = TWOPI;
-#define PASTE(a,b) a ## b
-float PASTE(tod, ay) = 17;
+//#define PASTE(a,b) a ## b
+//float PASTE(tod, ay) = 17;
+
+"boo" // ERROR
+int a = length("aoenatuh"); // ERROR
+
+'int'; // ERROR
+
+// ERROR: all the following are reserved
+#define GL_
+#define GL_Macro 1
+#define __M
+#define M__
+#define ABC__DE abc
+
+#if 4
+#else extra
+#elif
+// ERROR elif after else
+#endif
+
+#if blah
+ #if 0
+ #else extra
+ #ifdef M
+ #else
+ #else
+ // ERROR else after else
+ #endif extra
+ #endif
+#endif
+
+#define m1(a,a) // ERROR
+#define m2(a,b)
+
+// okay
+#define m3 (a)
+#define m3 (a)
+
+// ERROR
+#define m4(b)
+#define m4 (b)
+
+// ERROR
+#define m5 (b)
+#define m5(b)
+
+// ERROR
+#define m6(a)
+#define m6
+
+// ERROR (whitespace)
+#define m7 (a)
+#define m7 ( a)
+
+#define m80(a,b) is + exactly m3 the same
+#define m80(a,b) is + exactly m3 the same
+
+// ERROR
+#define m8(a,b) almost + exactly m3 the same
+#define m8(a,b) almost + exactly m3 thee same
+
+// ERROR
+#define m9(a,b,c) aoe
+#define m9(a,d,c) aoe
+
+#define n1 0xf
+int n = n1;
+
+#define f1 .08e-2Lf
+double f = f1;
+
+#if 1
+#else
+// ERROR, missing #endif
\ No newline at end of file
parserToken = &token;
TPpToken ppToken;
tokenText = pp->tokenize(&ppToken);
+ if (tokenText == 0)
+ return 0;
loc = ppToken.loc;
parserToken->sType.lex.loc = loc;
case CPP_OR_ASSIGN: return OR_ASSIGN;
case CPP_XOR_ASSIGN: return XOR_ASSIGN;
- case CPP_INTCONSTANT: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT;
- case CPP_UINTCONSTANT: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT;
+ case CPP_INTCONSTANT: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT;
+ case CPP_UINTCONSTANT: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT;
case CPP_FLOATCONSTANT: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT;
case CPP_DOUBLECONSTANT: parserToken->sType.lex.d = ppToken.dval; return DOUBLECONSTANT;
case CPP_IDENTIFIER: return tokenizeIdentifier();
//
class TInputScanner {
public:
- TInputScanner(int n, const char* const s[], size_t L[], int b = 0) :
- numSources(n), sources(s), lengths(L), currentSource(0), currentChar(0), stringBias(b)
+ TInputScanner(int n, const char* const s[], size_t L[], int b = 0, int f = 0) :
+ numSources(n), sources(s), lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f)
{
loc = new TSourceLoc[numSources];
loc[currentSource].string = -stringBias;
void setLine(int newLine) { loc[currentSource].line = newLine; }
void setString(int newString) { loc[currentSource].string = newString; }
- const TSourceLoc& getSourceLoc() const { return loc[currentSource]; }
+ const TSourceLoc& getSourceLoc() const { return loc[std::max(0, std::min(currentSource, numSources - finale - 1))]; }
void consumeWhiteSpace(bool& foundNonSpaceTab);
bool consumeComment();
TSourceLoc* loc; // an array
int stringBias; // the first string that is the user's string number 0
+ int finale; // number of internal strings after user's last string
};
} // end namespace glslang
lengths[0] = strlen(strings[0]);
strings[numStrings + 1] = "\n int;";
lengths[numStrings + 1] = strlen(strings[numStrings + 1]);
- TInputScanner fullInput(numStrings + 2, strings, lengths, 1);
+ TInputScanner fullInput(numStrings + 2, strings, lengths, 1, 1);
// Push a new symbol allocation scope that can for the shader's globals.
symbolTable.push();
{
mem_FreePool(pool);
- if (ifdepth)
- parseContext.error(parseContext.getCurrentLoc(), "missing #endif", "#if", "");
-
return 1;
}
-int TPpContext::CPPdefine(TPpToken * ppToken)
+int TPpContext::CPPdefine(TPpToken* ppToken)
{
int token, atom, args[maxMacroArgs], argc;
MacroSymbol mac;
memset(&mac, 0, sizeof(mac));
token = currentInput->scan(this, currentInput, ppToken);
if (token != CPP_IDENTIFIER) {
- parseContext.error(ppToken->loc, "must be followed by macro atom", "#define", "");
+ parseContext.error(ppToken->loc, "must be followed by macro name", "#define", "");
return token;
}
atom = ppToken->atom;
+ const char* definedName = GetAtomString(atom);
+ if (ppToken->loc.string >= 0) {
+ // We are in user code; check for reserved name use:
+ // "All macro names containing two consecutive underscores ( __ ) are reserved for future use as predefined
+ // macro names. All macro names prefixed with "GL_" ("GL" followed by a single underscore) are also
+ // reserved."
+ if (strncmp(definedName, "GL_", 3) == 0)
+ parseContext.error(ppToken->loc, "reserved built-in name prefix:", "#define", "GL_");
+ else if (strstr(definedName, "__") != 0)
+ parseContext.error(ppToken->loc, "names containing consecutive underscores are reserved", "#define", "");
+ }
token = currentInput->scan(this, currentInput, ppToken);
if (token == '(' && !ppToken->ival) {
// gather arguments
return token;
}
- if (argc < maxMacroArgs)
- args[argc++] = ppToken->atom;
+ // check for duplication
+ bool duplicate = false;
+ for (int a = 0; a < argc; ++a) {
+ if (args[a] == ppToken->atom) {
+ parseContext.error(ppToken->loc, "duplicate macro parameter", "#define", "");
+ duplicate = true;
+ break;
+ }
+ }
+ if (! duplicate) {
+ if (argc < maxMacroArgs)
+ args[argc++] = ppToken->atom;
+ else
+ parseContext.error(ppToken->loc, "too many macro parameters", "#define", "");
+ }
token = currentInput->scan(this, currentInput, ppToken);
} while (token == ',');
if (token != ')') {
memcpy(mac.args, args, argc * sizeof(int));
token = currentInput->scan(this, currentInput, ppToken);
}
- mac.body = NewTokenStream(GetAtomString(atom), pool);
+ TSourceLoc defineLoc = ppToken->loc; // because ppToken is going to go to the next line before we report errors
+ mac.body = NewTokenStream(pool);
while (token != '\n') {
- while (token == '\\') {
+ if (token == '\\') {
token = currentInput->scan(this, currentInput, ppToken);
if (token == '\n')
token = currentInput->scan(this, currentInput, ppToken);
- else
- RecordToken(mac.body, '\\', ppToken);
}
RecordToken(mac.body, token, ppToken);
+ int spaceCandidate = currentInput->getch(this, currentInput, ppToken);
+ if (spaceCandidate == ' ' || spaceCandidate == '\t')
+ RecordToken(mac.body, ' ', 0);
+ else
+ currentInput->ungetch(this, currentInput, spaceCandidate, ppToken);
token = currentInput->scan(this, currentInput, ppToken);
- };
+ }
symb = LookUpSymbol(atom);
if (symb) {
- if (!symb->mac.undef) {
- // already defined -- need to make sure they are identical
+ if (! symb->mac.undef) {
+ // Already defined -- need to make sure they are identical:
+ // "Two replacement lists are identical if and only if the preprocessing tokens in both have the same number,
+ // ordering, spelling, and white-space separation, where all white-space separations are considered identical."
if (symb->mac.argc != mac.argc)
- goto error;
- for (argc=0; argc < mac.argc; argc++)
- if (symb->mac.args[argc] != mac.args[argc])
- goto error;
- RewindTokenStream(symb->mac.body);
- RewindTokenStream(mac.body);
- do {
- int old_lval, old_token;
- old_token = ReadToken(symb->mac.body, ppToken);
- old_lval = ppToken->ival;
- token = ReadToken(mac.body, ppToken);
- if (token != old_token || ppToken->ival != old_lval) {
-error:
- parseContext.error(ppToken->loc, "Macro Redefined", "#define", GetAtomString(atom));
- break;
+ parseContext.error(defineLoc, "Macro redefined; different number of arguments:", "#define", GetAtomString(atom));
+ else {
+ for (argc=0; argc < mac.argc; argc++) {
+ if (symb->mac.args[argc] != mac.args[argc])
+ parseContext.error(defineLoc, "Macro redefined; different argument names:", "#define", GetAtomString(atom));
}
- } while (token > 0);
+ RewindTokenStream(symb->mac.body);
+ RewindTokenStream(mac.body);
+ int newToken;
+ do {
+ int oldToken;
+ TPpToken oldPpToken;
+ TPpToken newPpToken;
+ oldToken = ReadToken(symb->mac.body, &oldPpToken);
+ newToken = ReadToken(mac.body, &newPpToken);
+ if (oldToken != newToken || oldPpToken != newPpToken) {
+ parseContext.error(defineLoc, "Macro redefined; different substitutions:", "#define", GetAtomString(atom));
+ break;
+ }
+ } while (newToken > 0);
+ }
}
} else {
symb = AddSymbol(atom);
symb->mac = mac;
return '\n';
-} // CPPdefine
+}
int TPpContext::CPPundef(TPpToken * ppToken)
{
parseContext.error(ppToken->loc, "can only be followed by a single macro name", "#undef", "");
return token;
-} // CPPundef
+}
-/* CPPelse -- skip forward to appropriate spot. This is actually used
+/* Skip forward to appropriate spot. This is used both
** to skip to a #endif after seeing an #else, AND to skip to a #else,
-** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false
+** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false.
*/
-
-int TPpContext::CPPelse(int matchelse, TPpToken * ppToken)
+int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
{
int atom;
int depth = 0;
int token = currentInput->scan(this, currentInput, ppToken);
- while (token > 0) {
+ while (token != EOF) {
if (token != '#') {
- while (token != '\n')
+ while (token != '\n' && token != EOF)
token = currentInput->scan(this, currentInput, ppToken);
+
+ if (token == EOF)
+ return EOF;
token = currentInput->scan(this, currentInput, ppToken);
continue;
ifdepth++;
elsetracker++;
} else if (atom == endifAtom) {
+ token = extraTokenCheck(atom, ppToken, currentInput->scan(this, currentInput, ppToken));
elsedepth[elsetracker] = 0;
--elsetracker;
if (depth == 0) {
--ifdepth;
} else if (matchelse && depth == 0) {
if (atom == elseAtom ) {
+ token = extraTokenCheck(atom, ppToken, currentInput->scan(this, currentInput, ppToken));
// found the #else we are looking for
- token = currentInput->scan(this, currentInput, ppToken);
- if (token != '\n') {
- parseContext.warn(ppToken->loc, "#else", "unexpected tokens following #else directive - expected a newline", "");
- while (token != '\n')
- token = currentInput->scan(this, currentInput, ppToken);
- }
break;
} else if (atom == elifAtom) {
/* we decrement ifdepth here, because CPPif will increment
--elsetracker;
}
- return CPPif (ppToken);
+ return CPPif(ppToken);
}
- } else if ((atom == elseAtom) && (!ChkCorrectElseNesting()))
- parseContext.error(ppToken->loc, "#else after #else", "#else", "");
- }; // end while
+ } else if (atom == elseAtom || atom == elifAtom) {
+ if (! ChkCorrectElseNesting()) {
+ if (atom == elseAtom)
+ parseContext.error(ppToken->loc, "#else after #else", "#else", "");
+ else
+ parseContext.error(ppToken->loc, "#elif after #else", "#else", "");
+ }
+ if (atom == elseAtom)
+ token = extraTokenCheck(atom, ppToken, currentInput->scan(this, currentInput, ppToken));
+ }
+ }
+
+ return token;
+}
+
+int TPpContext::extraTokenCheck(int atom, TPpToken* ppToken, int token)
+{
+ if (token != '\n') {
+ static const char* message = "unexpected tokens following directive";
+
+ const char* label;
+ if (atom == elseAtom)
+ label = "#else";
+ else if (atom == elifAtom)
+ label = "#elif";
+ else if (atom == endifAtom)
+ label = "#endif";
+ else if (atom == ifAtom)
+ label = "#if";
+ else
+ label = "";
+
+ if (parseContext.messages & EShMsgRelaxedErrors)
+ parseContext.warn(ppToken->loc, message, label, "");
+ else
+ parseContext.error(ppToken->loc, message, label, "");
+
+ while (token != '\n')
+ token = currentInput->scan(this, currentInput, ppToken);
+ }
return token;
}
return token;
} // eval
-int TPpContext::CPPif (TPpToken * ppToken)
+int TPpContext::CPPif(TPpToken* ppToken)
{
int token = currentInput->scan(this, currentInput, ppToken);
int res = 0, err = 0;
return 0;
}
token = eval(token, MIN_PREC, &res, &err, ppToken);
- if (token != '\n') {
- parseContext.warn(ppToken->loc, "unexpected tokens following #if directive - expected a newline", "#if", "");
- while (token != '\n')
- token = currentInput->scan(this, currentInput, ppToken);
- }
- if (!res && !err) {
+ token = extraTokenCheck(ifAtom, ppToken, token);
+ if (!res && !err)
token = CPPelse(1, ppToken);
- }
return token;
-} // CPPif
+}
int TPpContext::CPPifdef(int defined, TPpToken * ppToken)
{
if (((s && !s->mac.undef) ? 1 : 0) != defined)
token = CPPelse(1, ppToken);
}
+
return token;
-} // CPPifdef
+}
// Handle #line
int TPpContext::CPPline(TPpToken * ppToken)
token = CPPdefine(ppToken);
} else if (ppToken->atom == elseAtom) {
if (ChkCorrectElseNesting()) {
- if (! ifdepth) {
+ if (! ifdepth)
parseContext.error(ppToken->loc, "mismatched statements", "#else", "");
- }
- token = currentInput->scan(this, currentInput, ppToken);
- if (token != '\n') {
- parseContext.warn(ppToken->loc, "unexpected tokens following #else directive - expected a newline", "#else", "");
- while (token != '\n')
- token = currentInput->scan(this, currentInput, ppToken);
- }
+ token = extraTokenCheck(elseAtom, ppToken, currentInput->scan(this, currentInput, ppToken));
token = CPPelse(0, ppToken);
} else {
parseContext.error(ppToken->loc, "#else after a #else", "#else", "");
return 0;
}
} else if (ppToken->atom == elifAtom) {
- if (! ifdepth) {
+ if (! ifdepth)
parseContext.error(ppToken->loc, "mismatched statements", "#elif", "");
- }
// this token is really a dont care, but we still need to eat the tokens
token = currentInput->scan(this, currentInput, ppToken);
while (token != '\n')
parseContext.error(ppToken->loc, "mismatched statements", "#endif", "");
else
--ifdepth;
+ token = extraTokenCheck(endifAtom, ppToken, currentInput->scan(this, currentInput, ppToken));
} else if (ppToken->atom == ifAtom) {
token = CPPif (ppToken);
} else if (ppToken->atom == ifdefAtom) {
parseContext.error(ppToken->loc, "Invalid Directive", "#", GetAtomString(ppToken->atom));
}
}
- while (token != '\n' && token != 0 && token != EOF) {
+
+ while (token != '\n' && token != 0 && token != EOF)
token = currentInput->scan(this, currentInput, ppToken);
- }
return token;
-} // readCPPline
+}
void TPpContext::FreeMacro(MacroSymbol *s) {
DeleteTokenStream(s->body);
token = ReadToken(a, ppToken);
if (token == CPP_IDENTIFIER && LookUpSymbol(ppToken->atom))
break;
- } while (token > 0);
- if (token <= 0) return a;
- n = NewTokenStream("macro arg", 0);
+ } while (token != EOF);
+ if (token == EOF)
+ return a;
+ n = NewTokenStream(0);
PushEofSrc();
ReadFromTokenStream(a, 0, 0);
while ((token = currentInput->scan(this, currentInput, ppToken)) > 0) {
}
PopEofSrc();
DeleteTokenStream(a);
+
return n;
-} // PrescanMacroArg
+}
//
// These are called through function pointers
//
-/* macro_scan ---
+/*
** return the next token for a macro expansion, handling macro args
*/
int TPpContext::macro_scan(TPpContext* pp, TPpContext::InputSrc* inInput, TPpToken* ppToken)
TPpContext::MacroInputSrc* in = (TPpContext::MacroInputSrc*)inInput;
int i;
- int token = pp->ReadToken(in->mac->body, ppToken);
+ int token;
+ do {
+ token = pp->ReadToken(in->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)
}
}
- if (token > 0)
+ if (token != EOF)
return token;
in->mac->busy = 0;
free(in);
return pp->currentInput->scan(pp, pp->currentInput, ppToken);
-} // macro_scan
+}
// return a zero, for scanning a macro that was never defined
int TPpContext::zero_scan(TPpContext* pp, InputSrc *inInput, TPpToken* ppToken)
return CPP_INTCONSTANT;
}
-/* MacroExpand
+/*
** Check an identifier (atom) to see if it is a macro that should be expanded.
** If it is, push an InputSrc that will produce the appropriate expansion
** and return 1.
}
in->args = (TokenStream**)malloc(in->mac->argc * sizeof(TokenStream *));
for (i = 0; i < in->mac->argc; i++)
- in->args[i] = NewTokenStream("macro arg", 0);
+ in->args[i] = NewTokenStream(0);
i = 0;
j = 0;
do {
in->args[i] = PrescanMacroArg(in->args[i], ppToken);
}
}
-#if 0
- printf(" <%s:%d>found macro %s\n", GetAtomString(atable, loc.file),
- loc.line, GetAtomString(atable, atom));
- for (i = 0; i<in->mac->argc; i++) {
- printf("\targ %s = '", GetAtomString(atable, in->mac->args[i]));
- DumpTokenStream(stdout, in->args[i]);
- printf("'\n");
- }
-#endif
+
/*retain the input source*/
in->base.prev = currentInput;
sym->mac.busy = 1;
currentInput = &in->base;
return 1;
-} // MacroExpand
+}
int TPpContext::ChkCorrectElseNesting()
{
return "<null atom>";
if (atom < 0)
return "<EOF>";
- if ((size_t)atom < stringMap.size())
- return stringMap[atom]->c_str();
+ if ((size_t)atom < stringMap.size()) {
+ if (stringMap[atom] == 0)
+ return "<invalid atom>";
+ else
+ return stringMap[atom]->c_str();
+ }
return "<invalid atom>";
}
{
TAtomMap::const_iterator it = atomMap.insert(std::pair<TString, int>(s, atom)).first;
if (stringMap.size() < (size_t)atom + 1)
- stringMap.resize(atom + 100);
+ stringMap.resize(atom + 100, 0);
stringMap[atom] = &it->first;
return atom;
StringInputSrc *in = (StringInputSrc *)malloc(sizeof(StringInputSrc));
memset(in, 0, sizeof(StringInputSrc));
in->input = &input;
- in->base.scan = byte_scan;
- in->base.getch = (int (*)(TPpContext*, InputSrc *, TPpToken *))str_getch;
- in->base.ungetch = (void (*)(TPpContext*, InputSrc *, int, TPpToken *))str_ungetch;
+ in->base.scan = sourceScan;
+ in->base.getch = (int (*)(TPpContext*, InputSrc *, TPpToken *))sourceGetCh;
+ in->base.ungetch = (void (*)(TPpContext*, InputSrc *, int, TPpToken *))sourceUngetCh;
in->base.prev = currentInput;
currentInput = &in->base;
errorOnVersion = versionWillBeError;
class TPpToken {
public:
- TPpToken() { loc.line = 0; loc.string = 0; name[0] = 0; }
+ TPpToken() : token(0), ival(0), dval(0.0), atom(0)
+ {
+ loc.line = 0;
+ loc.string = 0;
+ name[0] = 0;
+ }
+
+ bool operator==(const TPpToken& right)
+ {
+ return token == right.token && atom == right.atom &&
+ ival == right.ival && dval == right.dval &&
+ strcmp(name, right.name) == 0;
+ }
+ bool operator!=(const TPpToken& right) { return ! operator==(right); }
+
static const int maxTokenLength = 1024;
TSourceLoc loc;
const char* tokenize(TPpToken* ppToken);
+ // TODO: preprocessor simplification: this should be a base class, not a set of function pointers
struct InputSrc {
struct InputSrc *prev;
int (*scan)(TPpContext*, struct InputSrc *, TPpToken *);
struct TokenStream {
TokenStream *next;
- char *name;
TokenBlock *head;
TokenBlock *current;
};
int CPPdefine(TPpToken * ppToken);
int CPPundef(TPpToken * ppToken);
int CPPelse(int matchelse, TPpToken * ppToken);
+ int extraTokenCheck(int atom, TPpToken* ppToken, int token);
int eval(int token, int prec, int *res, int *err, TPpToken * ppToken);
int CPPif (TPpToken * ppToken);
int CPPifdef(int defined, TPpToken * ppToken);
//
// From PpTokens.cpp
//
- char* idstr(const char *fstr, MemoryPool *pool);
TPpContext::TokenBlock* lNewBlock(TokenStream *fTok, MemoryPool *pool);
void lAddByte(TokenStream *fTok, unsigned char fVal);
int lReadByte(TokenStream *pTok);
- TokenStream *NewTokenStream(const char *name, MemoryPool *pool);
+ TokenStream *NewTokenStream(MemoryPool *pool);
void DeleteTokenStream(TokenStream *pTok);
- void RecordToken(TokenStream *pTok, int token, TPpToken * ppToken);
+ void RecordToken(TokenStream* pTok, int token, TPpToken* ppToken);
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 UngetToken(int token, TPpToken * ppToken);
- void DumpTokenStream(FILE *fp, TokenStream *s, TPpToken * ppToken);
+ void UngetToken(int token, TPpToken* ppToken);
struct TokenInputSrc {
InputSrc base;
- TokenStream *tokens;
- int (*final)(TPpContext *);
+ TokenStream *tokens;
+ int (*final)(TPpContext *);
};
static int scan_token(TPpContext*, TokenInputSrc *in, TPpToken * ppToken);
struct UngotToken {
InputSrc base;
- int token;
- TPpToken lval;
+ int token;
+ TPpToken lval;
};
static int reget_token(TPpContext *, UngotToken *t, TPpToken * ppToken);
TInputScanner* input;
};
int InitScanner(TPpContext *cpp);
- static int str_getch(TPpContext*, StringInputSrc *in);
- static void str_ungetch(TPpContext*, StringInputSrc *in, int ch, TPpToken *type);
+ static int sourceGetCh(TPpContext*, StringInputSrc *in);
+ static void sourceUngetCh(TPpContext*, StringInputSrc *in, int ch, TPpToken *type);
int ScanFromString(char *s);
- int check_EOF(int token);
+ bool check_EOF(int token);
int lFloatConst(char *str, int len, int ch, TPpToken * ppToken);
- static int byte_scan(TPpContext*, InputSrc *in, TPpToken * ppToken);
+ static int sourceScan(TPpContext*, InputSrc *in, TPpToken * ppToken);
//
// From PpAtom.cpp
return 1;
}
-int TPpContext::str_getch(TPpContext* pp, StringInputSrc *in)
+int TPpContext::sourceGetCh(TPpContext* pp, StringInputSrc *in)
{
int ch = in->input->get();
return ch;
}
-void TPpContext::str_ungetch(TPpContext* pp, StringInputSrc *in, int ch, TPpToken *type)
+void TPpContext::sourceUngetCh(TPpContext* pp, StringInputSrc *in, int ch, TPpToken *type)
{
in->input->unget();
}
* letter 'e', or a precision ending (e.g., F or LF).
*/
-int TPpContext::lFloatConst(char *str, int len, int ch, TPpToken * ppToken)
+int TPpContext::lFloatConst(char* str, int len, int ch, TPpToken* ppToken)
{
bool HasDecimalOrExponent = false;
int declen, exp, ExpSign;
return CPP_DOUBLECONSTANT;
else
return CPP_FLOATCONSTANT;
-} // lFloatConst
-
-///////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////// Normal Scanner //////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////
+}
-int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * ppToken)
+//
+// Scanner used to tokenize source stream.
+//
+int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
{
char tokenText[TPpToken::maxTokenLength + 1];
int AlreadyComplained = 0;
switch (ch) {
default:
return ch; // Single character token
- case EOF:
- return EOF;
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O':
}
}
}
-} // byte_scan
+}
+//
+// Return string pointer to next token.
+// Return 0 when no more tokens.
+//
const char* TPpContext::tokenize(TPpToken* ppToken)
{
int token = '\n';
for(;;) {
-
const char* tokenString = 0;
token = currentInput->scan(this, currentInput, ppToken);
ppToken->token = token;
else if (token == CPP_INTCONSTANT || token == CPP_UINTCONSTANT ||
token == CPP_FLOATCONSTANT || token == CPP_DOUBLECONSTANT)
tokenString = ppToken->name;
- else
+ else if (token == CPP_STRCONSTANT) {
+ parseContext.error(ppToken->loc, "string literals not supported", "\"\"", "");
+ tokenString = 0;
+ } else if (token == '\'') {
+ parseContext.error(ppToken->loc, "character literals not supported", "\'", "");
+ tokenString = 0;
+ } else
tokenString = GetAtomString(token);
if (tokenString) {
return tokenString;
}
}
-
- return 0;
-} // PpTokenize
+}
//Checks if the token just read is EOF or not.
-int TPpContext::check_EOF(int token)
+bool TPpContext::check_EOF(int token)
{
if (token == EOF) {
if (ifdepth > 0)
- parseContext.error(parseContext.getCurrentLoc(), "missing #endif", "#if", "");
- return 1;
+ parseContext.error(parseContext.getCurrentLoc(), "missing #endif", "", "");
+
+ return true;
}
- return 0;
+
+ return false;
}
} // end namespace glslang
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\****************************************************************************/
+
//
-// tokens.c
+// For recording and playing back the stream of tokens in a macro definition.
//
+
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS
#define snprintf sprintf_s
namespace glslang {
-///////////////////////////////////////////////////////////////////////////////////////////////
-//////////////////////// Preprocessor and Token Recorder and Playback: ////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-/*
-* idstr()
-* Copy a string to a malloc'ed block and convert it into something suitable
-* for an ID
-*
-*/
-
-char* TPpContext::idstr(const char *fstr, MemoryPool *pool)
-{
- size_t len;
- char *str, *t;
- const char *f;
-
- len = strlen(fstr);
- if (!pool)
- str = (char *) malloc(len + 1);
- else
- str = (char *) mem_Alloc(pool, len + 1);
-
- for (f=fstr, t=str; *f; f++) {
- if (isalnum(*f)) *t++ = *f;
- else if (*f == '.' || *f == '/') *t++ = '_';
- }
- *t = 0;
- return str;
-} // idstr
-
-
-/*
-* lNewBlock()
-*
-*/
-
TPpContext::TokenBlock* TPpContext::lNewBlock(TokenStream *fTok, MemoryPool *pool)
{
TokenBlock *lBlock;
fTok->current = lBlock;
return lBlock;
-} // lNewBlock
-
-/*
-* lAddByte()
-*
-*/
+}
void TPpContext::lAddByte(TokenStream *fTok, unsigned char fVal)
{
if (lBlock->count >= lBlock->max)
lBlock = lNewBlock(fTok, 0);
lBlock->data[lBlock->count++] = fVal;
-} // lAddByte
-
+}
/*
-* lReadByte() - Get the next byte from a stream.
-*
+* Get the next byte from a stream.
*/
-
int TPpContext::lReadByte(TokenStream *pTok)
{
TokenBlock *lBlock;
lval = lBlock->data[lBlock->current++];
}
return lval;
-} // lReadByte
-
-/////////////////////////////////////// Global Functions://////////////////////////////////////
-
-/*
-* NewTokenStream()
-*
-*/
+}
-TPpContext::TokenStream* TPpContext::NewTokenStream(const char *name, MemoryPool *pool)
+//
+// Make a token stream (used for reprocessing macros).
+//
+TPpContext::TokenStream* TPpContext::NewTokenStream(MemoryPool *pool)
{
TokenStream *pTok;
else
pTok = (TokenStream*)mem_Alloc(pool, sizeof(TokenStream));
pTok->next = NULL;
- pTok->name = idstr(name, pool);
pTok->head = NULL;
pTok->current = NULL;
lNewBlock(pTok, pool);
return pTok;
-} // NewTokenStream
-
-/*
-* DeleteTokenStream()
-*
-*/
+}
void TPpContext::DeleteTokenStream(TokenStream *pTok)
{
free(pBlock);
pBlock = nBlock;
}
- if (pTok->name)
- free(pTok->name);
free(pTok);
}
-} // DeleteTokenStream
+}
/*
-* RecordToken() - Add a token to the end of a list for later playback or printout.
-*
+* Add a token to the end of a list for later playback.
*/
-
-void TPpContext::RecordToken(TokenStream *pTok, int token, TPpToken * ppToken)
+void TPpContext::RecordToken(TokenStream *pTok, int token, TPpToken* ppToken)
{
const char *s;
char *str = NULL;
lAddByte(pTok, (unsigned char)(token & 0x7f));
switch (token) {
case CPP_IDENTIFIER:
- case CPP_TYPEIDENTIFIER:
case CPP_STRCONSTANT:
s = GetAtomString(ppToken->atom);
while (*s)
break;
case '(':
lAddByte(pTok, (unsigned char)(ppToken->ival ? 1 : 0));
+ break;
default:
break;
}
-} // RecordToken
+}
/*
-* RewindTokenStream() - Reset a token stream in preperation for reading.
-*
+* Reset a token stream in preperation for reading.
*/
-
void TPpContext::RewindTokenStream(TokenStream *pTok)
{
if (pTok->head) {
pTok->current = pTok->head;
pTok->current->current = 0;
}
-} // RewindTokenStream
+}
/*
-* ReadToken() - Read the next token from a stream.
-*
+* Read the next token from a token stream (not the source stream, but stream used to hold a tokenized macro).
*/
-
int TPpContext::ReadToken(TokenStream *pTok, TPpToken *ppToken)
{
- //TODO: preprocessor simplification: why is this different than byte_scan
-
char tokenText[TPpToken::maxTokenLength + 1];
int ltoken, len;
char ch;
if (ltoken > 127)
ltoken += 128;
switch (ltoken) {
- case CPP_IDENTIFIER:
- case CPP_TYPEIDENTIFIER:
- len = 0;
- ch = lReadByte(pTok);
- while ((ch >= 'a' && ch <= 'z') ||
- (ch >= 'A' && ch <= 'Z') ||
- (ch >= '0' && ch <= '9') ||
- ch == '_')
- {
- if (len < TPpToken::maxTokenLength) {
- tokenText[len] = ch;
- len++;
- ch = lReadByte(pTok);
- } else {
- parseContext.error(ppToken->loc,"name too long", "", "");
- break;
- }
- }
- tokenText[len] = '\0';
- assert(ch == '\0');
- ppToken->atom = LookUpAddString(tokenText);
- return CPP_IDENTIFIER;
+ case '(':
+ ppToken->ival = lReadByte(pTok);
break;
case CPP_STRCONSTANT:
- len = 0;
- while ((ch = lReadByte(pTok)) != 0) {
- if (len < TPpToken::maxTokenLength)
- tokenText[len++] = ch;
- else
- break;
- }
-
- tokenText[len] = 0;
- ppToken->atom = LookUpAddString(tokenText);
- break;
+ case CPP_IDENTIFIER:
case CPP_FLOATCONSTANT:
case CPP_DOUBLECONSTANT:
- len = 0;
- ch = lReadByte(pTok);
- while ((ch >= '0' && ch <= '9') || ch=='e' || ch=='E' || ch=='.' || ch=='+' || ch=='-' || ch=='l' || ch=='L' || ch=='f'|| ch=='F')
- {
- if (len < TPpToken::maxTokenLength) {
- tokenText[len] = ch;
- len++;
- ch = lReadByte(pTok);
- } else {
- parseContext.error(ppToken->loc,"float literal too long", "", "");
- break;
- }
- }
- tokenText[len] = '\0';
- assert(ch == '\0');
- strcpy(ppToken->name, tokenText);
- ppToken->dval = atof(ppToken->name);
- break;
case CPP_INTCONSTANT:
case CPP_UINTCONSTANT:
len = 0;
ch = lReadByte(pTok);
- while ((ch >= '0' && ch <= '9') || ch == 'u' || ch == 'U')
- {
+ while (ch != 0) {
if (len < TPpToken::maxTokenLength) {
tokenText[len] = ch;
len++;
ch = lReadByte(pTok);
} else {
- parseContext.error(ppToken->loc,"integer literal too long", "", "");
+ parseContext.error(ppToken->loc, "token too long", "", "");
break;
}
}
- tokenText[len] = '\0';
- assert(ch == '\0');
- strcpy(ppToken->name,tokenText);
- ppToken->ival = atoi(ppToken->name);
- break;
- case '(':
- ppToken->ival = lReadByte(pTok);
- break;
+ tokenText[len] = 0;
+
+ switch (ltoken) {
+ case CPP_IDENTIFIER:
+ case CPP_STRCONSTANT:
+ ppToken->atom = LookUpAddString(tokenText);
+ break;
+ case CPP_FLOATCONSTANT:
+ case CPP_DOUBLECONSTANT:
+ strcpy(ppToken->name, tokenText);
+ ppToken->dval = atof(ppToken->name);
+ break;
+ case CPP_INTCONSTANT:
+ case CPP_UINTCONSTANT:
+ strcpy(ppToken->name, tokenText);
+ if (len > 0 && tokenText[0] == '0') {
+ if (len > 1 && tokenText[1] == 'x' || tokenText[1] == 'X')
+ ppToken->ival = strtol(ppToken->name, 0, 16);
+ else
+ ppToken->ival = strtol(ppToken->name, 0, 8);
+ } else
+ ppToken->ival = atoi(ppToken->name);
+ break;
+ }
}
return ltoken;
}
return EOF;
-} // ReadToken
+}
int TPpContext::scan_token(TPpContext* pp, TokenInputSrc *in, TPpToken * ppToken)
{
return token;
}
-typedef int (*scanFnPtr_t);
-
-void TPpContext::UngetToken(int token, TPpToken * ppToken)
+void TPpContext::UngetToken(int token, TPpToken* ppToken)
{
UngotToken *t = (UngotToken *) malloc(sizeof(UngotToken));
memset(t, 0, sizeof(UngotToken));
currentInput = &t->base;
}
-
-void TPpContext::DumpTokenStream(FILE *fp, TokenStream *s, TPpToken * ppToken)
-{
- int token;
-
- if (fp == 0) fp = stdout;
- RewindTokenStream(s);
- while ((token = ReadToken(s, ppToken)) > 0) {
- switch (token) {
- case CPP_IDENTIFIER:
- case CPP_TYPEIDENTIFIER:
- printf("%s ", GetAtomString(ppToken->atom));
- break;
- case CPP_STRCONSTANT:
- printf("\"%s\"", GetAtomString(ppToken->atom));
- break;
- case CPP_FLOATCONSTANT:
- case CPP_DOUBLECONSTANT:
- printf("%g9.6 ", ppToken->dval);
- break;
- case CPP_INTCONSTANT:
- case CPP_UINTCONSTANT:
- printf("%d ", ppToken->ival);
- break;
- default:
- if (token >= 127)
- printf("%s ", GetAtomString(token));
- else
- printf("%c", token);
- break;
- }
- }
-}
-
} // end namespace glslang
#define CPP_OR_OP 276
#define CPP_INC_OP 277
#define CPP_STRCONSTANT 278
-#define CPP_TYPEIDENTIFIER 279
#define CPP_RIGHT_ASSIGN 280
#define CPP_LEFT_ASSIGN 281
#define CPP_AND_ASSIGN 282