mirror of
https://github.com/KhronosGroup/glslang
synced 2024-09-18 19:59:54 +00:00
Extend the syntax of #line and __FILE__ to support filename strings.
According to the GLSL spec, the second parameter to #line should be an integer source string number and __FILE__ will be substituted with the integer source string number currently processed. This patch extends the syntax of #line and __FILE__. Now #line accepts as the second parameter a filename string quoted by double quotation marks. And if such a #line is set, __FILE__ will be substituted with the currently set filename string. The implementation is done via introducing a new extension GL_GOOGLE_cpp_style_line_directive using the extension framework. The purpose is to support cpp-style #line directives, which is required by #include.
This commit is contained in:
parent
c777fc2c4c
commit
5011fbebc3
26
Test/baseResults/preprocessor.cpp_style___FILE__.vert.out
Normal file
26
Test/baseResults/preprocessor.cpp_style___FILE__.vert.out
Normal file
@ -0,0 +1,26 @@
|
||||
#extension GL_GOOGLE_cpp_style_line_directive : enable
|
||||
|
||||
0
|
||||
#line 150 a.h
|
||||
"a.h"
|
||||
#line 24
|
||||
"a.h"
|
||||
#line 42
|
||||
"a.h"
|
||||
#line 30 b.cc
|
||||
"b.cc"
|
||||
#line 10 3
|
||||
3
|
||||
#line 48
|
||||
3
|
||||
#line 4
|
||||
3
|
||||
#line 55 100
|
||||
100
|
||||
#line 1000 c
|
||||
"c"
|
||||
#line 42 1
|
||||
1
|
||||
#line 42 this-is-a-quite-long-name-maybe-i-should-shorten-it
|
||||
"this-is-a-quite-long-name-maybe-i-should-shorten-it"
|
||||
|
@ -0,0 +1,15 @@
|
||||
ERROR: 0:3: '#error' : at 0:3
|
||||
ERROR: a.h:150: '#error' : at a.h:150
|
||||
ERROR: a.h:24: '#error' : at a.h:24
|
||||
ERROR: a.h:42: '#error' : at a.h:42
|
||||
ERROR: b.cc:30: '#error' : at b.cc:30
|
||||
ERROR: 3:10: '#error' : at 3:10
|
||||
ERROR: 3:48: '#error' : at 3:48
|
||||
ERROR: 3:4: '#error' : at 3:4
|
||||
ERROR: 100:55: '#error' : at 100:55
|
||||
ERROR: c:1000: '#error' : at c:1000
|
||||
ERROR: 1:42: '#error' : at 1:42
|
||||
ERROR: this-is-a-quite-long-name-maybe-i-should-shorten-it:42: '#error' : at this-is-a-quite-long-name-maybe-i-should-shorten-it:42
|
||||
ERROR: 12 compilation errors. No code generated.
|
||||
|
||||
|
36
Test/preprocessor.cpp_style___FILE__.vert
Normal file
36
Test/preprocessor.cpp_style___FILE__.vert
Normal file
@ -0,0 +1,36 @@
|
||||
#extension GL_GOOGLE_cpp_style_line_directive : enable
|
||||
|
||||
__FILE__
|
||||
|
||||
#line 150 "a.h"
|
||||
__FILE__
|
||||
|
||||
#line 24
|
||||
__FILE__
|
||||
|
||||
#line 42
|
||||
__FILE__
|
||||
|
||||
#line 30 "b.cc"
|
||||
__FILE__
|
||||
|
||||
#line 10 3
|
||||
__FILE__
|
||||
|
||||
#line 48
|
||||
__FILE__
|
||||
|
||||
#line 4
|
||||
__FILE__
|
||||
|
||||
#line 55 100
|
||||
__FILE__
|
||||
|
||||
#line 1000 "c"
|
||||
__FILE__
|
||||
|
||||
#line 42 1
|
||||
__FILE__
|
||||
|
||||
#line 42 "this-is-a-quite-long-name-maybe-i-should-shorten-it"
|
||||
__FILE__
|
36
Test/preprocessor.cpp_style_line_directive.vert
Normal file
36
Test/preprocessor.cpp_style_line_directive.vert
Normal file
@ -0,0 +1,36 @@
|
||||
#extension GL_GOOGLE_cpp_style_line_directive : enable
|
||||
|
||||
#error at "0:3"
|
||||
|
||||
#line 150 "a.h"
|
||||
#error at "a.h:150"
|
||||
|
||||
#line 24
|
||||
#error at "a.h:24"
|
||||
|
||||
#line 42
|
||||
#error at "a.h:42"
|
||||
|
||||
#line 30 "b.cc"
|
||||
#error at "b.cc:30"
|
||||
|
||||
#line 10 3
|
||||
#error at "3:10"
|
||||
|
||||
#line 48
|
||||
#error at "3:48"
|
||||
|
||||
#line 4
|
||||
#error at "3:4"
|
||||
|
||||
#line 55 100
|
||||
#error at "100:55"
|
||||
|
||||
#line 1000 "c"
|
||||
#error at "c:1000"
|
||||
|
||||
#line 42 1
|
||||
#error at "1:42"
|
||||
|
||||
#line 42 "this-is-a-quite-long-name-maybe-i-should-shorten-it"
|
||||
#error at "this-is-a-quite-long-name-maybe-i-should-shorten-it:42"
|
@ -1,3 +1,4 @@
|
||||
preprocessor.cpp_style_line_directive.vert
|
||||
preprocessor.edge_cases.vert
|
||||
preprocessor.errors.vert
|
||||
preprocessor.extensions.vert
|
||||
|
@ -189,7 +189,8 @@ inline const TString String(const int i, const int base = 10)
|
||||
}
|
||||
|
||||
struct TSourceLoc {
|
||||
void init() { string = 0; line = 0; column = 0; }
|
||||
void init() { name = nullptr; string = 0; line = 0; column = 0; }
|
||||
const char* name; // descriptive name for this string
|
||||
int string;
|
||||
int line;
|
||||
int column;
|
||||
|
@ -96,9 +96,14 @@ public:
|
||||
}
|
||||
}
|
||||
void location(TSourceLoc loc) {
|
||||
const int maxSize = 24;
|
||||
const int maxSize = 24;
|
||||
char locText[maxSize];
|
||||
snprintf(locText, maxSize, "%d:%d", loc.string, loc.line);
|
||||
if (loc.name != nullptr) {
|
||||
append(loc.name);
|
||||
snprintf(locText, maxSize, ":%d", loc.line);
|
||||
} else {
|
||||
snprintf(locText, maxSize, "%d:%d", loc.string, loc.line);
|
||||
}
|
||||
append(locText);
|
||||
append(": ");
|
||||
}
|
||||
|
@ -5346,10 +5346,10 @@ void TParseContext::notifyErrorDirective(int line, const char* error_message)
|
||||
}
|
||||
}
|
||||
|
||||
void TParseContext::notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum)
|
||||
void TParseContext::notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName)
|
||||
{
|
||||
if (lineCallback) {
|
||||
lineCallback(curLineNo, newLineNo, hasSource, sourceNum);
|
||||
lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,6 +214,7 @@ public:
|
||||
int getNumErrors() const { return numErrors; }
|
||||
const TSourceLoc& getCurrentLoc() const { return currentScanner->getSourceLoc(); }
|
||||
void setCurrentLine(int line) { currentScanner->setLine(line); }
|
||||
void setCurrentSourceName(const char* name) { currentScanner->setFile(name); }
|
||||
void setCurrentString(int string) { currentScanner->setString(string); }
|
||||
void setScanner(TInputScanner* scanner) { currentScanner = scanner; }
|
||||
|
||||
@ -221,7 +222,7 @@ public:
|
||||
|
||||
void notifyVersion(int line, int version, const char* type_string);
|
||||
void notifyErrorDirective(int line, const char* error_message);
|
||||
void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum);
|
||||
void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName);
|
||||
void notifyExtensionDirective(int line, const char* extension, const char* behavior);
|
||||
|
||||
// The following are implemented in Versions.cpp to localize version/profile/stage/extensions control
|
||||
@ -243,7 +244,7 @@ public:
|
||||
|
||||
void setVersionCallback(const std::function<void(int, int, const char*)>& func) { versionCallback = func; }
|
||||
void setPragmaCallback(const std::function<void(int, const TVector<TString>&)>& func) { pragmaCallback = func; }
|
||||
void setLineCallback(const std::function<void(int, int, bool, int)>& func) { lineCallback = func; }
|
||||
void setLineCallback(const std::function<void(int, int, bool, int, const char*)>& func) { lineCallback = func; }
|
||||
void setExtensionCallback(const std::function<void(int, const char*, const char*)>& func) { extensionCallback = func; }
|
||||
void setErrorCallback(const std::function<void(int, const char*)>& func) { errorCallback = func; }
|
||||
|
||||
@ -357,7 +358,7 @@ protected:
|
||||
|
||||
// These, if set, will be called when a line, pragma ... is preprocessed.
|
||||
// They will be called with any parameters to the original directive.
|
||||
std::function<void(int, int, bool, int)> lineCallback;
|
||||
std::function<void(int, int, bool, int, const char*)> lineCallback;
|
||||
std::function<void(int, const TVector<TString>&)> pragmaCallback;
|
||||
std::function<void(int, int, const char*)> versionCallback;
|
||||
std::function<void(int, const char*, const char*)> extensionCallback;
|
||||
|
@ -57,6 +57,9 @@ public:
|
||||
lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f)
|
||||
{
|
||||
loc = new TSourceLoc[numSources];
|
||||
for (int i = 0; i < numSources; ++i) {
|
||||
loc[i].init();
|
||||
}
|
||||
loc[currentSource].string = -stringBias;
|
||||
loc[currentSource].line = 1;
|
||||
loc[currentSource].column = 0;
|
||||
@ -140,7 +143,12 @@ public:
|
||||
|
||||
// for #line override
|
||||
void setLine(int newLine) { loc[getLastValidSourceIndex()].line = newLine; }
|
||||
void setString(int newString) { loc[getLastValidSourceIndex()].string = newString; }
|
||||
void setFile(const char* filename) { loc[getLastValidSourceIndex()].name = filename; }
|
||||
void setString(int newString)
|
||||
{
|
||||
loc[getLastValidSourceIndex()].string = newString;
|
||||
loc[getLastValidSourceIndex()].name = nullptr;
|
||||
}
|
||||
|
||||
const TSourceLoc& getSourceLoc() const { return loc[std::max(0, std::min(currentSource, numSources - finale - 1))]; }
|
||||
// Returns the index (starting from 0) of the most recent valid source string we are reading from.
|
||||
|
@ -690,12 +690,17 @@ struct DoPreprocessing {
|
||||
});
|
||||
|
||||
parseContext.setLineCallback([&lineSync, &outputStream, &parseContext](
|
||||
int curLineNum, int newLineNum, bool hasSource, int sourceNum) {
|
||||
int curLineNum, int newLineNum, bool hasSource, int sourceNum, const char* sourceName) {
|
||||
// SourceNum is the number of the source-string that is being parsed.
|
||||
lineSync.syncToLine(curLineNum);
|
||||
outputStream << "#line " << newLineNum;
|
||||
if (hasSource) {
|
||||
outputStream << " " << sourceNum;
|
||||
outputStream << " ";
|
||||
if (sourceName != nullptr) {
|
||||
outputStream << "\"" << sourceName << "\"";
|
||||
} else {
|
||||
outputStream << sourceNum;
|
||||
}
|
||||
}
|
||||
if (parseContext.lineDirectiveShouldSetNextLine()) {
|
||||
// newLineNum is the new line number for the line following the #line
|
||||
|
@ -190,6 +190,7 @@ void TParseContext::initializeExtensionBehavior()
|
||||
extensionBehavior[E_GL_EXT_tessellation_point_size] = EBhDisable;
|
||||
extensionBehavior[E_GL_EXT_texture_buffer] = EBhDisablePartial;
|
||||
extensionBehavior[E_GL_EXT_texture_cube_map_array] = EBhDisablePartial;
|
||||
extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhDisable;
|
||||
|
||||
// OES matching AEP
|
||||
extensionBehavior[E_GL_OES_geometry_shader] = EBhDisable;
|
||||
@ -233,6 +234,7 @@ const char* TParseContext::getPreamble()
|
||||
"#define GL_EXT_tessellation_point_size 1\n"
|
||||
"#define GL_EXT_texture_buffer 1\n"
|
||||
"#define GL_EXT_texture_cube_map_array 1\n"
|
||||
"#define GL_GOOGLE_cpp_style_line_directive 1\n"
|
||||
|
||||
// OES matching AEP
|
||||
"#define GL_OES_geometry_shader 1\n"
|
||||
@ -264,6 +266,7 @@ const char* TParseContext::getPreamble()
|
||||
"#define GL_ARB_derivative_control 1\n"
|
||||
"#define GL_ARB_shader_texture_image_samples 1\n"
|
||||
"#define GL_ARB_viewport_array 1\n"
|
||||
"#define GL_GOOGLE_cpp_style_line_directive 1\n"
|
||||
// "#define GL_ARB_cull_distance 1\n" // present for 4.5, but need extension control over block members
|
||||
;
|
||||
}
|
||||
|
@ -129,6 +129,8 @@ const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessel
|
||||
const char* const E_GL_EXT_texture_buffer = "GL_EXT_texture_buffer";
|
||||
const char* const E_GL_EXT_texture_cube_map_array = "GL_EXT_texture_cube_map_array";
|
||||
|
||||
const char* const E_GL_GOOGLE_cpp_style_line_directive = "GL_GOOGLE_cpp_style_line_directive";
|
||||
|
||||
// OES matching AEP
|
||||
const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader";
|
||||
const char* const E_GL_OES_geometry_point_size = "GL_OES_geometry_point_size";
|
||||
|
@ -612,8 +612,9 @@ int TPpContext::CPPline(TPpToken* ppToken)
|
||||
|
||||
int lineRes = 0; // Line number after macro expansion.
|
||||
int lineToken = 0;
|
||||
int fileRes = 0; // Source file number after macro expansion.
|
||||
bool hasFile = false;
|
||||
int fileRes = 0; // Source file number after macro expansion.
|
||||
const char* sourceName = nullptr; // Optional source file name.
|
||||
bool lineErr = false;
|
||||
bool fileErr = false;
|
||||
token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken);
|
||||
@ -627,14 +628,25 @@ int TPpContext::CPPline(TPpToken* ppToken)
|
||||
parseContext.setCurrentLine(lineRes);
|
||||
|
||||
if (token != '\n') {
|
||||
token = eval(token, MIN_PRECEDENCE, false, fileRes, fileErr, ppToken);
|
||||
if (! fileErr)
|
||||
parseContext.setCurrentString(fileRes);
|
||||
if (parseContext.extensionTurnedOn(E_GL_GOOGLE_cpp_style_line_directive) && token == PpAtomConstString) {
|
||||
// We need to save a copy of the string instead of pointing
|
||||
// to the name field of the token since the name field
|
||||
// will likely be overwritten by the next token scan.
|
||||
sourceName = GetAtomString(LookUpAddString(ppToken->name));
|
||||
parseContext.setCurrentSourceName(sourceName);
|
||||
hasFile = true;
|
||||
token = scanToken(ppToken);
|
||||
} else {
|
||||
token = eval(token, MIN_PRECEDENCE, false, fileRes, fileErr, ppToken);
|
||||
if (! fileErr) {
|
||||
parseContext.setCurrentString(fileRes);
|
||||
hasFile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!fileErr && !lineErr) {
|
||||
parseContext.notifyLineDirective(directiveLoc, lineToken, hasFile, fileRes);
|
||||
parseContext.notifyLineDirective(directiveLoc, lineToken, hasFile, fileRes, sourceName);
|
||||
}
|
||||
token = extraTokenCheck(PpAtomLine, ppToken, token);
|
||||
|
||||
@ -952,11 +964,17 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool
|
||||
UngetToken(PpAtomConstInt, ppToken);
|
||||
return 1;
|
||||
|
||||
case PpAtomFileMacro:
|
||||
ppToken->ival = parseContext.getCurrentLoc().string;
|
||||
sprintf(ppToken->name, "%d", ppToken->ival);
|
||||
case PpAtomFileMacro: {
|
||||
const char* current_file = parseContext.getCurrentLoc().name;
|
||||
if (parseContext.extensionTurnedOn(E_GL_GOOGLE_cpp_style_line_directive) && current_file != nullptr) {
|
||||
sprintf(ppToken->name, "\"%s\"", current_file);
|
||||
} else {
|
||||
ppToken->ival = parseContext.getCurrentLoc().string;
|
||||
sprintf(ppToken->name, "%d", ppToken->ival);
|
||||
}
|
||||
UngetToken(PpAtomConstInt, ppToken);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case PpAtomVersionMacro:
|
||||
ppToken->ival = parseContext.version;
|
||||
|
Loading…
Reference in New Issue
Block a user