1) Allow '\' before a non-newline as a token in the preprocessor, and 2) localize...
authorJohn Kessenich <cepheus@frii.com>
Mon, 16 Dec 2013 23:58:15 +0000 (23:58 +0000)
committerJohn Kessenich <cepheus@frii.com>
Mon, 16 Dec 2013 23:58:15 +0000 (23:58 +0000)
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24530 e7fa87d3-cd2b-0410-9028-fcbf551c1848

Install/Windows/glslangValidator.exe
Test/baseResults/lineContinuation.vert.out
Test/baseResults/lineContinuation100.vert.out
Test/lineContinuation.vert
Test/lineContinuation100.vert
glslang/Include/revision.h
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/Scan.cpp
glslang/MachineIndependent/preprocessor/Pp.cpp
glslang/MachineIndependent/preprocessor/PpScanner.cpp

index 0c00fc8..d138589 100644 (file)
Binary files a/Install/Windows/glslangValidator.exe and b/Install/Windows/glslangValidator.exe differ
index 344099b..c41ee1b 100644 (file)
@@ -3,7 +3,16 @@ WARNING: 0:3: 'line continuation' : used at end of comment; the following line i
 ERROR: 0:6: '#error' : e1  \r
 ERROR: 0:11: '#error' : e2  \r
 ERROR: 0:18: '#error' : e3  \r
-ERROR: 3 compilation errors.  No code generated.\r
+ERROR: 0:42: '\' : illegal use of escape character \r
+ERROR: 0:43: '@' : unexpected token \r
+ERROR: 0:44: '$' : unexpected token \r
+ERROR: 0:45: '\' : illegal use of escape character \r
+ERROR: 0:47: '\' : illegal use of escape character \r
+ERROR: 0:48: '\' : illegal use of escape character \r
+ERROR: 0:49: '$' : unexpected token \r
+ERROR: 0:50: '@' : unexpected token \r
+ERROR: 0:55: '#error' : good continuation  \r
+ERROR: 12 compilation errors.  No code generated.\r
 \r
 \r
 ERROR: node is still EOpNull!\r
@@ -24,9 +33,56 @@ ERROR: node is still EOpNull!
 0:24          'a' (in highp 4-component vector of float)\r
 0:25      Branch: Return with expression\r
 0:25        'b' (highp 4-component vector of float)\r
+0:42  Sequence\r
+0:42    move second child to first child (highp int)\r
+0:42      'a1' (highp int)\r
+0:42      Constant:\r
+0:42        4 (const int)\r
+0:43  Sequence\r
+0:43    move second child to first child (highp int)\r
+0:43      'a2' (highp int)\r
+0:43      Constant:\r
+0:43        3 (const int)\r
+0:44  Sequence\r
+0:44    move second child to first child (highp int)\r
+0:44      'a3' (highp int)\r
+0:44      Constant:\r
+0:44        4 (const int)\r
+0:45  Sequence\r
+0:45    move second child to first child (highp int)\r
+0:45      'a4' (highp int)\r
+0:45      'a2' (highp int)\r
+0:47  Sequence\r
+0:47    move second child to first child (highp int)\r
+0:47      'q1' (highp int)\r
+0:47      Constant:\r
+0:47        1 (const int)\r
+0:48  Sequence\r
+0:48    move second child to first child (highp int)\r
+0:48      'q2' (highp int)\r
+0:48      Constant:\r
+0:48        1 (const int)\r
+0:49  Sequence\r
+0:49    move second child to first child (highp int)\r
+0:49      'q3' (highp int)\r
+0:49      Constant:\r
+0:49        1 (const int)\r
+0:50  Sequence\r
+0:50    move second child to first child (highp int)\r
+0:50      'q4' (highp int)\r
+0:50      Constant:\r
+0:50        1 (const int)\r
 0:?   Linker Objects\r
 0:?     'foo' (highp float)\r
 0:?     'goodDecl' (highp int)\r
+0:?     'a1' (highp int)\r
+0:?     'a2' (highp int)\r
+0:?     'a3' (highp int)\r
+0:?     'a4' (highp int)\r
+0:?     'q1' (highp int)\r
+0:?     'q2' (highp int)\r
+0:?     'q3' (highp int)\r
+0:?     'q4' (highp int)\r
 0:?     'gl_VertexID' (gl_VertexId highp int)\r
 0:?     'gl_InstanceID' (gl_InstanceId highp int)\r
 \r
index 7519146..6312793 100644 (file)
@@ -8,7 +8,18 @@ ERROR: 0:14: 'line continuation' : not supported for this version or the enabled
 ERROR: 0:15: 'line continuation' : not supported for this version or the enabled extensions \r
 ERROR: 0:18: '#error' : e3  \r
 ERROR: 0:24: 'line continuation' : not supported for this version or the enabled extensions \r
-ERROR: 8 compilation errors.  No code generated.\r
+ERROR: 0:40: '\' : illegal use of escape character \r
+ERROR: 0:41: '@' : unexpected token \r
+ERROR: 0:42: '$' : unexpected token \r
+ERROR: 0:43: '\' : illegal use of escape character \r
+ERROR: 0:45: '\' : illegal use of escape character \r
+ERROR: 0:46: '\' : illegal use of escape character \r
+ERROR: 0:47: '$' : unexpected token \r
+ERROR: 0:48: '@' : unexpected token \r
+ERROR: 0:50: 'line continuation' : not supported for this version or the enabled extensions \r
+ERROR: 0:52: 'line continuation' : not supported for this version or the enabled extensions \r
+ERROR: 0:53: '#error' : bad continuation  \r
+ERROR: 19 compilation errors.  No code generated.\r
 \r
 \r
 ERROR: node is still EOpNull!\r
@@ -29,8 +40,55 @@ ERROR: node is still EOpNull!
 0:24          'a' (in highp 4-component vector of float)\r
 0:25      Branch: Return with expression\r
 0:25        'b' (highp 4-component vector of float)\r
+0:40  Sequence\r
+0:40    move second child to first child (highp int)\r
+0:40      'a1' (highp int)\r
+0:40      Constant:\r
+0:40        4 (const int)\r
+0:41  Sequence\r
+0:41    move second child to first child (highp int)\r
+0:41      'a2' (highp int)\r
+0:41      Constant:\r
+0:41        3 (const int)\r
+0:42  Sequence\r
+0:42    move second child to first child (highp int)\r
+0:42      'a3' (highp int)\r
+0:42      Constant:\r
+0:42        4 (const int)\r
+0:43  Sequence\r
+0:43    move second child to first child (highp int)\r
+0:43      'a4' (highp int)\r
+0:43      'a2' (highp int)\r
+0:45  Sequence\r
+0:45    move second child to first child (highp int)\r
+0:45      'q1' (highp int)\r
+0:45      Constant:\r
+0:45        1 (const int)\r
+0:46  Sequence\r
+0:46    move second child to first child (highp int)\r
+0:46      'q2' (highp int)\r
+0:46      Constant:\r
+0:46        1 (const int)\r
+0:47  Sequence\r
+0:47    move second child to first child (highp int)\r
+0:47      'q3' (highp int)\r
+0:47      Constant:\r
+0:47        1 (const int)\r
+0:48  Sequence\r
+0:48    move second child to first child (highp int)\r
+0:48      'q4' (highp int)\r
+0:48      Constant:\r
+0:48        1 (const int)\r
 0:?   Linker Objects\r
 0:?     'foo' (highp float)\r
+0:?     'a1' (highp int)\r
+0:?     'a2' (highp int)\r
+0:?     'a3' (highp int)\r
+0:?     'a4' (highp int)\r
+0:?     'q1' (highp int)\r
+0:?     'q2' (highp int)\r
+0:?     'q3' (highp int)\r
+0:?     'q4' (highp int)\r
 \r
 \r
 Linked vertex stage:\r
index a70b625..7c0e29b 100644 (file)
@@ -34,3 +34,24 @@ vec4 foo2(vec4 a)
 
 FOO
 
+#define A int q1 = \ 1
+#define B int q2 = \1
+#define C int q3 = $ 1
+#define D int q4 = @ 1
+
+int a1 = \ 4;  // ERROR
+int a2 = @ 3;  // ERROR
+int a3 = $4;   // ERROR
+int a4 = a2\;  // ERROR
+
+A;
+B;
+C;
+D;
+
+# \
+
+# \
+    error good continuation
+
+#define AA a \ b
index b68b715..5bb112a 100644 (file)
@@ -31,3 +31,23 @@ vec4 foo2(vec4 a)
 /*@*/\r
 /* *@/*/\r
 //@\r
+\r
+#define A int q1 = \ 1\r
+#define B int q2 = \1\r
+#define C int q3 = $ 1\r
+#define D int q4 = @ 1\r
+\r
+int a1 = \ 4;  // ERROR\r
+int a2 = @ 3;  // ERROR\r
+int a3 = $4;   // ERROR\r
+int a4 = a2\;  // ERROR\r
+\r
+A;\r
+B;\r
+C;\r
+D;\r
+\r
+# \\r
+\r
+# \\r
+    error bad continuation
\ No newline at end of file
index d5b74af..9f79c7f 100644 (file)
@@ -9,5 +9,5 @@
 // source have to figure out how to create revision.h just to get a build\r
 // going.  However, if it is not updated, it can be a version behind.\r
 \r
-#define GLSLANG_REVISION "24518"\r
-#define GLSLANG_DATE     "2013/12/13 11:38:43"\r
+#define GLSLANG_REVISION "24522"\r
+#define GLSLANG_DATE     "2013/12/13 12:26:54"\r
index 0f4e6d7..d208056 100644 (file)
@@ -1484,6 +1484,7 @@ bool TParseContext::lineContinuationCheck(TSourceLoc loc, bool endOfComment)
 
     if (messages & EShMsgRelaxedErrors) {
         warn(loc, "not allowed in this version", message, "");
+        return true;
     } else {
         requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, message);
         profileRequires(loc, EEsProfile, 300, 0, message);
index 2c1eb54..9077ca6 100644 (file)
@@ -478,74 +478,82 @@ void TScanContext::fillInKeywordMap()
 
 int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
 {
-    parserToken = &token;
-    TPpToken ppToken;
-    tokenText = pp->tokenize(&ppToken);
-    if (tokenText == 0)
-        return 0;
+    do {
+        parserToken = &token;
+        TPpToken ppToken;
+        tokenText = pp->tokenize(&ppToken);
+        if (tokenText == 0)
+            return 0;
+
+        loc = ppToken.loc;
+        parserToken->sType.lex.loc = loc;
+        switch (ppToken.token) {
+        case ';':  afterType = false;   return SEMICOLON;
+        case ',':  afterType = false;   return COMMA;
+        case ':':                       return COLON;
+        case '=':  afterType = false;   return EQUAL;
+        case '(':  afterType = false;   return LEFT_PAREN;
+        case ')':  afterType = false;   return RIGHT_PAREN;
+        case '.':  field = true;        return DOT;
+        case '!':                       return BANG;
+        case '-':                       return DASH;
+        case '~':                       return TILDE;
+        case '+':                       return PLUS;
+        case '*':                       return STAR;
+        case '/':                       return SLASH;
+        case '%':                       return PERCENT;
+        case '<':                       return LEFT_ANGLE;
+        case '>':                       return RIGHT_ANGLE;
+        case '|':                       return VERTICAL_BAR;
+        case '^':                       return CARET;
+        case '&':                       return AMPERSAND;
+        case '?':                       return QUESTION;
+        case '[':                       return LEFT_BRACKET;
+        case ']':                       return RIGHT_BRACKET;
+        case '{':                       return LEFT_BRACE;
+        case '}':                       return RIGHT_BRACE;
+        case '\\':
+            parseContext.error(loc, "illegal use of escape character", "\\", "");
+            break;
 
-    loc = ppToken.loc;
-    parserToken->sType.lex.loc = loc;
-    switch (ppToken.token) {
-    case ';':  afterType = false;   return SEMICOLON;
-    case ',':  afterType = false;   return COMMA;
-    case ':':                       return COLON;
-    case '=':  afterType = false;   return EQUAL;
-    case '(':  afterType = false;   return LEFT_PAREN;
-    case ')':  afterType = false;   return RIGHT_PAREN;
-    case '.':  field = true;        return DOT;
-    case '!':                       return BANG;
-    case '-':                       return DASH;
-    case '~':                       return TILDE;
-    case '+':                       return PLUS;
-    case '*':                       return STAR;
-    case '/':                       return SLASH;
-    case '%':                       return PERCENT;
-    case '<':                       return LEFT_ANGLE;
-    case '>':                       return RIGHT_ANGLE;
-    case '|':                       return VERTICAL_BAR;
-    case '^':                       return CARET;
-    case '&':                       return AMPERSAND;
-    case '?':                       return QUESTION;
-    case '[':                       return LEFT_BRACKET;
-    case ']':                       return RIGHT_BRACKET;
-    case '{':                       return LEFT_BRACE;
-    case '}':                       return RIGHT_BRACE;
-
-    case CPP_AND_OP:                return AND_OP;
-    case CPP_SUB_ASSIGN:            return SUB_ASSIGN;
-    case CPP_MOD_ASSIGN:            return MOD_ASSIGN;
-    case CPP_ADD_ASSIGN:            return ADD_ASSIGN;
-    case CPP_DIV_ASSIGN:            return DIV_ASSIGN;
-    case CPP_MUL_ASSIGN:            return MUL_ASSIGN;
-    case CPP_EQ_OP:                 return EQ_OP;
-    case CPP_XOR_OP:                return XOR_OP;
-    case CPP_GE_OP:                 return GE_OP;
-    case CPP_RIGHT_OP:              return RIGHT_OP;
-    case CPP_LE_OP:                 return LE_OP;
-    case CPP_LEFT_OP:               return LEFT_OP;
-    case CPP_DEC_OP:                return DEC_OP;
-    case CPP_NE_OP:                 return NE_OP;
-    case CPP_OR_OP:                 return OR_OP;
-    case CPP_INC_OP:                return INC_OP;
-    case CPP_RIGHT_ASSIGN:          return RIGHT_ASSIGN;
-    case CPP_LEFT_ASSIGN:           return LEFT_ASSIGN;
-    case CPP_AND_ASSIGN:            return AND_ASSIGN;
-    case CPP_OR_ASSIGN:             return OR_ASSIGN;
-    case CPP_XOR_ASSIGN:            return XOR_ASSIGN;
+        case CPP_AND_OP:                return AND_OP;
+        case CPP_SUB_ASSIGN:            return SUB_ASSIGN;
+        case CPP_MOD_ASSIGN:            return MOD_ASSIGN;
+        case CPP_ADD_ASSIGN:            return ADD_ASSIGN;
+        case CPP_DIV_ASSIGN:            return DIV_ASSIGN;
+        case CPP_MUL_ASSIGN:            return MUL_ASSIGN;
+        case CPP_EQ_OP:                 return EQ_OP;
+        case CPP_XOR_OP:                return XOR_OP;
+        case CPP_GE_OP:                 return GE_OP;
+        case CPP_RIGHT_OP:              return RIGHT_OP;
+        case CPP_LE_OP:                 return LE_OP;
+        case CPP_LEFT_OP:               return LEFT_OP;
+        case CPP_DEC_OP:                return DEC_OP;
+        case CPP_NE_OP:                 return NE_OP;
+        case CPP_OR_OP:                 return OR_OP;
+        case CPP_INC_OP:                return INC_OP;
+        case CPP_RIGHT_ASSIGN:          return RIGHT_ASSIGN;
+        case CPP_LEFT_ASSIGN:           return LEFT_ASSIGN;
+        case CPP_AND_ASSIGN:            return AND_ASSIGN;
+        case CPP_OR_ASSIGN:             return OR_ASSIGN;
+        case CPP_XOR_ASSIGN:            return XOR_ASSIGN;
                                    
-    case CPP_INTCONSTANT:           parserToken->sType.lex.i = ppToken.ival;       return INTCONSTANT;
-    case CPP_UINTCONSTANT:          parserToken->sType.lex.i = ppToken.ival;       return UINTCONSTANT;
-    case CPP_FLOATCONSTANT:         parserToken->sType.lex.d = ppToken.dval;       return FLOATCONSTANT;
-    case CPP_DOUBLECONSTANT:        parserToken->sType.lex.d = ppToken.dval;       return DOUBLECONSTANT;
-    case CPP_IDENTIFIER:            return tokenizeIdentifier();
+        case CPP_INTCONSTANT:           parserToken->sType.lex.i = ppToken.ival;       return INTCONSTANT;
+        case CPP_UINTCONSTANT:          parserToken->sType.lex.i = ppToken.ival;       return UINTCONSTANT;
+        case CPP_FLOATCONSTANT:         parserToken->sType.lex.d = ppToken.dval;       return FLOATCONSTANT;
+        case CPP_DOUBLECONSTANT:        parserToken->sType.lex.d = ppToken.dval;       return DOUBLECONSTANT;
+        case CPP_IDENTIFIER:            return tokenizeIdentifier();
 
-    case EOF:                       return 0;
+        case EOF:                       return 0;
                                    
-    default:
-        parseContext.infoSink.info.message(EPrefixInternalError, "Unknown PP token", loc);
-        return 0;
-    }
+        default:
+            char buf[2];
+            buf[0] = ppToken.token;
+            buf[1] = 0;
+            parseContext.error(loc, "unexpected token", buf, "");
+            break;
+        }
+    } while (true);
 }
 
 int TScanContext::tokenizeIdentifier()
index 7fa5b92..7cb5a38 100644 (file)
@@ -190,12 +190,6 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
     TSourceLoc defineLoc = ppToken->loc; // because ppToken is going to go to the next line before we report errors
     mac.body = new TokenStream;
     while (token != '\n') {
-        if (token == '\\') {
-            parseContext.lineContinuationCheck(ppToken->loc, false);
-            token = currentInput->scan(this, currentInput, ppToken);
-            if (token == '\n' || token == '\r')
-                token = currentInput->scan(this, currentInput, ppToken);
-        }
         RecordToken(mac.body, token, ppToken);
         token = currentInput->scan(this, currentInput, ppToken);
         if (token != '\n' && ppToken->space)
index 1add7a2..82eaf26 100644 (file)
@@ -281,20 +281,29 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
         case 'k': case 'l': case 'm': case 'n': case 'o':
         case 'p': case 'q': case 'r': case 's': case 't':
         case 'u': case 'v': case 'w': case 'x': case 'y':
-        case 'z': case '\\' :
+        case 'z': case '\\':
             do {
                 if (ch == '\\') {
                     // escaped character
-                    pp->parseContext.lineContinuationCheck(ppToken->loc, false);
                     ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
                     if (ch == '\r' || ch == '\n') {
+                        pp->parseContext.lineContinuationCheck(ppToken->loc, false);
                         int nextch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
                         if (ch == '\r' && nextch == '\n')
                             ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
                         else
                             ch = nextch;
-                    } else
-                        pp->parseContext.error(ppToken->loc, "can only escape newlines", "\\", "");
+                    } else {
+                        // Not an escaped newline.
+                        // Put back whatever it was
+                        pp->currentInput->ungetch(pp, pp->currentInput, ch, ppToken);
+                        // If not in the middle of an identifier, the \ is our token
+                        if (len == 0)
+                            return '\\';
+                        // Otherwise, put back the \ character, leave it for the next call
+                        ch = '\\';  // for the upcoming unget(...ch...);
+                        break;
+                    }
                 } else if (len < TPpToken::maxTokenLength) {
                     tokenText[len++] = ch;
                     ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);                                       
@@ -303,7 +312,7 @@ int TPpContext::sourceScan(TPpContext* pp, InputSrc*, TPpToken* ppToken)
                         pp->parseContext.error(ppToken->loc, "name too long", "", "");
                         AlreadyComplained = 1;
                     }
-                    ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);                                       
+                    ch = pp->currentInput->getch(pp, pp->currentInput, ppToken);
                 }
             } while ((ch >= 'a' && ch <= 'z') ||
                 (ch >= 'A' && ch <= 'Z') ||