// record the definition of the macro
TSourceLoc defineLoc = ppToken->loc; // because ppToken is going to go to the next line before we report errors
while (token != '\n' && token != EndOfInput) {
- RecordToken(mac.body, token, ppToken);
+ mac.body.putToken(token, ppToken);
token = scanToken(ppToken);
if (token != '\n' && ppToken->space)
- RecordToken(mac.body, ' ', ppToken);
+ mac.body.putToken(' ', ppToken);
}
// check for duplicate definition
else {
if (existing->args != mac.args)
parseContext.ppError(defineLoc, "Macro redefined; different argument names:", "#define", atomStrings.getString(defAtom));
- RewindTokenStream(existing->body);
- RewindTokenStream(mac.body);
+ existing->body.reset();
+ mac.body.reset();
int newToken;
do {
int oldToken;
TPpToken oldPpToken;
TPpToken newPpToken;
- oldToken = ReadToken(existing->body, &oldPpToken);
- newToken = ReadToken(mac.body, &newPpToken);
+ oldToken = existing->body.getToken(parseContext, &oldPpToken);
+ newToken = mac.body.getToken(parseContext, &newPpToken);
if (oldToken != newToken || oldPpToken != newPpToken) {
parseContext.ppError(defineLoc, "Macro redefined; different substitutions:", "#define", atomStrings.getString(defAtom));
break;
token = tokenPaste(token, *ppToken);
if (token == PpAtomIdentifier && MacroExpand(ppToken, false, newLineOkay) != 0)
continue;
- RecordToken(*expandedArg, token, ppToken);
+ expandedArg->putToken(token, ppToken);
}
if (token == EndOfInput) {
{
int token;
do {
- token = pp->ReadToken(mac->body, ppToken);
+ token = mac->body.getToken(pp->parseContext, ppToken);
} while (token == ' '); // handle white space in macro
// Hash operators basically turn off a round of macro substitution
}
// see if are preceding a ##
- if (peekMacPasting()) {
+ if (mac->body.peekUntokenizedPasting()) {
prepaste = true;
pasting = true;
}
return token;
}
-// See if the next non-white-space token in the macro is ##
-bool TPpContext::tMacroInput::peekMacPasting()
-{
- // don't return early, have to restore this
- size_t savePos = mac->body.current;
-
- // skip white-space
- int subtoken;
- do {
- subtoken = pp->getSubtoken(mac->body);
- } while (subtoken == ' ');
-
- // check for ##
- bool pasting = false;
- if (subtoken == '#') {
- subtoken = pp->getSubtoken(mac->body);
- if (subtoken == '#')
- pasting = true;
- }
-
- mac->body.current = savePos;
-
- return pasting;
-}
-
// return a textual zero, for scanning a macro that was never defined
int TPpContext::tZeroInput::scan(TPpToken* ppToken)
{
depth++;
if (token == ')')
depth--;
- RecordToken(*in->args[arg], token, ppToken);
+ in->args[arg]->putToken(token, ppToken);
tokenRecorded = true;
}
if (token == ')') {
pushInput(in);
macro->busy = 1;
- RewindTokenStream(macro->body);
+ macro->body.reset();
return 1;
}
inputStack.pop_back();
}
- struct TokenStream {
+ //
+ // From PpTokens.cpp
+ //
+
+ class TokenStream {
+ public:
TokenStream() : current(0) { }
+
+ void putToken(int token, TPpToken* ppToken);
+ int getToken(TParseContextBase&, TPpToken*);
+ bool atEnd() { return current >= data.size(); }
+ bool peekTokenizedPasting(bool lastTokenPastes);
+ bool peekUntokenizedPasting();
+ void reset() { current = 0; }
+
+ protected:
+ void putSubtoken(int);
+ int getSubtoken();
+ void ungetSubtoken();
+
TVector<unsigned char> data;
size_t current;
};
virtual int getch() override { assert(0); return EndOfInput; }
virtual void ungetch() override { assert(0); }
bool peekPasting() override { return prepaste; }
- bool endOfReplacementList() override { return mac->body.current >= mac->body.data.size(); }
+ bool endOfReplacementList() override { return mac->body.atEnd(); }
MacroSymbol *mac;
TVector<TokenStream*> args;
TVector<TokenStream*> expandedArgs;
protected:
- bool peekMacPasting();
bool prepaste; // true if we are just before ##
bool postpaste; // true if we are right after ##
};
//
// From PpTokens.cpp
//
- void putSubtoken(TokenStream&, int fVal);
- int getSubtoken(TokenStream&);
- void ungetSubtoken(TokenStream&);
- void RecordToken(TokenStream&, int token, TPpToken* ppToken);
- void RewindTokenStream(TokenStream&);
- int ReadToken(TokenStream&, TPpToken*);
void pushTokenStreamInput(TokenStream&, bool pasting = false);
void UngetToken(int token, TPpToken*);
class tTokenInput : public tInput {
public:
tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting) : tInput(pp), tokens(t), lastTokenPastes(prepasting) { }
- virtual int scan(TPpToken *) override;
+ virtual int scan(TPpToken *ppToken) override { return tokens->getToken(pp->parseContext, ppToken); }
virtual int getch() override { assert(0); return EndOfInput; }
virtual void ungetch() override { assert(0); }
- virtual bool peekPasting() override;
+ virtual bool peekPasting() override { return tokens->peekTokenizedPasting(lastTokenPastes); }
protected:
TokenStream* tokens;
bool lastTokenPastes; // true if the last token in the input is to be pasted, rather than consumed as a token
namespace glslang {
// push onto back of stream
-void TPpContext::putSubtoken(TokenStream& stream, int subtoken)
+void TPpContext::TokenStream::putSubtoken(int subtoken)
{
assert((subtoken & ~0xff) == 0);
- stream.data.push_back(static_cast<unsigned char>(subtoken));
+ data.push_back(static_cast<unsigned char>(subtoken));
}
// get the next token in stream
-int TPpContext::getSubtoken(TokenStream& stream)
+int TPpContext::TokenStream::getSubtoken()
{
- if (stream.current < stream.data.size())
- return stream.data[stream.current++];
+ if (current < data.size())
+ return data[current++];
else
return EndOfInput;
}
// back up one position in the stream
-void TPpContext::ungetSubtoken(TokenStream& stream)
+void TPpContext::TokenStream::ungetSubtoken()
{
- if (stream.current > 0)
- --stream.current;
+ if (current > 0)
+ --current;
}
-/*
-* Add a token to the end of a list for later playback.
-*/
-void TPpContext::RecordToken(TokenStream& pTok, int token, TPpToken* ppToken)
+// Add a complete token (including backing string) to the end of a list
+// for later playback.
+void TPpContext::TokenStream::putToken(int token, TPpToken* ppToken)
{
const char* s;
char* str = NULL;
- putSubtoken(pTok, token);
+ putSubtoken(token);
switch (token) {
case PpAtomIdentifier:
case PpAtomConstString:
s = ppToken->name;
while (*s)
- putSubtoken(pTok, *s++);
- putSubtoken(pTok, 0);
+ putSubtoken(*s++);
+ putSubtoken(0);
break;
case PpAtomConstInt:
case PpAtomConstUint:
#endif
str = ppToken->name;
while (*str) {
- putSubtoken(pTok, *str);
+ putSubtoken(*str);
str++;
}
- putSubtoken(pTok, 0);
+ putSubtoken(0);
break;
default:
break;
}
}
-/*
-* Reset a token stream in preparation for reading.
-*/
-void TPpContext::RewindTokenStream(TokenStream& pTok)
-{
- pTok.current = 0;
-}
-
-/*
-* 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)
+// Read the next token from a token stream.
+// (Not the source stream, but a stream used to hold a tokenized macro).
+int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken *ppToken)
{
int len;
int ch;
- int subtoken = getSubtoken(pTok);
+ int subtoken = getSubtoken();
ppToken->loc = parseContext.getCurrentLoc();
switch (subtoken) {
case '#':
// Check for ##, unless the current # is the last character
- if (pTok.current < pTok.data.size()) {
- if (getSubtoken(pTok) == '#') {
+ if (current < data.size()) {
+ if (getSubtoken() == '#') {
parseContext.requireProfile(ppToken->loc, ~EEsProfile, "token pasting (##)");
parseContext.profileRequires(ppToken->loc, ~EEsProfile, 130, 0, "token pasting (##)");
subtoken = PpAtomPaste;
} else
- ungetSubtoken(pTok);
+ ungetSubtoken();
}
break;
case PpAtomConstString:
case PpAtomConstInt64:
case PpAtomConstUint64:
len = 0;
- ch = getSubtoken(pTok);
+ ch = getSubtoken();
while (ch != 0 && ch != EndOfInput) {
if (len < MaxTokenLength) {
ppToken->name[len] = (char)ch;
len++;
- ch = getSubtoken(pTok);
+ ch = getSubtoken();
} else {
parseContext.error(ppToken->loc, "token too long", "", "");
break;
return subtoken;
}
-int TPpContext::tTokenInput::scan(TPpToken* ppToken)
-{
- return pp->ReadToken(*tokens, ppToken);
-}
-
// We are pasting if
// 1. we are preceding a pasting operator within this stream
// or
// 2. the entire macro is preceding a pasting operator (lastTokenPastes)
// and we are also on the last token
-bool TPpContext::tTokenInput::peekPasting()
+bool TPpContext::TokenStream::peekTokenizedPasting(bool lastTokenPastes)
{
// 1. preceding ##?
- size_t savePos = tokens->current;
+ size_t savePos = current;
int subtoken;
// skip white space
do {
- subtoken = pp->getSubtoken(*tokens);
+ subtoken = getSubtoken();
} while (subtoken == ' ');
- tokens->current = savePos;
+ current = savePos;
if (subtoken == PpAtomPaste)
return true;
// Getting here means the last token will be pasted, after this
// Are we at the last non-whitespace token?
- savePos = tokens->current;
+ savePos = current;
bool moreTokens = false;
do {
- subtoken = pp->getSubtoken(*tokens);
+ subtoken = getSubtoken();
if (subtoken == EndOfInput)
break;
if (subtoken != ' ') {
break;
}
} while (true);
- tokens->current = savePos;
+ current = savePos;
return !moreTokens;
}
+// See if the next non-white-space tokens are two consecutive #
+bool TPpContext::TokenStream::peekUntokenizedPasting()
+{
+ // don't return early, have to restore this
+ size_t savePos = current;
+
+ // skip white-space
+ int subtoken;
+ do {
+ subtoken = getSubtoken();
+ } while (subtoken == ' ');
+
+ // check for ##
+ bool pasting = false;
+ if (subtoken == '#') {
+ subtoken = getSubtoken();
+ if (subtoken == '#')
+ pasting = true;
+ }
+
+ current = savePos;
+
+ return pasting;
+}
+
void TPpContext::pushTokenStreamInput(TokenStream& ts, bool prepasting)
{
pushInput(new tTokenInput(this, &ts, prepasting));
- RewindTokenStream(ts);
+ ts.reset();
}
int TPpContext::tUngotTokenInput::scan(TPpToken* ppToken)