Merge pull request #16 from google/pp-directive

Preprocessing directive handling
This commit is contained in:
John Kessenich 2015-07-14 19:36:29 -06:00
commit 279012d8c4
9 changed files with 87 additions and 48 deletions

View File

@ -0,0 +1,2 @@
Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.

View File

@ -0,0 +1,5 @@
#version 310 es
#line 1 2
#pragma something
void main(){ }

View File

@ -1,24 +1,39 @@
#line 300 #line 300
#line 2 #line 2
#line 10
#line 2
#line 0 #line 10
#line 4
#line 2
#line 8
#line 0
void main(){
gl_Position = vec4(10);
}
#line 8 4 #line 4
#line 12 3
#line 1
#line 8
void main(){
gl_Position = vec4(10);
}
#line 8 4
#line 12 3
#line 1

View File

@ -0,0 +1,4 @@
#version 310 es
#line 1 2
#pragma something
void main() {}

View File

@ -3,6 +3,7 @@ preprocessor.errors.vert
preprocessor.extensions.vert preprocessor.extensions.vert
preprocessor.function_macro.vert preprocessor.function_macro.vert
preprocessor.line.vert preprocessor.line.vert
preprocessor.line.frag
preprocessor.pragma.vert preprocessor.pragma.vert
preprocessor.simple.vert preprocessor.simple.vert
preprocessor.success_if_parse_would_fail.vert preprocessor.success_if_parse_would_fail.vert

View File

@ -2673,6 +2673,19 @@ void TParseContext::updateImplicitArraySize(TSourceLoc loc, TIntermNode *node, i
symbol->getWritableType().setImplicitArraySize(index + 1); symbol->getWritableType().setImplicitArraySize(index + 1);
} }
// Returns true if the first argument to the #line directive is the line number for the next line.
//
// Desktop, pre-version 3.30: "After processing this directive
// (including its new-line), the implementation will behave as if it is compiling at line number line+1 and
// source string number source-string-number."
//
// Desktop, version 3.30 and later, and ES: "After processing this directive
// (including its new-line), the implementation will behave as if it is compiling at line number line and
// source string number source-string-number.
bool TParseContext::lineDirectiveShouldSetNextLine() const {
return profile == EEsProfile || version >= 330;
}
// //
// Enforce non-initializer type/qualifier rules. // Enforce non-initializer type/qualifier rules.
// //
@ -5291,10 +5304,10 @@ void TParseContext::notifyErrorDirective(int line, const char* error_message)
} }
} }
void TParseContext::notifyLineDirective(int line, bool has_source, int source) void TParseContext::notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum)
{ {
if (lineCallback) { if (lineCallback) {
lineCallback(line, has_source, source); lineCallback(curLineNo, newLineNo, hasSource, sourceNum);
} }
} }

View File

@ -217,9 +217,11 @@ public:
void setCurrentString(int string) { currentScanner->setString(string); } void setCurrentString(int string) { currentScanner->setString(string); }
void setScanner(TInputScanner* scanner) { currentScanner = scanner; } void setScanner(TInputScanner* scanner) { currentScanner = scanner; }
bool lineDirectiveShouldSetNextLine() const;
void notifyVersion(int line, int version, const char* type_string); void notifyVersion(int line, int version, const char* type_string);
void notifyErrorDirective(int line, const char* error_message); void notifyErrorDirective(int line, const char* error_message);
void notifyLineDirective(int line, bool has_source, int source); void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum);
// The following are implemented in Versions.cpp to localize version/profile/stage/extensions control // The following are implemented in Versions.cpp to localize version/profile/stage/extensions control
void initializeExtensionBehavior(); void initializeExtensionBehavior();
@ -240,7 +242,7 @@ public:
void setVersionCallback(const std::function<void(int, int, const char*)>& func) { versionCallback = func; } 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 setPragmaCallback(const std::function<void(int, const TVector<TString>&)>& func) { pragmaCallback = func; }
void setLineCallback(const std::function<void(int, bool, int)>& func) { lineCallback = func; } void setLineCallback(const std::function<void(int, int, bool, int)>& func) { lineCallback = func; }
void setExtensionCallback(const std::function<void(int, const char*, const char*)>& func) { extensionCallback = 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; } void setErrorCallback(const std::function<void(int, const char*)>& func) { errorCallback = func; }
@ -354,7 +356,7 @@ protected:
// These, if set, will be called when a line, pragma ... is preprocessed. // These, if set, will be called when a line, pragma ... is preprocessed.
// They will be called with any parameters to the original directive. // They will be called with any parameters to the original directive.
std::function<void(int, bool, int)> lineCallback; std::function<void(int, int, bool, int)> lineCallback;
std::function<void(int, const TVector<TString>&)> pragmaCallback; std::function<void(int, const TVector<TString>&)> pragmaCallback;
std::function<void(int, int, const char*)> versionCallback; std::function<void(int, int, const char*)> versionCallback;
std::function<void(int, const char*, const char*)> extensionCallback; std::function<void(int, const char*, const char*)> extensionCallback;

View File

@ -639,30 +639,33 @@ struct DoPreprocessing {
adjustLine(line); adjustLine(line);
outputStream << "#extension " << extension << " : " << behavior; outputStream << "#extension " << extension << " : " << behavior;
}); });
parseContext.setLineCallback([&lastLine, &outputStream]( parseContext.setLineCallback([&adjustLine, &lastLine, &outputStream, &parseContext](
int line, bool hasSource, int sourceNum) { int curLineNo, int newLineNo, bool hasSource, int sourceNum) {
// SourceNum is the number of the source-string that is being parsed. // SourceNum is the number of the source-string that is being parsed.
if (lastLine != -1) { adjustLine(curLineNo);
outputStream << std::endl; outputStream << "#line " << newLineNo;
}
outputStream << "#line " << line;
if (hasSource) { if (hasSource) {
outputStream << " " << sourceNum; outputStream << " " << sourceNum;
} }
if (parseContext.lineDirectiveShouldSetNextLine()) {
// newLineNo is the new line number for the line following the #line
// directive. So the new line number for the current line is
newLineNo -= 1;
}
outputStream << std::endl; outputStream << std::endl;
lastLine = std::max(line - 1, 1); // Line number starts from 1. And we are at the next line of the #line
// directive now. So lastLine (from 0) should be (newLineNo - 1) + 1.
lastLine = newLineNo;
}); });
parseContext.setVersionCallback( parseContext.setVersionCallback(
[&adjustLine, &lastLine, &outputStream](int line, int version, const char* str) { [&adjustLine, &outputStream](int line, int version, const char* str) {
adjustLine(line); adjustLine(line);
outputStream << "#version " << version; outputStream << "#version " << version;
if (str) { if (str) {
outputStream << " " << str; outputStream << " " << str;
} }
outputStream << std::endl;
++lastLine;
}); });
parseContext.setPragmaCallback([&adjustLine, &outputStream]( parseContext.setPragmaCallback([&adjustLine, &outputStream](

View File

@ -624,6 +624,7 @@ int TPpContext::CPPline(TPpToken* ppToken)
// "#line line source-string-number" // "#line line source-string-number"
int token = scanToken(ppToken); int token = scanToken(ppToken);
const int directiveLoc = ppToken->loc.line;
if (token == '\n') { if (token == '\n') {
parseContext.ppError(ppToken->loc, "must by followed by an integral literal", "#line", ""); parseContext.ppError(ppToken->loc, "must by followed by an integral literal", "#line", "");
return token; return token;
@ -641,14 +642,7 @@ int TPpContext::CPPline(TPpToken* ppToken)
if (token == '\n') if (token == '\n')
++lineRes; ++lineRes;
// Desktop, pre-version 3.30: "After processing this directive if (parseContext.lineDirectiveShouldSetNextLine())
// (including its new-line), the implementation will behave as if it is compiling at line number line+1 and
// source string number source-string-number."
//
// Desktop, version 3.30 and later, and ES: "After processing this directive
// (including its new-line), the implementation will behave as if it is compiling at line number line and
// source string number source-string-number.
if (parseContext.profile == EEsProfile || parseContext.version >= 330)
--lineRes; --lineRes;
parseContext.setCurrentLine(lineRes); parseContext.setCurrentLine(lineRes);
@ -660,7 +654,7 @@ int TPpContext::CPPline(TPpToken* ppToken)
} }
} }
if (!fileErr && !lineErr) { if (!fileErr && !lineErr) {
parseContext.notifyLineDirective(lineToken, hasFile, fileRes); parseContext.notifyLineDirective(directiveLoc, lineToken, hasFile, fileRes);
} }
token = extraTokenCheck(lineAtom, ppToken, token); token = extraTokenCheck(lineAtom, ppToken, token);