PP: Recognize <> style #include header names. I.e., #include <header-name>.
authorJohn Kessenich <cepheus@frii.com>
Tue, 3 Jan 2017 03:12:08 +0000 (20:12 -0700)
committerJohn Kessenich <cepheus@frii.com>
Tue, 3 Jan 2017 18:05:16 +0000 (11:05 -0700)
Also correctly test and handle missing newline.

Test/baseResults/preprocessor.include.disabled.vert.err
Test/baseResults/preprocessor.include.enabled.vert.err
Test/preprocessor.include.disabled.vert
Test/preprocessor.include.enabled.vert
glslang/Include/revision.h
glslang/MachineIndependent/preprocessor/Pp.cpp
glslang/MachineIndependent/preprocessor/PpContext.h
glslang/MachineIndependent/preprocessor/PpScanner.cpp

index 7d1f0a0..da17047 100644 (file)
@@ -1,13 +1,13 @@
 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' : 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' : unexpected 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' : unexpected include directiv
+ERROR: 0:8004: '#include' : expected newlin
 ERROR: 10 compilation errors.  No code generated.
 
 
index be8c5cf..b19b835 100644 (file)
@@ -1,8 +1,13 @@
-ERROR: 0:8000: '#include' : must be followed by a file designation 
-ERROR: 0:8001: '#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 header name 
 ERROR: 0:8002: '#include' : unexpected include directive 
-ERROR: 0:8003: '#include' : extra content after file designation 
-ERROR: 0:8004: '#include' : unexpected include directive 
-ERROR: 5 compilation errors.  No code generated.
+ERROR: 0:8003: '#include' : unexpected include directive 
+ERROR: 0:8004: '#include' : extra content after header name 
+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.
 
 
index 130d928..865baa1 100644 (file)
@@ -3,5 +3,4 @@
 #include 123
 #include "foo"
 #include "foo" garbage
-#include "no-eol"
-
+#include "no-eol"
\ No newline at end of file
index ecdf466..6d64b23 100644 (file)
@@ -3,5 +3,11 @@
 #include\r
 #include 123\r
 #include "foo"\r
+#include <foo>\r
 #include "foo" garbage\r
-#include "no-eol"\r
+#include <foo> garbage\r
+// max length\r
+#include <ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789>\r
+// too long\r
+#include <ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF01234567890>\r
+#include "no-eol"
\ No newline at end of file
index cccc796..cee8a8b 100644 (file)
@@ -2,5 +2,5 @@
 // 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).
 
-#define GLSLANG_REVISION "Overload400-PrecQual.1728"
-#define GLSLANG_DATE "02-Jan-2017"
+#define GLSLANG_REVISION "Overload400-PrecQual.1730"
+#define GLSLANG_DATE "03-Jan-2017"
index eb2f3df..02e4521 100644 (file)
@@ -571,46 +571,61 @@ int TPpContext::CPPifdef(int defined, TPpToken* ppToken)
     return token;
 }
 
-// Handle #include
+// Handle #include ...
+// TODO: Handle macro expansions for the header name
 int TPpContext::CPPinclude(TPpToken* ppToken)
 {
     const TSourceLoc directiveLoc = ppToken->loc;
+    TShader::Includer::IncludeType includeType = TShader::Includer::EIncludeRelative;
     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) {
-        // TODO: handle angle brackets.
-        parseContext.ppError(directiveLoc, "must be followed by a file designation", "#include", "");
+        parseContext.ppError(directiveLoc, "must be followed by a header name", "#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 {
-        // 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' && token != EndOfInput) {
-            parseContext.ppError(ppToken->loc, "extra content after file designation", "#include", "");
+        TShader::Includer::IncludeResult* res = includer.include(filename.c_str(), includeType, currentSourceFile.c_str(), includeStack.size() + 1);
+        if (res && !res->file_name.empty()) {
+            if (res->file_data && res->file_length) {
+                const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine();
+                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 {
-            TShader::Includer::IncludeResult* res = includer.include(filename.c_str(), TShader::Includer::EIncludeRelative, currentSourceFile.c_str(), includeStack.size() + 1);
-            if (res && !res->file_name.empty()) {
-                if (res->file_data && res->file_length) {
-                    const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine();
-                    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 {
-                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);
-                }
+            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;
 }
 
@@ -911,6 +926,38 @@ int TPpContext::readCPPline(TPpToken* ppToken)
     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'.
 // Does not replace 'arg'.
 // Returns nullptr if no expanded argument is created.
index 64f99ef..84c1bef 100644 (file)
@@ -368,6 +368,7 @@ protected:
     int CPPversion(TPpToken * ppToken);
     int CPPextension(TPpToken * ppToken);
     int readCPPline(TPpToken * ppToken);
+    int scanHeaderName(TPpToken* ppToken, char delimit);
     TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay);
     int MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay);
 
index 4bb7c93..426e44e 100644 (file)
@@ -688,6 +688,9 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
             }
             break;
         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();
             while (ch != '"' && ch != '\n' && ch != EndOfInput) {
                 if (len < MaxTokenLength) {