Scanning: 1) rationalize end-of-input everywhere, 2) prevent infinite loop at end-of-input, 3) use positive chars.

Fixes issue #25. (char 255 aliased to -1 and missing tests for end of input).

1) All layers of input scanning now share a single EndOfInput value.
This avoids translation of it across layers of encapsulation.

2) Some places looking for end of line were not stopping on EndOfInput.

3) Use of "char" for the input made char values > 127 be negative numbers.
This allowed for aliasing of 255 to -1, etc.  This is fixed by using
unsigned char.
This commit is contained in:
John Kessenich 2015-07-27 09:37:55 -06:00
parent 91b977e172
commit c777fc2c4c
15 changed files with 134 additions and 112 deletions

6
Test/badChars.frag Normal file
View File

@ -0,0 +1,6 @@
#ifþ
#endif
#error AÿB
#if
#endif
int aÿ

View File

@ -0,0 +1,26 @@
badChars.frag
ERROR: 0:1: 'preprocessor evaluation' : bad expression
ERROR: 0:1: '#if' : unexpected tokens following directive
ERROR: 0:3: '#error' : A <bad token> B
ERROR: 0:4: 'preprocessor evaluation' : bad expression
ERROR: 0:4: '#if' : unexpected tokens following directive
ERROR: 0:6: 'ÿ' : unexpected token
ERROR: 0:7: '' : syntax error
ERROR: 7 compilation errors. No code generated.
Shader version: 100
ERROR: node is still EOpNull!
0:? Linker Objects
0:? 'a' (global mediump int)
Linked fragment stage:
ERROR: Linking fragment stage: Missing entry point: Each stage requires one "void main()" entry point
Shader version: 100
ERROR: node is still EOpNull!
0:? Linker Objects
0:? 'a' (global mediump int)

View File

@ -5,19 +5,19 @@ 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:87: 'macro expansion' : end of line in macro substitution: foobar ERROR: 0:87: 'macro expansion' : End of line in macro substitution: foobar
ERROR: 0:88: 'preprocessor evaluation' : can't evaluate expression ERROR: 0:88: 'preprocessor evaluation' : can't evaluate expression
ERROR: 0:88: 'preprocessor evaluation' : bad expression ERROR: 0:88: 'preprocessor evaluation' : bad expression
ERROR: 0:88: '#if' : unexpected tokens following directive ERROR: 0:88: '#if' : unexpected tokens following directive
ERROR: 0:92: 'macro expansion' : end of line in macro substitution: foobar 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' : can't evaluate expression
ERROR: 0:93: 'preprocessor evaluation' : bad expression ERROR: 0:93: 'preprocessor evaluation' : bad expression
ERROR: 0:93: '#if' : unexpected tokens following directive ERROR: 0:93: '#if' : unexpected tokens following directive
ERROR: 0:99: 'macro expansion' : end of line in macro substitution: foobar 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' : 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:101: 'macro expansion' : end of line in macro substitution: foobar ERROR: 0:101: 'macro expansion' : End of line in macro substitution: foobar
ERROR: 0:102: 'preprocessor evaluation' : can't evaluate expression ERROR: 0:102: 'preprocessor evaluation' : can't evaluate expression
ERROR: 0:102: 'preprocessor evaluation' : bad expression ERROR: 0:102: 'preprocessor evaluation' : bad expression
ERROR: 0:102: '#if' : unexpected tokens following directive ERROR: 0:102: '#if' : unexpected tokens following directive

View File

@ -3,7 +3,7 @@ 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: 0:177: 'macro expansion' : EOF in macro FUNC ERROR: 0:177: 'macro expansion' : End of input in macro FUNC
ERROR: 0:178: '' : syntax error ERROR: 0:178: '' : syntax error
ERROR: 6 compilation errors. No code generated. ERROR: 6 compilation errors. No code generated.

View File

@ -13,10 +13,10 @@ 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
WARNING: 0:62: 'line continuation' : used at end of comment; the following line is still part of the comment 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:111: 'macro expansion' : End of line in macro substitution: FOOM
ERROR: 0:112: 'preprocessor evaluation' : can't evaluate expression ERROR: 0:112: 'preprocessor evaluation' : can't evaluate expression
ERROR: 0:112: '#if' : unexpected tokens following directive ERROR: 0:112: '#if' : unexpected tokens following directive
ERROR: 0:117: 'macro expansion' : end of line in macro substitution: FOOM ERROR: 0:117: 'macro expansion' : End of line in macro substitution: FOOM
ERROR: 0:118: 'preprocessor evaluation' : can't evaluate expression ERROR: 0:118: 'preprocessor evaluation' : can't evaluate expression
ERROR: 0:118: '#if' : unexpected tokens following directive ERROR: 0:118: '#if' : unexpected tokens following directive
ERROR: 0:150: '' : syntax error ERROR: 0:150: '' : syntax error

View File

@ -25,6 +25,7 @@ cppSimple.vert
cppIndent.vert cppIndent.vert
cppNest.vert cppNest.vert
cppComplexExpr.vert cppComplexExpr.vert
badChars.frag
pointCoord.frag pointCoord.frag
array.frag array.frag
array100.frag array100.frag

View File

@ -168,7 +168,7 @@ void TParseContext::parserError(const char* s)
{ {
if (afterEOF) { if (afterEOF) {
if (tokensBeforeEOF == 1) if (tokensBeforeEOF == 1)
error(getCurrentLoc(), "", "pre-mature EOF", s, ""); error(getCurrentLoc(), "", "premature end of input", s, "");
} else } else
error(getCurrentLoc(), "", "", s, ""); error(getCurrentLoc(), "", "", s, "");
} }

View File

@ -81,10 +81,10 @@ bool TInputScanner::consumeComment()
get(); // consume the second '/' get(); // consume the second '/'
c = get(); c = get();
do { do {
while (c > 0 && c != '\\' && c != '\r' && c != '\n') while (c != EndOfInput && c != '\\' && c != '\r' && c != '\n')
c = get(); c = get();
if (c <= 0 || c == '\r' || c == '\n') { if (c == EndOfInput || c == '\r' || c == '\n') {
while (c == '\r' || c == '\n') while (c == '\r' || c == '\n')
c = get(); c = get();
@ -104,7 +104,7 @@ bool TInputScanner::consumeComment()
} while (true); } while (true);
// put back the last non-comment character // put back the last non-comment character
if (c > 0) if (c != EndOfInput)
unget(); unget();
return true; return true;
@ -114,7 +114,7 @@ bool TInputScanner::consumeComment()
get(); // consume the '*' get(); // consume the '*'
c = get(); c = get();
do { do {
while (c > 0 && c != '*') while (c != EndOfInput && c != '*')
c = get(); c = get();
if (c == '*') { if (c == '*') {
c = get(); c = get();
@ -142,7 +142,7 @@ void TInputScanner::consumeWhitespaceComment(bool& foundNonSpaceTab)
// if not starting a comment now, then done // if not starting a comment now, then done
int c = peek(); int c = peek();
if (c != '/' || c < 0) if (c != '/' || c == EndOfInput)
return; return;
// skip potential comment // skip potential comment
@ -188,10 +188,10 @@ bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstT
} else } else
do { do {
c = get(); c = get();
} while (c > 0 && c != '\n' && c != '\r'); } while (c != EndOfInput && c != '\n' && c != '\r');
while (peek() == '\n' || peek() == '\r') while (peek() == '\n' || peek() == '\r')
get(); get();
if (peek() < 0) if (peek() == EndOfInput)
return true; return true;
} }
lookingInMiddle = true; lookingInMiddle = true;
@ -249,12 +249,12 @@ bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstT
char profileString[maxProfileLength]; char profileString[maxProfileLength];
int profileLength; int profileLength;
for (profileLength = 0; profileLength < maxProfileLength; ++profileLength) { for (profileLength = 0; profileLength < maxProfileLength; ++profileLength) {
if (c < 0 || c == ' ' || c == '\t' || c == '\n' || c == '\r') if (c == EndOfInput || c == ' ' || c == '\t' || c == '\n' || c == '\r')
break; break;
profileString[profileLength] = (char)c; profileString[profileLength] = (char)c;
c = get(); c = get();
} }
if (c > 0 && c != ' ' && c != '\t' && c != '\n' && c != '\r') { if (c != EndOfInput && c != ' ' && c != '\t' && c != '\n' && c != '\r') {
versionNotFirst = true; versionNotFirst = true;
continue; continue;
} }
@ -600,7 +600,7 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
case PpAtomConstDouble: parserToken->sType.lex.d = ppToken.dval; return DOUBLECONSTANT; case PpAtomConstDouble: parserToken->sType.lex.d = ppToken.dval; return DOUBLECONSTANT;
case PpAtomIdentifier: return tokenizeIdentifier(); case PpAtomIdentifier: return tokenizeIdentifier();
case EOF: return 0; case EndOfInput: return 0;
default: default:
char buf[2]; char buf[2];

View File

@ -40,6 +40,11 @@
namespace glslang { namespace glslang {
// Use a global end-of-input character, so no tranlation is needed across
// layers of encapsulation. Characters are all 8 bit, and positive, so there is
// no aliasing of character 255 onto -1, for example.
const int EndOfInput = -1;
// //
// A character scanner that seamlessly, on read-only strings, reads across an // A character scanner that seamlessly, on read-only strings, reads across an
// array of strings without assuming null termination. // array of strings without assuming null termination.
@ -47,7 +52,9 @@ namespace glslang {
class TInputScanner { class TInputScanner {
public: public:
TInputScanner(int n, const char* const s[], size_t L[], int b = 0, int f = 0) : 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) numSources(n),
sources(reinterpret_cast<const unsigned char* const *>(s)), // up to this point, common usage is "char*", but now we need positive 8-bit characters
lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f)
{ {
loc = new TSourceLoc[numSources]; loc = new TSourceLoc[numSources];
loc[currentSource].string = -stringBias; loc[currentSource].string = -stringBias;
@ -60,14 +67,11 @@ public:
delete [] loc; delete [] loc;
} }
// return of -1 means end of strings,
// anything else is the next character
// retrieve the next character and advance one character // retrieve the next character and advance one character
int get() int get()
{ {
if (currentSource >= numSources) if (currentSource >= numSources)
return -1; return EndOfInput;
int ret = peek(); int ret = peek();
++loc[currentSource].column; ++loc[currentSource].column;
@ -84,7 +88,7 @@ public:
int peek() int peek()
{ {
if (currentSource >= numSources) if (currentSource >= numSources)
return -1; return EndOfInput;
// Make sure we do not read off the end of a string. // Make sure we do not read off the end of a string.
// N.B. Sources can have a length of 0. // N.B. Sources can have a length of 0.
int sourceToRead = currentSource; int sourceToRead = currentSource;
@ -93,9 +97,11 @@ public:
charToRead = 0; charToRead = 0;
sourceToRead += 1; sourceToRead += 1;
if (sourceToRead >= numSources) { if (sourceToRead >= numSources) {
return -1; return EndOfInput;
} }
} }
// Here, we care about making negative valued characters positive
return sources[sourceToRead][charToRead]; return sources[sourceToRead][charToRead];
} }
@ -106,17 +112,17 @@ public:
--currentChar; --currentChar;
--loc[currentSource].column; --loc[currentSource].column;
if (loc[currentSource].column < 0) { if (loc[currentSource].column < 0) {
// We've moved back past a new line. Find the // We've moved back past a new line. Find the
// previous newline (or start of the file) to compute // previous newline (or start of the file) to compute
// the column count on the now current line. // the column count on the now current line.
size_t ch = currentChar; size_t chIndex = currentChar;
while(ch > 0) { while (chIndex > 0) {
if (sources[currentSource][ch] == '\n') { if (sources[currentSource][chIndex] == '\n') {
break; break;
}
--chIndex;
} }
--ch; loc[currentSource].column = (int)(currentChar - chIndex);
}
loc[currentSource].column = (int)(currentChar - ch);
} }
} else { } else {
do { do {
@ -170,9 +176,9 @@ protected:
} }
} }
int numSources; // number of strings in source int numSources; // number of strings in source
const char* const *sources; // array of strings const unsigned char* const *sources; // array of strings; must be converted to positive values on use, to avoid aliasing with -1 as EndOfInput
const size_t *lengths; // length of each string const size_t *lengths; // length of each string
int currentSource; int currentSource;
size_t currentChar; size_t currentChar;

View File

@ -731,7 +731,7 @@ struct DoPreprocessing {
outputStream << "#error " << errorMessage; outputStream << "#error " << errorMessage;
}); });
int lastToken = EOF; // lastToken records the last token processed. int lastToken = EndOfInput; // lastToken records the last token processed.
while (const char* tok = ppContext.tokenize(&token)) { while (const char* tok = ppContext.tokenize(&token)) {
bool isNewString = lineSync.syncToMostRecentString(); bool isNewString = lineSync.syncToMostRecentString();
bool isNewLine = lineSync.syncToLine(token.loc.line); bool isNewLine = lineSync.syncToLine(token.loc.line);
@ -746,7 +746,7 @@ struct DoPreprocessing {
// Output a space in between tokens, but not at the start of a line, // Output a space in between tokens, but not at the start of a line,
// and also not around special tokens. This helps with readability // and also not around special tokens. This helps with readability
// and consistency. // and consistency.
if (!isNewString && !isNewLine && lastToken != -1 && if (!isNewString && !isNewLine && lastToken != EndOfInput &&
(unNeededSpaceTokens.find((char)token.token) == std::string::npos) && (unNeededSpaceTokens.find((char)token.token) == std::string::npos) &&
(unNeededSpaceTokens.find((char)lastToken) == std::string::npos) && (unNeededSpaceTokens.find((char)lastToken) == std::string::npos) &&
(noSpaceBeforeTokens.find((char)token.token) == std::string::npos)) { (noSpaceBeforeTokens.find((char)token.token) == std::string::npos)) {

View File

@ -164,7 +164,7 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
// record the definition of the macro // record the definition of the macro
TSourceLoc defineLoc = ppToken->loc; // because ppToken is going to go to the next line before we report errors TSourceLoc defineLoc = ppToken->loc; // because ppToken is going to go to the next line before we report errors
mac.body = new TokenStream; mac.body = new TokenStream;
while (token != '\n') { while (token != '\n' && token != EndOfInput) {
RecordToken(mac.body, token, ppToken); RecordToken(mac.body, token, ppToken);
token = scanToken(ppToken); token = scanToken(ppToken);
if (token != '\n' && ppToken->space) if (token != '\n' && ppToken->space)
@ -245,13 +245,13 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
int depth = 0; int depth = 0;
int token = scanToken(ppToken); int token = scanToken(ppToken);
while (token != EOF) { while (token != EndOfInput) {
if (token != '#') { if (token != '#') {
while (token != '\n' && token != EOF) while (token != '\n' && token != EndOfInput)
token = scanToken(ppToken); token = scanToken(ppToken);
if (token == EOF) if (token == EndOfInput)
return EOF; return token;
token = scanToken(ppToken); token = scanToken(ppToken);
continue; continue;
@ -314,7 +314,7 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
// Call when there should be no more tokens left on a line. // Call when there should be no more tokens left on a line.
int TPpContext::extraTokenCheck(int atom, TPpToken* ppToken, int token) int TPpContext::extraTokenCheck(int atom, TPpToken* ppToken, int token)
{ {
if (token != '\n') { if (token != '\n' && token != EndOfInput) {
static const char* message = "unexpected tokens following directive"; static const char* message = "unexpected tokens following directive";
const char* label; const char* label;
@ -336,7 +336,7 @@ int TPpContext::extraTokenCheck(int atom, TPpToken* ppToken, int token)
else else
parseContext.ppError(ppToken->loc, message, label, ""); parseContext.ppError(ppToken->loc, message, label, "");
while (token != '\n') while (token != '\n' && token != EndOfInput)
token = scanToken(ppToken); token = scanToken(ppToken);
} }
@ -586,7 +586,7 @@ int TPpContext::CPPifdef(int defined, TPpToken* ppToken)
token = scanToken(ppToken); token = scanToken(ppToken);
if (token != '\n') { if (token != '\n') {
parseContext.ppError(ppToken->loc, "unexpected tokens following #ifdef directive - expected a newline", "#ifdef", ""); parseContext.ppError(ppToken->loc, "unexpected tokens following #ifdef directive - expected a newline", "#ifdef", "");
while (token != '\n') while (token != '\n' && token != EndOfInput)
token = scanToken(ppToken); token = scanToken(ppToken);
} }
if (((s && !s->mac.undef) ? 1 : 0) != defined) if (((s && !s->mac.undef) ? 1 : 0) != defined)
@ -648,7 +648,7 @@ int TPpContext::CPPerror(TPpToken* ppToken)
std::string message; std::string message;
TSourceLoc loc = ppToken->loc; TSourceLoc loc = ppToken->loc;
while (token != '\n') { while (token != '\n' && token != EndOfInput) {
if (token == PpAtomConstInt || token == PpAtomConstUint || if (token == PpAtomConstInt || token == PpAtomConstUint ||
token == PpAtomConstFloat || token == PpAtomConstDouble) { token == PpAtomConstFloat || token == PpAtomConstDouble) {
message.append(ppToken->name); message.append(ppToken->name);
@ -675,7 +675,7 @@ int TPpContext::CPPpragma(TPpToken* ppToken)
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 = scanToken(ppToken); int token = scanToken(ppToken);
while (token != '\n' && token != EOF) { while (token != '\n' && token != EndOfInput) {
switch (token) { switch (token) {
case PpAtomIdentifier: case PpAtomIdentifier:
case PpAtomConstInt: case PpAtomConstInt:
@ -692,7 +692,7 @@ int TPpContext::CPPpragma(TPpToken* ppToken)
token = scanToken(ppToken); token = scanToken(ppToken);
} }
if (token == EOF) if (token == EndOfInput)
parseContext.ppError(loc, "directive must end with a newline", "#pragma", ""); parseContext.ppError(loc, "directive must end with a newline", "#pragma", "");
else else
parseContext.handlePragma(loc, tokens); parseContext.handlePragma(loc, tokens);
@ -810,7 +810,7 @@ int TPpContext::readCPPline(TPpToken* ppToken)
parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", ""); parseContext.ppError(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 = scanToken(ppToken); token = scanToken(ppToken);
while (token != '\n') while (token != '\n' && token != EndOfInput)
token = scanToken(ppToken); token = scanToken(ppToken);
token = CPPelse(0, ppToken); token = CPPelse(0, ppToken);
break; break;
@ -854,10 +854,10 @@ int TPpContext::readCPPline(TPpToken* ppToken)
parseContext.ppError(ppToken->loc, "invalid directive:", "#", ppToken->name); parseContext.ppError(ppToken->loc, "invalid directive:", "#", ppToken->name);
break; break;
} }
} else if (token != '\n' && token != EOF) } else if (token != '\n' && token != EndOfInput)
parseContext.ppError(ppToken->loc, "invalid directive", "#", ""); parseContext.ppError(ppToken->loc, "invalid directive", "#", "");
while (token != '\n' && token != 0 && token != EOF) while (token != '\n' && token != EndOfInput)
token = scanToken(ppToken); token = scanToken(ppToken);
return token; return token;
@ -872,9 +872,9 @@ TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream* a, TPpToken* p
token = ReadToken(a, ppToken); token = ReadToken(a, ppToken);
if (token == PpAtomIdentifier && LookUpSymbol(ppToken->atom)) if (token == PpAtomIdentifier && LookUpSymbol(ppToken->atom))
break; break;
} while (token != tInput::endOfInput); } while (token != EndOfInput);
if (token == tInput::endOfInput) if (token == EndOfInput)
return a; return a;
n = new TokenStream; n = new TokenStream;
@ -914,17 +914,17 @@ int TPpContext::tMacroInput::scan(TPpToken* ppToken)
} }
} }
if (token == endOfInput) if (token == EndOfInput)
mac->busy = 0; mac->busy = 0;
return token; return token;
} }
// return a zero, for scanning a macro that was never defined // return a textual zero, for scanning a macro that was never defined
int TPpContext::tZeroInput::scan(TPpToken* ppToken) int TPpContext::tZeroInput::scan(TPpToken* ppToken)
{ {
if (done) if (done)
return endOfInput; return EndOfInput;
strcpy(ppToken->name, "0"); strcpy(ppToken->name, "0");
ppToken->ival = 0; ppToken->ival = 0;
@ -1013,14 +1013,14 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool
depth = 0; depth = 0;
while (1) { while (1) {
token = scanToken(ppToken); token = scanToken(ppToken);
if (token == EOF) { if (token == EndOfInput) {
parseContext.ppError(loc, "EOF in macro", "macro expansion", GetAtomString(atom)); parseContext.ppError(loc, "End of input in macro", "macro expansion", GetAtomString(atom));
delete in; delete in;
return 0; return 0;
} }
if (token == '\n') { if (token == '\n') {
if (! newLineOkay) { if (! newLineOkay) {
parseContext.ppError(loc, "end of line in macro substitution:", "macro expansion", GetAtomString(atom)); parseContext.ppError(loc, "End of line in macro substitution:", "macro expansion", GetAtomString(atom));
delete in; delete in;
return 0; return 0;
} }
@ -1055,7 +1055,7 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool
parseContext.ppError(loc, "Too few args in Macro", "macro expansion", GetAtomString(atom)); parseContext.ppError(loc, "Too few args in Macro", "macro expansion", GetAtomString(atom));
else if (token != ')') { else if (token != ')') {
depth=0; depth=0;
while (token != EOF && (depth > 0 || token != ')')) { while (token != EndOfInput && (depth > 0 || token != ')')) {
if (token == ')') if (token == ')')
depth--; depth--;
token = scanToken(ppToken); token = scanToken(ppToken);
@ -1063,8 +1063,8 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool
depth++; depth++;
} }
if (token == EOF) { if (token == EndOfInput) {
parseContext.ppError(loc, "EOF in macro", "macro expansion", GetAtomString(atom)); parseContext.ppError(loc, "End of input in macro", "macro expansion", GetAtomString(atom));
delete in; delete in;
return 0; return 0;
} }

View File

@ -144,18 +144,12 @@ int TPpContext::LookUpAddString(const char* s)
// //
const char* TPpContext::GetAtomString(int atom) const char* TPpContext::GetAtomString(int atom)
{ {
if (atom == 0) if ((size_t)atom >= stringMap.size())
return "<null atom>"; return "<bad token>";
if (atom < 0)
return "<EOF>";
if ((size_t)atom < stringMap.size()) {
if (stringMap[atom] == 0)
return "<invalid atom>";
else
return stringMap[atom]->c_str();
}
return "<invalid atom>"; const TString* atomString = stringMap[atom];
return atomString ? atomString->c_str() : "<bad token>";
} }
// //

View File

@ -134,8 +134,6 @@ public:
virtual int getch() = 0; virtual int getch() = 0;
virtual void ungetch() = 0; virtual void ungetch() = 0;
static const int endOfInput = -2;
protected: protected:
bool done; bool done;
TPpContext* pp; TPpContext* pp;
@ -210,21 +208,18 @@ protected:
// Get the next token from *stack* of input sources, popping input sources // 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. // 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. // Return EndOfInput when there are no more tokens to be found by doing this.
int scanToken(TPpToken* ppToken) int scanToken(TPpToken* ppToken)
{ {
int token = EOF; int token = EndOfInput;
while (! inputStack.empty()) { while (! inputStack.empty()) {
token = inputStack.back()->scan(ppToken); token = inputStack.back()->scan(ppToken);
if (token != tInput::endOfInput) if (token != EndOfInput)
break; break;
popInput(); popInput();
} }
if (token == tInput::endOfInput)
return EOF;
return token; return token;
} }
int getChar() { return inputStack.back()->getch(); } int getChar() { return inputStack.back()->getch(); }
@ -248,7 +243,7 @@ protected:
} }
virtual int scan(TPpToken*); virtual int scan(TPpToken*);
virtual int getch() { assert(0); return endOfInput; } virtual int getch() { assert(0); return EndOfInput; }
virtual void ungetch() { assert(0); } virtual void ungetch() { assert(0); }
MacroSymbol *mac; MacroSymbol *mac;
TVector<TokenStream*> args; TVector<TokenStream*> args;
@ -260,12 +255,12 @@ protected:
virtual int scan(TPpToken*) virtual int scan(TPpToken*)
{ {
if (done) if (done)
return endOfInput; return EndOfInput;
done = true; done = true;
return marker; return marker;
} }
virtual int getch() { assert(0); return endOfInput; } virtual int getch() { assert(0); return EndOfInput; }
virtual void ungetch() { assert(0); } virtual void ungetch() { assert(0); }
static const int marker = -3; static const int marker = -3;
}; };
@ -274,7 +269,7 @@ protected:
public: public:
tZeroInput(TPpContext* pp) : tInput(pp) { } tZeroInput(TPpContext* pp) : tInput(pp) { }
virtual int scan(TPpToken*); virtual int scan(TPpToken*);
virtual int getch() { assert(0); return endOfInput; } virtual int getch() { assert(0); return EndOfInput; }
virtual void ungetch() { assert(0); } virtual void ungetch() { assert(0); }
}; };
@ -328,7 +323,7 @@ protected:
public: public:
tTokenInput(TPpContext* pp, TokenStream* t) : tInput(pp), tokens(t) { } tTokenInput(TPpContext* pp, TokenStream* t) : tInput(pp), tokens(t) { }
virtual int scan(TPpToken *); virtual int scan(TPpToken *);
virtual int getch() { assert(0); return endOfInput; } virtual int getch() { assert(0); return EndOfInput; }
virtual void ungetch() { assert(0); } virtual void ungetch() { assert(0); }
protected: protected:
TokenStream *tokens; TokenStream *tokens;
@ -338,7 +333,7 @@ protected:
public: public:
tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { } tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { }
virtual int scan(TPpToken *); virtual int scan(TPpToken *);
virtual int getch() { assert(0); return endOfInput; } virtual int getch() { assert(0); return EndOfInput; }
virtual void ungetch() { assert(0); } virtual void ungetch() { assert(0); }
protected: protected:
int token; int token;

View File

@ -253,12 +253,9 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
len = 0; len = 0;
switch (ch) { switch (ch) {
default: default:
// Single character token, including '#' and '\' (escaped newlines are handled at a lower level, so this is just a '\' token) // Single character token, including EndOfInput, '#' and '\' (escaped newlines are handled at a lower level, so this is just a '\' token)
return ch; return ch;
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':
@ -590,28 +587,25 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
pp->inComment = true; pp->inComment = true;
do { do {
ch = pp->getChar(); ch = pp->getChar();
} while (ch != '\n' && ch != EOF); } while (ch != '\n' && ch != EndOfInput);
ppToken->space = true; ppToken->space = true;
pp->inComment = false; pp->inComment = false;
if (ch == EOF)
return endOfInput;
return ch; return ch;
} else if (ch == '*') { } else if (ch == '*') {
ch = pp->getChar(); ch = pp->getChar();
do { do {
while (ch != '*') { while (ch != '*') {
if (ch == EOF) { if (ch == EndOfInput) {
pp->parseContext.ppError(ppToken->loc, "EOF in comment", "comment", ""); pp->parseContext.ppError(ppToken->loc, "End of input in comment", "comment", "");
return endOfInput; return ch;
} }
ch = pp->getChar(); ch = pp->getChar();
} }
ch = pp->getChar(); ch = pp->getChar();
if (ch == EOF) { if (ch == EndOfInput) {
pp->parseContext.ppError(ppToken->loc, "EOF in comment", "comment", ""); pp->parseContext.ppError(ppToken->loc, "End of input in comment", "comment", "");
return endOfInput; return ch;
} }
} while (ch != '/'); } while (ch != '/');
ppToken->space = true; ppToken->space = true;
@ -626,7 +620,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
break; break;
case '"': case '"':
ch = pp->getChar(); ch = pp->getChar();
while (ch != '"' && ch != '\n' && ch != EOF) { while (ch != '"' && ch != '\n' && ch != EndOfInput) {
if (len < MaxTokenLength) { if (len < MaxTokenLength) {
tokenText[len] = (char)ch; tokenText[len] = (char)ch;
len++; len++;
@ -637,7 +631,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
tokenText[len] = '\0'; tokenText[len] = '\0';
if (ch != '"') { if (ch != '"') {
pp->ungetChar(); pp->ungetChar();
pp->parseContext.ppError(ppToken->loc, "end of line in string", "string", ""); pp->parseContext.ppError(ppToken->loc, "End of line in string", "string", "");
} }
return PpAtomConstString; return PpAtomConstString;
} }
@ -660,14 +654,14 @@ const char* TPpContext::tokenize(TPpToken* ppToken)
for(;;) { for(;;) {
token = scanToken(ppToken); token = scanToken(ppToken);
ppToken->token = token; ppToken->token = token;
if (token == EOF) { if (token == EndOfInput) {
missingEndifCheck(); missingEndifCheck();
return nullptr; return nullptr;
} }
if (token == '#') { if (token == '#') {
if (previous_token == '\n') { if (previous_token == '\n') {
token = readCPPline(ppToken); token = readCPPline(ppToken);
if (token == EOF) { if (token == EndOfInput) {
missingEndifCheck(); missingEndifCheck();
return nullptr; return nullptr;
} }

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 tInput::endOfInput; return EndOfInput;
} }
void TPpContext::lUnreadByte(TokenStream *pTok) void TPpContext::lUnreadByte(TokenStream *pTok)
@ -249,7 +249,7 @@ void TPpContext::pushTokenStreamInput(TokenStream* ts)
int TPpContext::tUngotTokenInput::scan(TPpToken* ppToken) int TPpContext::tUngotTokenInput::scan(TPpToken* ppToken)
{ {
if (done) if (done)
return endOfInput; return EndOfInput;
int ret = token; int ret = token;
*ppToken = lval; *ppToken = lval;