mirror of
https://github.com/KhronosGroup/glslang
synced 2024-11-09 12:00:05 +00:00
PP: Recognize <> style #include header names. I.e., #include <header-name>.
Also correctly test and handle missing newline.
This commit is contained in:
parent
faa720f14c
commit
affc26674d
@ -1,13 +1,13 @@
|
|||||||
ERROR: 0:8000: '#include' : required extension not requested: GL_GOOGLE_include_directive
|
ERROR: 0:8000: '#include' : required extension not requested: GL_GOOGLE_include_directive
|
||||||
ERROR: 0:8000: '#include' : must be followed by a file designation
|
ERROR: 0:8000: '#include' : must be followed by a header name
|
||||||
ERROR: 0:8001: '#include' : required extension not requested: GL_GOOGLE_include_directive
|
ERROR: 0:8001: '#include' : required extension not requested: GL_GOOGLE_include_directive
|
||||||
ERROR: 0:8001: '#include' : must be followed by a file designation
|
ERROR: 0:8001: '#include' : must be followed by a header name
|
||||||
ERROR: 0:8002: '#include' : required extension not requested: GL_GOOGLE_include_directive
|
ERROR: 0:8002: '#include' : required extension not requested: GL_GOOGLE_include_directive
|
||||||
ERROR: 0:8002: '#include' : unexpected include directive
|
ERROR: 0:8002: '#include' : unexpected include directive
|
||||||
ERROR: 0:8003: '#include' : required extension not requested: GL_GOOGLE_include_directive
|
ERROR: 0:8003: '#include' : required extension not requested: GL_GOOGLE_include_directive
|
||||||
ERROR: 0:8003: '#include' : extra content after file designation
|
ERROR: 0:8003: '#include' : extra content after header name
|
||||||
ERROR: 0:8004: '#include' : required extension not requested: GL_GOOGLE_include_directive
|
ERROR: 0:8004: '#include' : required extension not requested: GL_GOOGLE_include_directive
|
||||||
ERROR: 0:8004: '#include' : unexpected include directive
|
ERROR: 0:8004: '#include' : expected newline
|
||||||
ERROR: 10 compilation errors. No code generated.
|
ERROR: 10 compilation errors. No code generated.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
ERROR: 0:8000: '#include' : must be followed by a file designation
|
ERROR: 0:8000: '#include' : must be followed by a header name
|
||||||
ERROR: 0:8001: '#include' : must be followed by a file designation
|
ERROR: 0:8001: '#include' : must be followed by a header name
|
||||||
ERROR: 0:8002: '#include' : unexpected include directive
|
ERROR: 0:8002: '#include' : unexpected include directive
|
||||||
ERROR: 0:8003: '#include' : extra content after file designation
|
ERROR: 0:8003: '#include' : unexpected include directive
|
||||||
ERROR: 0:8004: '#include' : unexpected include directive
|
ERROR: 0:8004: '#include' : extra content after header name
|
||||||
ERROR: 5 compilation errors. No code generated.
|
ERROR: 0:8005: '#include' : extra content after header name
|
||||||
|
ERROR: 0:8007: '#include' : unexpected include directive
|
||||||
|
ERROR: 0:8009: '' : header name too long
|
||||||
|
ERROR: 0:8009: '#include' : unexpected include directive
|
||||||
|
ERROR: 0:8010: '#include' : expected newline
|
||||||
|
ERROR: 10 compilation errors. No code generated.
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,5 +3,4 @@
|
|||||||
#include 123
|
#include 123
|
||||||
#include "foo"
|
#include "foo"
|
||||||
#include "foo" garbage
|
#include "foo" garbage
|
||||||
#include "no-eol"
|
#include "no-eol"
|
||||||
|
|
@ -3,5 +3,11 @@
|
|||||||
#include
|
#include
|
||||||
#include 123
|
#include 123
|
||||||
#include "foo"
|
#include "foo"
|
||||||
|
#include <foo>
|
||||||
#include "foo" garbage
|
#include "foo" garbage
|
||||||
#include "no-eol"
|
#include <foo> garbage
|
||||||
|
// max length
|
||||||
|
#include <ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789>
|
||||||
|
// too long
|
||||||
|
#include <ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF01234567890>
|
||||||
|
#include "no-eol"
|
@ -2,5 +2,5 @@
|
|||||||
// For the version, it uses the latest git tag followed by the number of commits.
|
// For the version, it uses the latest git tag followed by the number of commits.
|
||||||
// For the date, it uses the current date (when then script is run).
|
// For the date, it uses the current date (when then script is run).
|
||||||
|
|
||||||
#define GLSLANG_REVISION "Overload400-PrecQual.1728"
|
#define GLSLANG_REVISION "Overload400-PrecQual.1730"
|
||||||
#define GLSLANG_DATE "02-Jan-2017"
|
#define GLSLANG_DATE "03-Jan-2017"
|
||||||
|
@ -571,46 +571,61 @@ int TPpContext::CPPifdef(int defined, TPpToken* ppToken)
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle #include
|
// Handle #include ...
|
||||||
|
// TODO: Handle macro expansions for the header name
|
||||||
int TPpContext::CPPinclude(TPpToken* ppToken)
|
int TPpContext::CPPinclude(TPpToken* ppToken)
|
||||||
{
|
{
|
||||||
const TSourceLoc directiveLoc = ppToken->loc;
|
const TSourceLoc directiveLoc = ppToken->loc;
|
||||||
|
TShader::Includer::IncludeType includeType = TShader::Includer::EIncludeRelative;
|
||||||
int token = scanToken(ppToken);
|
int token = scanToken(ppToken);
|
||||||
|
|
||||||
|
// handle <header-name>-style #include
|
||||||
|
if (token == '<') {
|
||||||
|
includeType = TShader::Includer::EIncludeStandard;
|
||||||
|
token = scanHeaderName(ppToken, '>');
|
||||||
|
}
|
||||||
|
// otherwise ppToken already has the header name and it was "header-name" style
|
||||||
|
|
||||||
if (token != PpAtomConstString) {
|
if (token != PpAtomConstString) {
|
||||||
// TODO: handle angle brackets.
|
parseContext.ppError(directiveLoc, "must be followed by a header name", "#include", "");
|
||||||
parseContext.ppError(directiveLoc, "must be followed by a file designation", "#include", "");
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a copy of the name because it will be overwritten by the next token scan.
|
||||||
|
const std::string filename = ppToken->name;
|
||||||
|
token = scanToken(ppToken);
|
||||||
|
if (token != '\n') {
|
||||||
|
if (token == EndOfInput)
|
||||||
|
parseContext.ppError(ppToken->loc, "expected newline", "#include", "");
|
||||||
|
else
|
||||||
|
parseContext.ppError(ppToken->loc, "extra content after header name", "#include", "");
|
||||||
} else {
|
} else {
|
||||||
// Make a copy of the name because it will be overwritten by the next token scan.
|
TShader::Includer::IncludeResult* res = includer.include(filename.c_str(), includeType, currentSourceFile.c_str(), includeStack.size() + 1);
|
||||||
const std::string filename = ppToken->name;
|
if (res && !res->file_name.empty()) {
|
||||||
token = scanToken(ppToken);
|
if (res->file_data && res->file_length) {
|
||||||
if (token != '\n' && token != EndOfInput) {
|
const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine();
|
||||||
parseContext.ppError(ppToken->loc, "extra content after file designation", "#include", "");
|
std::ostringstream prologue;
|
||||||
|
std::ostringstream epilogue;
|
||||||
|
prologue << "#line " << forNextLine << " " << "\"" << res->file_name << "\"\n";
|
||||||
|
epilogue << (res->file_data[res->file_length - 1] == '\n'? "" : "\n") << "#line " << directiveLoc.line + forNextLine << " " << directiveLoc.getStringNameOrNum() << "\n";
|
||||||
|
pushInput(new TokenizableIncludeFile(directiveLoc, prologue.str(), res, epilogue.str(), 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 {
|
} else {
|
||||||
TShader::Includer::IncludeResult* res = includer.include(filename.c_str(), TShader::Includer::EIncludeRelative, currentSourceFile.c_str(), includeStack.size() + 1);
|
std::string message =
|
||||||
if (res && !res->file_name.empty()) {
|
res ? std::string(res->file_data, res->file_length)
|
||||||
if (res->file_data && res->file_length) {
|
: std::string("Could not process include directive");
|
||||||
const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine();
|
parseContext.ppError(directiveLoc, message.c_str(), "#include", "");
|
||||||
std::ostringstream prologue;
|
if (res) {
|
||||||
std::ostringstream epilogue;
|
includer.releaseInclude(res);
|
||||||
prologue << "#line " << forNextLine << " " << "\"" << res->file_name << "\"\n";
|
|
||||||
epilogue << (res->file_data[res->file_length - 1] == '\n'? "" : "\n") << "#line " << directiveLoc.line + forNextLine << " " << directiveLoc.getStringNameOrNum() << "\n";
|
|
||||||
pushInput(new TokenizableIncludeFile(directiveLoc, prologue.str(), res, epilogue.str(), 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 {
|
|
||||||
std::string message =
|
|
||||||
res ? std::string(res->file_data, res->file_length)
|
|
||||||
: std::string("Could not process include directive");
|
|
||||||
parseContext.ppError(directiveLoc, message.c_str(), "#include", "");
|
|
||||||
if (res) {
|
|
||||||
includer.releaseInclude(res);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -911,6 +926,38 @@ int TPpContext::readCPPline(TPpToken* ppToken)
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Context-dependent parsing of a #include <header-name>.
|
||||||
|
// Assumes no macro expansions etc. are being done; the name is just on the current input.
|
||||||
|
// Always creates a name and returns PpAtomicConstString, unless we run out of input.
|
||||||
|
int TPpContext::scanHeaderName(TPpToken* ppToken, char delimit)
|
||||||
|
{
|
||||||
|
bool tooLong = false;
|
||||||
|
|
||||||
|
if (inputStack.empty())
|
||||||
|
return EndOfInput;
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
ppToken->name[0] = '\0';
|
||||||
|
do {
|
||||||
|
int ch = inputStack.back()->getch();
|
||||||
|
|
||||||
|
// done yet?
|
||||||
|
if (ch == delimit) {
|
||||||
|
ppToken->name[len] = '\0';
|
||||||
|
if (tooLong)
|
||||||
|
parseContext.ppError(ppToken->loc, "header name too long", "", "");
|
||||||
|
return PpAtomConstString;
|
||||||
|
} else if (ch == EndOfInput)
|
||||||
|
return EndOfInput;
|
||||||
|
|
||||||
|
// found a character to expand the name with
|
||||||
|
if (len < MaxTokenLength)
|
||||||
|
ppToken->name[len++] = ch;
|
||||||
|
else
|
||||||
|
tooLong = true;
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
// Macro-expand a macro argument 'arg' to create 'expandedArg'.
|
// Macro-expand a macro argument 'arg' to create 'expandedArg'.
|
||||||
// Does not replace 'arg'.
|
// Does not replace 'arg'.
|
||||||
// Returns nullptr if no expanded argument is created.
|
// Returns nullptr if no expanded argument is created.
|
||||||
|
@ -368,6 +368,7 @@ protected:
|
|||||||
int CPPversion(TPpToken * ppToken);
|
int CPPversion(TPpToken * ppToken);
|
||||||
int CPPextension(TPpToken * ppToken);
|
int CPPextension(TPpToken * ppToken);
|
||||||
int readCPPline(TPpToken * ppToken);
|
int readCPPline(TPpToken * ppToken);
|
||||||
|
int scanHeaderName(TPpToken* ppToken, char delimit);
|
||||||
TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay);
|
TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay);
|
||||||
int MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay);
|
int MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay);
|
||||||
|
|
||||||
|
@ -688,6 +688,9 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '"':
|
case '"':
|
||||||
|
// TODO: If this gets enhanced to handle escape sequences, or
|
||||||
|
// anything that is different than what #include needs, then
|
||||||
|
// #include needs to use scanHeaderName() for this.
|
||||||
ch = getch();
|
ch = getch();
|
||||||
while (ch != '"' && ch != '\n' && ch != EndOfInput) {
|
while (ch != '"' && ch != '\n' && ch != EndOfInput) {
|
||||||
if (len < MaxTokenLength) {
|
if (len < MaxTokenLength) {
|
||||||
|
Loading…
Reference in New Issue
Block a user