From b51f62c5730212b270f8931e7920260b0811bbd7 Mon Sep 17 00:00:00 2001
From: John Kessenich <cepheus@frii.com>
Date: Thu, 11 Apr 2013 16:31:09 +0000
Subject: [PATCH] Add the GL_ES macro for ES personalities, along with a
 general mechanism for adding preambles in front of shaders without effecting
 line numbers, etc.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@21122 e7fa87d3-cd2b-0410-9028-fcbf551c1848
---
 StandAlone/StandAlone.cpp                     |  2 +-
 Test/140.frag                                 |  5 +++
 Test/300.vert                                 |  8 +++-
 glslang/MachineIndependent/ParseHelper.cpp    | 10 +++++
 glslang/MachineIndependent/ParseHelper.h      |  3 +-
 glslang/MachineIndependent/ShaderLang.cpp     |  4 +-
 glslang/MachineIndependent/glslang.l          | 38 ++++++++++++-------
 .../MachineIndependent/preprocessor/scanner.c | 13 ++++---
 8 files changed, 60 insertions(+), 23 deletions(-)

diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp
index 18e9c5478..e7d080083 100644
--- a/StandAlone/StandAlone.cpp
+++ b/StandAlone/StandAlone.cpp
@@ -89,7 +89,7 @@ int OutputMultipleStrings = 1;
 // Set up the per compile resources
 //
 void GenerateResources(TBuiltInResource& resources)
-{    
+{
     resources.maxLights = 32;
     resources.maxClipPlanes = 6;
     resources.maxTextureUnits = 32;
diff --git a/Test/140.frag b/Test/140.frag
index 045983d19..140c0c6db 100644
--- a/Test/140.frag
+++ b/Test/140.frag
@@ -8,3 +8,8 @@ out vec4 o;
 void main()
 {
 }
+#ifdef GL_ES
+#error GL_ES is set
+#else
+#error GL_ES is not set
+#endif
diff --git a/Test/300.vert b/Test/300.vert
index 5db2be19f..7e7a5257e 100644
--- a/Test/300.vert
+++ b/Test/300.vert
@@ -7,7 +7,7 @@ uniform mat4x4 m44;
 in vec3 v3;
 in vec2 v2;
 
-in vec4 bad[10];
+in vec4 bad[10];  // ERROR
 
 void main()
 {
@@ -30,4 +30,10 @@ void main()
     mat3x3 im = inverse(m33);
 
     mat3x2 op = outerProduct(v2, v3);
+
+#ifdef GL_ES
+#error GL_ES is set
+#else
+#error GL_ES is not set
+#endif
 }
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 8c24c26ed..b247cbf81 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -77,6 +77,16 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, E
     defaultGlobalQualification.layoutSlotLocation = 0;
 }
 
+// Get code that is not part of a shared symbol table, specific to this shader
+// or needed by CPP (which does not have a shared symbol table).
+const char* TParseContext::getPreamble()
+{
+    if (profile == EEsProfile)
+        return "#define GL_ES 1\n";
+    else
+        return 0;
+}
+
 ///////////////////////////////////////////////////////////////////////
 //
 // Sub- vector and matrix fields
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index 69504130d..66c75ec76 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -96,6 +96,7 @@ struct TParseContext {
     bool AfterEOF;
 
     void initializeExtensionBehavior();
+    const char* getPreamble();
 
     void C_DECL error(TSourceLoc, const char *szReason, const char *szToken,
                       const char *szExtraInfoFormat, ...);
@@ -159,7 +160,7 @@ struct TParseContext {
     void doubleCheck(int line, const char* op);
 };
 
-int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext&);
+int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext&, const char* preamble);
 int PaParseComment(int &lineno, TParseContext&);
 void ResetFlex();
 
diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp
index 6b77f37c2..ea4a31de5 100644
--- a/glslang/MachineIndependent/ShaderLang.cpp
+++ b/glslang/MachineIndependent/ShaderLang.cpp
@@ -132,7 +132,7 @@ bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, int version, EProfil
         builtInShaders[0] = (*i).c_str();
         builtInLengths[0] = (int) (*i).size();
 
-        if (PaParseStrings(const_cast<char**>(builtInShaders), builtInLengths, 1, parseContext) != 0) {
+        if (PaParseStrings(const_cast<char**>(builtInShaders), builtInLengths, 1, parseContext, 0) != 0) {
             infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
 
             return false;
@@ -548,7 +548,7 @@ int ShCompile(
     if (parseContext.insertBuiltInArrayAtGlobalLevel())
         success = false;
 
-    int ret = PaParseStrings(const_cast<char**>(shaderStrings), 0, numStrings, parseContext);
+    int ret = PaParseStrings(const_cast<char**>(shaderStrings), 0, numStrings, parseContext, parseContext.getPreamble());
     if (ret)
         success = false;
 
diff --git a/glslang/MachineIndependent/glslang.l b/glslang/MachineIndependent/glslang.l
index 0e22616b1..e4e01a244 100644
--- a/glslang/MachineIndependent/glslang.l
+++ b/glslang/MachineIndependent/glslang.l
@@ -470,15 +470,8 @@ int yy_input(char* buf, int max_size)
 //
 // Returns 0 for success, as per yyparse().
 //
-int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseContextLocal)
+int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseContextLocal, const char* preamble)
 {
-    int argv0len;
-
-    ScanFromString(argv[0]);
-
-    //Storing the Current Compiler Parse context into the cpp structure.
-	cpp->pC = (void*)&parseContextLocal;
-	
 	if (!argv || argc == 0)
         return 1;
 
@@ -490,13 +483,27 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon
         }
     }
 
+    // set up all the cpp fields...
+	cpp->pC = (void*)&parseContextLocal;
+    char *writeablePreamble = 0;
+    if (preamble) {
+        // preAmble could be a hard-coded string; make writable copy
+        // TODO: CPP: make it not need writable strings
+        int size = strlen(preamble) + 1;
+        writeablePreamble = new char[size];
+        memcpy(writeablePreamble, preamble, size);
+        ScanFromString(writeablePreamble);
+        cpp->PaWhichStr = -1;
+    } else {
+        ScanFromString(argv[0]);
+        cpp->PaWhichStr = 0;
+    }
     if (! strLen) {
-        argv0len = (int) strlen(argv[0]);
+        int argv0len = (int) strlen(argv[0]);
         strLen   = &argv0len;
     }
     yyrestart(0);
     (&parseContextLocal)->AfterEOF = false;
-    cpp->PaWhichStr = 0;
     cpp->PaArgv     = argv;
     cpp->PaArgc     = argc;
     cpp->PaStrLen   = strLen;
@@ -508,9 +515,10 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon
     while (argv[0][len] == ' '  ||
            argv[0][len] == '\t' ||
            argv[0][len] == '\n' ||
-           argv[0][len] == '\r')
+           argv[0][len] == '\r') {
         if (++len >= strLen[0])
             return 0;
+    }
 
     if (*cpp->PaStrLen > 0) {
         int ret;
@@ -519,12 +527,16 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon
         #else
             ret = yyparse((void*)(&parseContextLocal));
         #endif
+        delete writeablePreamble;
         if (cpp->CompileError == 1 || parseContextLocal.recoveredFromError || parseContextLocal.numErrors > 0)
              return 1;
         else
              return 0;
-    } else
-        return 0;
+    } 
+
+    delete writeablePreamble;
+
+    return 0;
 }
 
 void yyerror(const char *s)
diff --git a/glslang/MachineIndependent/preprocessor/scanner.c b/glslang/MachineIndependent/preprocessor/scanner.c
index 964b07847..dc9925635 100644
--- a/glslang/MachineIndependent/preprocessor/scanner.c
+++ b/glslang/MachineIndependent/preprocessor/scanner.c
@@ -168,23 +168,26 @@ int FreeScanner(void)
  */
 static int str_getch(StringInputSrc *in)
 {
-	for(;;){
-	   if (*in->p){
+	for(;;) {
+	   if (*in->p) {
 	      if (*in->p == '\n') {
              in->base.line++;
              IncLineNumber();
           }
           return *in->p++;
 	   }
-	   if(++(cpp->PaWhichStr) < cpp->PaArgc){
+       if (cpp->PaWhichStr < 0) {
+           // we only parsed the built-in pre-amble; start with clean slate for user code
+            cpp->notAVersionToken = 0;
+       }
+	   if (++(cpp->PaWhichStr) < cpp->PaArgc) {
 		  free(in);
 		  SetStringNumber(cpp->PaWhichStr);
     	  SetLineNumber(1);
 		  ScanFromString(cpp->PaArgv[cpp->PaWhichStr]);
 		  in=(StringInputSrc*)cpp->currentInput;
 	      continue;             
-	   }
-	   else{
+	   } else {
 	      cpp->currentInput = in->base.prev;
 	      cpp->PaWhichStr=0;
           free(in);
-- 
GitLab