Improve preprocessor by using GLSL scanner, allowing read-only strings to be compiled, unifying of line # tracking, and correct detection that ES #version appeared after a comment.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23721 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
9497485e14
commit
ea869fb403
20 changed files with 285 additions and 300 deletions
|
|
@ -134,7 +134,7 @@ int TPpContext::FinalCPP()
|
|||
mem_FreePool(pool);
|
||||
|
||||
if (ifdepth)
|
||||
parseContext.error(parseContext.currentLoc, "missing #endif", "#if", "");
|
||||
parseContext.error(parseContext.getCurrentLoc(), "missing #endif", "#if", "");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -552,21 +552,21 @@ int TPpContext::CPPline(TPpToken * ppToken)
|
|||
return token;
|
||||
}
|
||||
else if (token == CPP_INTCONSTANT) {
|
||||
parseContext.currentLoc.line = atoi(ppToken->name);
|
||||
parseContext.setCurrentLine(atoi(ppToken->name));
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
|
||||
if (token == CPP_INTCONSTANT) {
|
||||
parseContext.currentLoc.string = atoi(ppToken->name);
|
||||
parseContext.setCurrentString(atoi(ppToken->name));
|
||||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
if (token != '\n')
|
||||
parseContext.error(parseContext.currentLoc, "cannot be followed by more than two integral literals", "#line", "");
|
||||
parseContext.error(parseContext.getCurrentLoc(), "cannot be followed by more than two integral literals", "#line", "");
|
||||
} else if (token == '\n')
|
||||
|
||||
return token;
|
||||
else
|
||||
parseContext.error(parseContext.currentLoc, "second argument can only be an integral literal", "#line", "");
|
||||
parseContext.error(parseContext.getCurrentLoc(), "second argument can only be an integral literal", "#line", "");
|
||||
} else
|
||||
parseContext.error(parseContext.currentLoc, "first argument can only be an integral literal", "#line", "");
|
||||
parseContext.error(parseContext.getCurrentLoc(), "first argument can only be an integral literal", "#line", "");
|
||||
|
||||
return token;
|
||||
}
|
||||
|
|
@ -662,8 +662,8 @@ int TPpContext::CPPversion(TPpToken * ppToken)
|
|||
{
|
||||
int token = currentInput->scan(this, currentInput, ppToken);
|
||||
|
||||
if (notAVersionToken)
|
||||
parseContext.error(ppToken->loc, "must occur before any other statement in the program", "#version", "");
|
||||
if (errorOnVersion)
|
||||
parseContext.error(ppToken->loc, "must occur first in shader", "#version", "");
|
||||
|
||||
if (token == '\n') {
|
||||
parseContext.error(ppToken->loc, "must be followed by version number", "#version", "");
|
||||
|
|
@ -759,7 +759,6 @@ int TPpContext::readCPPline(TPpToken * ppToken)
|
|||
} else {
|
||||
parseContext.error(ppToken->loc, "#else after a #else", "#else", "");
|
||||
ifdepth = 0;
|
||||
notAVersionToken = true;
|
||||
return 0;
|
||||
}
|
||||
} else if (ppToken->atom == elifAtom) {
|
||||
|
|
@ -805,8 +804,6 @@ int TPpContext::readCPPline(TPpToken * ppToken)
|
|||
token = currentInput->scan(this, currentInput, ppToken);
|
||||
}
|
||||
|
||||
notAVersionToken = ! isVersion;
|
||||
|
||||
return token;
|
||||
} // readCPPline
|
||||
|
||||
|
|
@ -931,7 +928,7 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, int expandUndef)
|
|||
int depth = 0;
|
||||
|
||||
if (atom == __LINE__Atom) {
|
||||
ppToken->ival = parseContext.currentLoc.line;
|
||||
ppToken->ival = parseContext.getCurrentLoc().line;
|
||||
sprintf(ppToken->name, "%d", ppToken->ival);
|
||||
UngetToken(CPP_INTCONSTANT, ppToken);
|
||||
|
||||
|
|
@ -939,7 +936,7 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, int expandUndef)
|
|||
}
|
||||
|
||||
if (atom == __FILE__Atom) {
|
||||
ppToken->ival = parseContext.currentLoc.string;
|
||||
ppToken->ival = parseContext.getCurrentLoc().string;
|
||||
sprintf(ppToken->name, "%d", ppToken->ival);
|
||||
UngetToken(CPP_INTCONSTANT, ppToken);
|
||||
|
||||
|
|
@ -964,8 +961,6 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, int expandUndef)
|
|||
|
||||
in = (MacroInputSrc*)malloc(sizeof(*in));
|
||||
memset(in, 0, sizeof(*in));
|
||||
in->base.line = currentInput->line;
|
||||
in->base.name = currentInput->name;
|
||||
|
||||
if ((! sym || sym->mac.undef) && expandUndef) {
|
||||
// push input
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace glslang {
|
||||
|
||||
TPpContext::TPpContext(TParseContext& pc) :
|
||||
preamble(0), strings(0), notAVersionToken(false), parseContext(pc)
|
||||
preamble(0), strings(0), parseContext(pc)
|
||||
{
|
||||
InitAtomTable();
|
||||
InitScanner(this);
|
||||
|
|
@ -101,28 +101,17 @@ TPpContext::~TPpContext()
|
|||
delete [] preamble;
|
||||
}
|
||||
|
||||
void TPpContext::setPreamble(const char* p, size_t l)
|
||||
void TPpContext::setInput(TInputScanner& input, bool versionWillBeError)
|
||||
{
|
||||
if (p && l > 0) {
|
||||
// preAmble could be a hard-coded string; make writable copy
|
||||
// TODO: efficiency PP: make it not need writable strings
|
||||
preambleLength = l;
|
||||
preamble = new char[preambleLength + 1];
|
||||
memcpy(preamble, p, preambleLength + 1); // TODO: PP: assuming nul-terminated strings
|
||||
ScanFromString(preamble);
|
||||
currentString = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void TPpContext::setShaderStrings(char* s[], size_t l[], int n)
|
||||
{
|
||||
strings = s;
|
||||
lengths = l;
|
||||
numStrings = n;
|
||||
if (! preamble) {
|
||||
ScanFromString(strings[0]);
|
||||
currentString = 0;
|
||||
}
|
||||
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.prev = currentInput;
|
||||
currentInput = &in->base;
|
||||
errorOnVersion = versionWillBeError;
|
||||
}
|
||||
|
||||
} // end namespace glslang
|
||||
|
|
|
|||
|
|
@ -95,6 +95,8 @@ public:
|
|||
char name[maxTokenLength+1];
|
||||
};
|
||||
|
||||
class TInputScanner;
|
||||
|
||||
// This class is the result of turning a huge pile of C code communicating through globals
|
||||
// into a class. This was done to allowing instancing to attain thread safety.
|
||||
// Don't expect too much in terms of OO design.
|
||||
|
|
@ -104,7 +106,7 @@ public:
|
|||
virtual ~TPpContext();
|
||||
|
||||
void setPreamble(const char* preamble, size_t length);
|
||||
void setShaderStrings(char* strings[], size_t lengths[], int numStrings);
|
||||
void setInput(TInputScanner& input, bool versionWillBeError);
|
||||
|
||||
const char* tokenize(TPpToken* ppToken);
|
||||
|
||||
|
|
@ -113,8 +115,6 @@ public:
|
|||
int (*scan)(TPpContext*, struct InputSrc *, TPpToken *);
|
||||
int (*getch)(TPpContext*, struct InputSrc *, TPpToken *);
|
||||
void (*ungetch)(TPpContext*, struct InputSrc *, int, TPpToken *);
|
||||
int name; /* atom */
|
||||
int line;
|
||||
};
|
||||
|
||||
struct TokenBlock {
|
||||
|
|
@ -177,7 +177,6 @@ protected:
|
|||
// Scanner data:
|
||||
int mostRecentToken; // Most recent token seen by the scanner
|
||||
int previous_token;
|
||||
bool notAVersionToken; // used to make sure that #version is the first token seen in the file, if present
|
||||
TParseContext& parseContext;
|
||||
|
||||
static const int maxMacroArgs = 64;
|
||||
|
|
@ -195,6 +194,7 @@ protected:
|
|||
};
|
||||
|
||||
InputSrc *currentInput;
|
||||
bool errorOnVersion;
|
||||
|
||||
//
|
||||
// from Pp.cpp
|
||||
|
|
@ -289,7 +289,7 @@ protected:
|
|||
//
|
||||
struct StringInputSrc {
|
||||
InputSrc base;
|
||||
char *p;
|
||||
TInputScanner* input;
|
||||
};
|
||||
int InitScanner(TPpContext *cpp);
|
||||
static int str_getch(TPpContext*, StringInputSrc *in);
|
||||
|
|
|
|||
|
|
@ -88,23 +88,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "PpContext.h"
|
||||
#include "PpTokens.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace glslang;
|
||||
|
||||
int eof_scan(TPpContext*, TPpContext::InputSrc*, TPpToken*)
|
||||
{
|
||||
return EOF;
|
||||
}
|
||||
|
||||
void noop(TPpContext*, TPpContext::InputSrc *in, int ch, TPpToken * ppToken)
|
||||
{
|
||||
}
|
||||
|
||||
TPpContext::InputSrc eof_inputsrc = { 0, &eof_scan, &eof_scan, &noop };
|
||||
|
||||
} // end anonymous namespace
|
||||
#include "Scan.h"
|
||||
|
||||
namespace glslang {
|
||||
|
||||
|
|
@ -115,79 +99,26 @@ int TPpContext::InitScanner(TPpContext *cpp)
|
|||
return 0;
|
||||
|
||||
mostRecentToken = 0;
|
||||
currentInput = &eof_inputsrc;
|
||||
currentInput = 0;
|
||||
previous_token = '\n';
|
||||
notAVersionToken = false;
|
||||
|
||||
return 1;
|
||||
} // InitScanner
|
||||
|
||||
/*
|
||||
* str_getch()
|
||||
* takes care of reading from multiple strings.
|
||||
* returns the next-char from the input stream.
|
||||
* returns EOF when the complete shader is parsed.
|
||||
*/
|
||||
int TPpContext::str_getch(TPpContext* pp, StringInputSrc *in)
|
||||
{
|
||||
for(;;) {
|
||||
if (*in->p) {
|
||||
if (*in->p == '\n') {
|
||||
in->base.line++;
|
||||
++pp->parseContext.currentLoc.line;
|
||||
}
|
||||
return *in->p++;
|
||||
}
|
||||
if (pp->currentString < 0) {
|
||||
// we only parsed the built-in pre-amble; start with clean slate for user code
|
||||
pp->notAVersionToken = false;
|
||||
}
|
||||
if (++(pp->currentString) < pp->numStrings) {
|
||||
free(in);
|
||||
pp->parseContext.currentLoc.string = pp->currentString;
|
||||
pp->parseContext.currentLoc.line = 1;
|
||||
pp->ScanFromString(pp->strings[pp->currentString]);
|
||||
in=(StringInputSrc*)pp->currentInput;
|
||||
continue;
|
||||
} else {
|
||||
pp->currentInput = in->base.prev;
|
||||
pp->currentString = 0;
|
||||
free(in);
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
} // str_getch
|
||||
|
||||
void TPpContext::str_ungetch(TPpContext* pp, StringInputSrc *in, int ch, TPpToken *type)
|
||||
{
|
||||
if (in->p[-1] == ch)in->p--;
|
||||
else {
|
||||
*(in->p)='\0'; //this would take care of shifting to the previous string.
|
||||
pp->currentString--;
|
||||
pp->parseContext.currentLoc.string = pp->currentString;
|
||||
}
|
||||
if (ch == '\n') {
|
||||
in->base.line--;
|
||||
--pp->parseContext.currentLoc.line;
|
||||
}
|
||||
} // str_ungetch
|
||||
|
||||
int TPpContext::ScanFromString(char *s)
|
||||
{
|
||||
|
||||
StringInputSrc *in = (StringInputSrc *)malloc(sizeof(StringInputSrc));
|
||||
memset(in, 0, sizeof(StringInputSrc));
|
||||
in->p = s;
|
||||
in->base.line = 1;
|
||||
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.prev = currentInput;
|
||||
currentInput = &in->base;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int TPpContext::str_getch(TPpContext* pp, StringInputSrc *in)
|
||||
{
|
||||
int ch = in->input->get();
|
||||
|
||||
if (ch == EOF)
|
||||
free(in);
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
void TPpContext::str_ungetch(TPpContext* pp, StringInputSrc *in, int ch, TPpToken *type)
|
||||
{
|
||||
in->input->unget();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////// Floating point constants: /////////////////////////////////
|
||||
|
|
@ -332,7 +263,7 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * ppToken)
|
|||
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
|
||||
}
|
||||
|
||||
ppToken->loc = pp->parseContext.currentLoc;
|
||||
ppToken->loc = pp->parseContext.getCurrentLoc();
|
||||
len = 0;
|
||||
switch (ch) {
|
||||
default:
|
||||
|
|
@ -696,6 +627,7 @@ int TPpContext::byte_scan(TPpContext* pp, InputSrc *in, TPpToken * ppToken)
|
|||
return '.';
|
||||
}
|
||||
case '/':
|
||||
// TODO: preprocessor: use the Scan.cpp comment scanner
|
||||
ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
|
||||
if (ch == '/') {
|
||||
do {
|
||||
|
|
@ -801,8 +733,6 @@ const char* TPpContext::tokenize(TPpToken* ppToken)
|
|||
if (token == '\n')
|
||||
continue;
|
||||
|
||||
notAVersionToken = true;
|
||||
|
||||
// expand macros
|
||||
if (token == CPP_IDENTIFIER && MacroExpand(ppToken->atom, ppToken, 0) == 1)
|
||||
continue;
|
||||
|
|
@ -831,7 +761,7 @@ int TPpContext::check_EOF(int token)
|
|||
{
|
||||
if (token == EOF) {
|
||||
if (ifdepth > 0)
|
||||
parseContext.error(parseContext.currentLoc, "missing #endif", "#if", "");
|
||||
parseContext.error(parseContext.getCurrentLoc(), "missing #endif", "#if", "");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ int TPpContext::ReadToken(TokenStream *pTok, TPpToken *ppToken)
|
|||
char ch;
|
||||
|
||||
ltoken = lReadByte(pTok);
|
||||
ppToken->loc = parseContext.currentLoc;
|
||||
ppToken->loc = parseContext.getCurrentLoc();
|
||||
if (ltoken >= 0) {
|
||||
if (ltoken > 127)
|
||||
ltoken += 128;
|
||||
|
|
@ -399,12 +399,9 @@ int TPpContext::scan_token(TPpContext* pp, TokenInputSrc *in, TPpToken * ppToken
|
|||
{
|
||||
int token = pp->ReadToken(in->tokens, ppToken);
|
||||
int (*final)(TPpContext *);
|
||||
if (token == '\n') {
|
||||
in->base.line++;
|
||||
return token;
|
||||
}
|
||||
if (token > 0)
|
||||
return token;
|
||||
|
||||
pp->currentInput = in->base.prev;
|
||||
final = in->final;
|
||||
free(in);
|
||||
|
|
@ -418,10 +415,8 @@ int TPpContext::ReadFromTokenStream(TokenStream *ts, int name, int (*final)(TPpC
|
|||
{
|
||||
TokenInputSrc *in = (TokenInputSrc *) malloc(sizeof(TokenInputSrc));
|
||||
memset(in, 0, sizeof(TokenInputSrc));
|
||||
in->base.name = name;
|
||||
in->base.prev = currentInput;
|
||||
in->base.scan = (int (*)(TPpContext*, InputSrc*, TPpToken*))scan_token;
|
||||
in->base.line = 1;
|
||||
in->tokens = ts;
|
||||
in->final = final;
|
||||
RewindTokenStream(ts);
|
||||
|
|
@ -449,8 +444,6 @@ void TPpContext::UngetToken(int token, TPpToken * ppToken)
|
|||
t->lval = *ppToken;
|
||||
t->base.scan = (int(*)(TPpContext*, struct InputSrc *, TPpToken *))reget_token;
|
||||
t->base.prev = currentInput;
|
||||
t->base.name = currentInput->name;
|
||||
t->base.line = currentInput->line;
|
||||
currentInput = &t->base;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue