Add #include processing to glslang (though turned off by default).
When an include directive is recognized by the preprocessor, it executes a callback on the filepath argument to obtain the file contents. That way the compilation client can deal with the file system, include paths, etc. Currently only accepts quoted filepaths -- no angle brackets yet.
This commit is contained in:
parent
1363fcd60b
commit
7be4b8282d
14 changed files with 142 additions and 21 deletions
|
|
@ -596,6 +596,38 @@ int TPpContext::CPPifdef(int defined, TPpToken* ppToken)
|
|||
return token;
|
||||
}
|
||||
|
||||
// Handle #include
|
||||
int TPpContext::CPPinclude(TPpToken* ppToken)
|
||||
{
|
||||
const TSourceLoc directiveLoc = ppToken->loc;
|
||||
int token = scanToken(ppToken);
|
||||
if (token != PpAtomConstString) {
|
||||
// TODO: handle angle brackets.
|
||||
parseContext.ppError(directiveLoc, "must be followed by a file designation", "#include", "");
|
||||
} else {
|
||||
const char* name = GetAtomString(ppToken->atom);
|
||||
token = scanToken(ppToken);
|
||||
if (token != '\n' && token != EndOfInput) {
|
||||
parseContext.ppError(ppToken->loc, "extra content after file designation", "#include", "");
|
||||
} else {
|
||||
if (!inputStack.empty()) ungetChar();
|
||||
std::string replacement;
|
||||
bool success;
|
||||
std::tie(success, replacement) = includer.include(name);
|
||||
if (success) {
|
||||
pushInput(new TokenizableString(replacement, this));
|
||||
// At EOF, there's no "current" location anymore.
|
||||
if (token != EndOfInput) parseContext.setCurrentColumn(0);
|
||||
// Don't accidentally return EndOfInput, which will end all preprocessing.
|
||||
return '\n';
|
||||
} else {
|
||||
parseContext.ppError(ppToken->loc, "not found", name, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
// Handle #line
|
||||
int TPpContext::CPPline(TPpToken* ppToken)
|
||||
{
|
||||
|
|
@ -845,6 +877,9 @@ int TPpContext::readCPPline(TPpToken* ppToken)
|
|||
case PpAtomIfndef:
|
||||
token = CPPifdef(0, ppToken);
|
||||
break;
|
||||
case PpAtomInclude:
|
||||
token = CPPinclude(ppToken);
|
||||
break;
|
||||
case PpAtomLine:
|
||||
token = CPPline(ppToken);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -120,6 +120,9 @@ const struct {
|
|||
{ PpAtomLineMacro, "__LINE__" },
|
||||
{ PpAtomFileMacro, "__FILE__" },
|
||||
{ PpAtomVersionMacro, "__VERSION__" },
|
||||
|
||||
{ PpAtomInclude, "include" },
|
||||
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
|
|
|||
|
|
@ -83,8 +83,8 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
namespace glslang {
|
||||
|
||||
TPpContext::TPpContext(TParseContext& pc) :
|
||||
preamble(0), strings(0), parseContext(pc), inComment(false)
|
||||
TPpContext::TPpContext(TParseContext& pc, const TShader::Includer& inclr) :
|
||||
preamble(0), strings(0), parseContext(pc), includer(inclr), inComment(false)
|
||||
{
|
||||
InitAtomTable();
|
||||
InitScanner();
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ class TInputScanner;
|
|||
// Don't expect too much in terms of OO design.
|
||||
class TPpContext {
|
||||
public:
|
||||
TPpContext(TParseContext&);
|
||||
TPpContext(TParseContext&, const TShader::Includer&);
|
||||
virtual ~TPpContext();
|
||||
|
||||
void setPreamble(const char* preamble, size_t length);
|
||||
|
|
@ -281,6 +281,8 @@ protected:
|
|||
// from Pp.cpp
|
||||
//
|
||||
TSourceLoc ifloc; /* outermost #if */
|
||||
// Used to obtain #include content.
|
||||
const TShader::Includer& includer;
|
||||
|
||||
int InitCPP();
|
||||
int CPPdefine(TPpToken * ppToken);
|
||||
|
|
@ -291,6 +293,7 @@ protected:
|
|||
int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
|
||||
int CPPif (TPpToken * ppToken);
|
||||
int CPPifdef(int defined, TPpToken * ppToken);
|
||||
int CPPinclude(TPpToken * ppToken);
|
||||
int CPPline(TPpToken * ppToken);
|
||||
int CPPerror(TPpToken * ppToken);
|
||||
int CPPpragma(TPpToken * ppToken);
|
||||
|
|
@ -419,6 +422,36 @@ protected:
|
|||
TInputScanner* input;
|
||||
};
|
||||
|
||||
// Holds a string that can be tokenized via the tInput interface.
|
||||
class TokenizableString : public tInput {
|
||||
public:
|
||||
// Copies str, which must be non-empty.
|
||||
TokenizableString(const std::string& str, TPpContext* pp)
|
||||
: tInput(pp),
|
||||
str_(str),
|
||||
strings(str_.data()),
|
||||
length(str_.size()),
|
||||
scanner(1, &strings, &length),
|
||||
stringInput(pp, scanner) {}
|
||||
|
||||
// tInput methods:
|
||||
int scan(TPpToken* t) override { return stringInput.scan(t); }
|
||||
int getch() override { return stringInput.getch(); }
|
||||
void ungetch() override { stringInput.ungetch(); }
|
||||
|
||||
private:
|
||||
// Stores the titular string.
|
||||
const std::string str_;
|
||||
// Will point to str_[0] and be passed to scanner constructor.
|
||||
const char* const strings;
|
||||
// Length of str_, passed to scanner constructor.
|
||||
size_t length;
|
||||
// Scans over str_.
|
||||
TInputScanner scanner;
|
||||
// Delegate object implementing the tInput interface.
|
||||
tStringInput stringInput;
|
||||
};
|
||||
|
||||
int InitScanner();
|
||||
int ScanFromString(char* s);
|
||||
void missingEndifCheck();
|
||||
|
|
|
|||
|
|
@ -158,6 +158,9 @@ enum EFixedAtoms {
|
|||
PpAtomFileMacro,
|
||||
PpAtomVersionMacro,
|
||||
|
||||
// #include
|
||||
PpAtomInclude,
|
||||
|
||||
PpAtomLast,
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue