Add scanner that can find '#version' across an array of non-null terminated, length-based, strings. Handle the ES error where #version is not the first thing found, while still supporting desktop behavior, and more generally support length-based multiple strings for a single shader.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22165 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
		
							parent
							
								
									ebf0825ec4
								
							
						
					
					
						commit
						41cf6b540b
					
				@ -79,8 +79,9 @@ void usage();
 | 
				
			|||||||
void FreeFileData(char **data);
 | 
					void FreeFileData(char **data);
 | 
				
			||||||
char** ReadFileData(const char *fileName);
 | 
					char** ReadFileData(const char *fileName);
 | 
				
			||||||
void InfoLogMsg(const char* msg, const char* name, const int num);
 | 
					void InfoLogMsg(const char* msg, const char* name, const int num);
 | 
				
			||||||
//Added to accomodate the multiple strings.
 | 
					
 | 
				
			||||||
int OutputMultipleStrings = 1;
 | 
					// Use to test breaking a single shader file into multiple strings.
 | 
				
			||||||
 | 
					int NumShaderStrings = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Set up the per compile resources
 | 
					// Set up the per compile resources
 | 
				
			||||||
@ -255,21 +256,31 @@ static EShLanguage FindLanguage(char *name)
 | 
				
			|||||||
bool CompileFile(const char *fileName, ShHandle compiler, int debugOptions, const TBuiltInResource *resources)
 | 
					bool CompileFile(const char *fileName, ShHandle compiler, int debugOptions, const TBuiltInResource *resources)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ret;
 | 
					    int ret;
 | 
				
			||||||
    char **data = ReadFileData(fileName);
 | 
					    char** shaderStrings = ReadFileData(fileName);
 | 
				
			||||||
 | 
					    int* lengths = new int[NumShaderStrings];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // move to length-based strings, rather than null-terminated strings
 | 
				
			||||||
 | 
					    for (int s = 0; s < NumShaderStrings; ++s)
 | 
				
			||||||
 | 
					        lengths[s] = strlen(shaderStrings[s]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
    PROCESS_MEMORY_COUNTERS counters;  // just for memory leak testing
 | 
					    PROCESS_MEMORY_COUNTERS counters;  // just for memory leak testing
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!data)
 | 
					    if (! shaderStrings)
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EShMessages messages = EShMsgDefault;
 | 
					    EShMessages messages = EShMsgDefault;
 | 
				
			||||||
    if (debugOptions & EDebugOpRelaxedErrors)
 | 
					    if (debugOptions & EDebugOpRelaxedErrors)
 | 
				
			||||||
        messages = (EShMessages)(messages | EShMsgRelaxedErrors);
 | 
					        messages = (EShMessages)(messages | EShMsgRelaxedErrors);
 | 
				
			||||||
    for (int i = 0; i < ((debugOptions & EDebugOpMemoryLeakMode) ? 100 : 1); ++i) {
 | 
					    for (int i = 0; i < ((debugOptions & EDebugOpMemoryLeakMode) ? 100 : 1); ++i) {
 | 
				
			||||||
        for (int j = 0; j < ((debugOptions & EDebugOpMemoryLeakMode) ? 100 : 1); ++j)
 | 
					        for (int j = 0; j < ((debugOptions & EDebugOpMemoryLeakMode) ? 100 : 1); ++j) {
 | 
				
			||||||
            ret = ShCompile(compiler, data, OutputMultipleStrings, EShOptNone, resources, debugOptions, 100, false, messages);
 | 
					            //ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, resources, debugOptions, 100, false, messages);
 | 
				
			||||||
 | 
					            ret = ShCompile(compiler, shaderStrings, NumShaderStrings, 0, EShOptNone, resources, debugOptions, 100, false, messages);
 | 
				
			||||||
 | 
					            //const char* multi[4] = { "# ve", "rsion", " 300 e", "s" };
 | 
				
			||||||
 | 
					            //const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" };
 | 
				
			||||||
 | 
					            //ret = ShCompile(compiler, multi, 4, 0, EShOptNone, resources, debugOptions, 100, false, messages);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
        if (debugOptions & EDebugOpMemoryLeakMode) {
 | 
					        if (debugOptions & EDebugOpMemoryLeakMode) {
 | 
				
			||||||
@ -279,7 +290,8 @@ bool CompileFile(const char *fileName, ShHandle compiler, int debugOptions, cons
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    FreeFileData(data);
 | 
					    delete [] lengths;
 | 
				
			||||||
 | 
					    FreeFileData(shaderStrings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return ret ? true : false;
 | 
					    return ret ? true : false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -366,11 +378,11 @@ char** ReadFileData(const char *fileName)
 | 
				
			|||||||
    if(count==0){
 | 
					    if(count==0){
 | 
				
			||||||
        return_data[0]=(char*)malloc(count+2);
 | 
					        return_data[0]=(char*)malloc(count+2);
 | 
				
			||||||
        return_data[0][0]='\0';
 | 
					        return_data[0][0]='\0';
 | 
				
			||||||
        OutputMultipleStrings=0;
 | 
					        NumShaderStrings=0;
 | 
				
			||||||
        return return_data;       
 | 
					        return return_data;       
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int len = (int)(ceil)((float)count/(float)OutputMultipleStrings);
 | 
						int len = (int)(ceil)((float)count/(float)NumShaderStrings);
 | 
				
			||||||
    int ptr_len=0,i=0;
 | 
					    int ptr_len=0,i=0;
 | 
				
			||||||
	while(count>0){
 | 
						while(count>0){
 | 
				
			||||||
		return_data[i]=(char*)malloc(len+2);
 | 
							return_data[i]=(char*)malloc(len+2);
 | 
				
			||||||
@ -380,7 +392,7 @@ char** ReadFileData(const char *fileName)
 | 
				
			|||||||
		ptr_len+=(len);
 | 
							ptr_len+=(len);
 | 
				
			||||||
		if(count<len){
 | 
							if(count<len){
 | 
				
			||||||
            if(count==0){
 | 
					            if(count==0){
 | 
				
			||||||
               OutputMultipleStrings=(i+1);
 | 
					               NumShaderStrings=(i+1);
 | 
				
			||||||
               break;
 | 
					               break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
           len = count;
 | 
					           len = count;
 | 
				
			||||||
@ -394,7 +406,7 @@ char** ReadFileData(const char *fileName)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void FreeFileData(char **data)
 | 
					void FreeFileData(char **data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    for(int i=0;i<OutputMultipleStrings;i++)
 | 
					    for(int i=0;i<NumShaderStrings;i++)
 | 
				
			||||||
        free(data[i]);
 | 
					        free(data[i]);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -154,6 +154,7 @@ xcopy /y $(IntDir)$(TargetName)$(TargetExt) Test</Command>
 | 
				
			|||||||
    <ClCompile Include="glslang\MachineIndependent\glslang_tab.cpp" />
 | 
					    <ClCompile Include="glslang\MachineIndependent\glslang_tab.cpp" />
 | 
				
			||||||
    <ClCompile Include="glslang\MachineIndependent\InfoSink.cpp" />
 | 
					    <ClCompile Include="glslang\MachineIndependent\InfoSink.cpp" />
 | 
				
			||||||
    <ClCompile Include="glslang\MachineIndependent\Initialize.cpp" />
 | 
					    <ClCompile Include="glslang\MachineIndependent\Initialize.cpp" />
 | 
				
			||||||
 | 
					    <ClCompile Include="glslang\MachineIndependent\Scan.cpp" />
 | 
				
			||||||
    <ClCompile Include="glslang\MachineIndependent\Versions.cpp" />
 | 
					    <ClCompile Include="glslang\MachineIndependent\Versions.cpp" />
 | 
				
			||||||
    <ClCompile Include="OGLCompilersDLL\InitializeDll.cpp" />
 | 
					    <ClCompile Include="OGLCompilersDLL\InitializeDll.cpp" />
 | 
				
			||||||
    <ClCompile Include="glslang\MachineIndependent\IntermTraverse.cpp" />
 | 
					    <ClCompile Include="glslang\MachineIndependent\IntermTraverse.cpp" />
 | 
				
			||||||
@ -204,6 +205,7 @@ xcopy /y $(IntDir)$(TargetName)$(TargetExt) Test</Command>
 | 
				
			|||||||
    <ClInclude Include="glslang\Include\Common.h" />
 | 
					    <ClInclude Include="glslang\Include\Common.h" />
 | 
				
			||||||
    <ClInclude Include="glslang\Include\ConstantUnion.h" />
 | 
					    <ClInclude Include="glslang\Include\ConstantUnion.h" />
 | 
				
			||||||
    <ClInclude Include="glslang\Include\InfoSink.h" />
 | 
					    <ClInclude Include="glslang\Include\InfoSink.h" />
 | 
				
			||||||
 | 
					    <ClInclude Include="glslang\MachineIndependent\Scan.h" />
 | 
				
			||||||
    <ClInclude Include="glslang\MachineIndependent\Versions.h" />
 | 
					    <ClInclude Include="glslang\MachineIndependent\Versions.h" />
 | 
				
			||||||
    <ClInclude Include="OGLCompilersDLL\InitializeDll.h" />
 | 
					    <ClInclude Include="OGLCompilersDLL\InitializeDll.h" />
 | 
				
			||||||
    <ClInclude Include="glslang\Include\InitializeGlobals.h" />
 | 
					    <ClInclude Include="glslang\Include\InitializeGlobals.h" />
 | 
				
			||||||
 | 
				
			|||||||
@ -109,6 +109,9 @@
 | 
				
			|||||||
    <ClCompile Include="glslang\MachineIndependent\Constant.cpp">
 | 
					    <ClCompile Include="glslang\MachineIndependent\Constant.cpp">
 | 
				
			||||||
      <Filter>Machine Independent</Filter>
 | 
					      <Filter>Machine Independent</Filter>
 | 
				
			||||||
    </ClCompile>
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					    <ClCompile Include="glslang\MachineIndependent\Scan.cpp">
 | 
				
			||||||
 | 
					      <Filter>Machine Independent</Filter>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <ClInclude Include="glslang\MachineIndependent\Initialize.h">
 | 
					    <ClInclude Include="glslang\MachineIndependent\Initialize.h">
 | 
				
			||||||
@ -216,6 +219,9 @@
 | 
				
			|||||||
    <ClInclude Include="glslang\MachineIndependent\Versions.h">
 | 
					    <ClInclude Include="glslang\MachineIndependent\Versions.h">
 | 
				
			||||||
      <Filter>Machine Independent</Filter>
 | 
					      <Filter>Machine Independent</Filter>
 | 
				
			||||||
    </ClInclude>
 | 
					    </ClInclude>
 | 
				
			||||||
 | 
					    <ClInclude Include="glslang\MachineIndependent\Scan.h">
 | 
				
			||||||
 | 
					      <Filter>Machine Independent</Filter>
 | 
				
			||||||
 | 
					    </ClInclude>
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <CustomBuild Include="glslang\MachineIndependent\glslang.y">
 | 
					    <CustomBuild Include="glslang\MachineIndependent\glslang.y">
 | 
				
			||||||
 | 
				
			|||||||
@ -11,12 +11,12 @@ LIBCODEGEN=./../GenericCodeGen/libCodeGen.a
 | 
				
			|||||||
OBJECTS= Initialize.o IntermTraverse.o \
 | 
					OBJECTS= Initialize.o IntermTraverse.o \
 | 
				
			||||||
	Intermediate.o ParseHelper.o PoolAlloc.o QualifierAlive.o \
 | 
						Intermediate.o ParseHelper.o PoolAlloc.o QualifierAlive.o \
 | 
				
			||||||
	RemoveTree.o ShaderLang.o intermOut.o parseConst.o SymbolTable.o \
 | 
						RemoveTree.o ShaderLang.o intermOut.o parseConst.o SymbolTable.o \
 | 
				
			||||||
	InfoSink.o Versions.o Constant.o
 | 
						InfoSink.o Versions.o Constant.o Scan.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SRCS= gen_glslang.cpp gen_glslang_tab.cpp Initialize.cpp IntermTraverse.cpp \
 | 
					SRCS= gen_glslang.cpp gen_glslang_tab.cpp Initialize.cpp IntermTraverse.cpp \
 | 
				
			||||||
	Intermediate.cpp ParseHelper.cpp PoolAlloc.cp QualifierAlive.cpp \
 | 
						Intermediate.cpp ParseHelper.cpp PoolAlloc.cp QualifierAlive.cpp \
 | 
				
			||||||
	RemoveTree.cpp ShaderLang.cpp SymbolTable.cpp intermOut.cpp \
 | 
						RemoveTree.cpp ShaderLang.cpp SymbolTable.cpp intermOut.cpp \
 | 
				
			||||||
	parseConst.cpp InfoSink.cpp Versions.cpp Constant.cpp
 | 
						parseConst.cpp InfoSink.cpp Versions.cpp Constant.cpp Scan.cpp
 | 
				
			||||||
CPPFLAGS=$(DEFINE) $(INCLUDE) -fPIC
 | 
					CPPFLAGS=$(DEFINE) $(INCLUDE) -fPIC
 | 
				
			||||||
SHAREDOBJECT=./lib/libglslang.so
 | 
					SHAREDOBJECT=./lib/libglslang.so
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -161,3 +161,4 @@ parseConst.o: ../Public/ShaderLang.h
 | 
				
			|||||||
InfoSink.o: ../Include/InfoSink.h
 | 
					InfoSink.o: ../Include/InfoSink.h
 | 
				
			||||||
Versions.o: ParseHelper.h  Versions.h ../Include/ShHandle.h SymbolTable.h localintermediate.h
 | 
					Versions.o: ParseHelper.h  Versions.h ../Include/ShHandle.h SymbolTable.h localintermediate.h
 | 
				
			||||||
Constant.o: localintermediate.h ../Include/intermediate.h ../Public/ShaderLang.h SymbolTable.h Versions.h
 | 
					Constant.o: localintermediate.h ../Include/intermediate.h ../Public/ShaderLang.h SymbolTable.h Versions.h
 | 
				
			||||||
 | 
					Scan.o: Scan.h Versions.h
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										216
									
								
								glslang/MachineIndependent/Scan.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								glslang/MachineIndependent/Scan.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,216 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					//Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 | 
				
			||||||
 | 
					//Copyright (C) 2013 LunarG, Inc.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					//modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					//are met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					//    notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					//    copyright notice, this list of conditions and the following
 | 
				
			||||||
 | 
					//    disclaimer in the documentation and/or other materials provided
 | 
				
			||||||
 | 
					//    with the distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
 | 
				
			||||||
 | 
					//    contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					//    from this software without specific prior written permission.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
				
			||||||
 | 
					//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
				
			||||||
 | 
					//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
				
			||||||
 | 
					//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
				
			||||||
 | 
					//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | 
				
			||||||
 | 
					//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
				
			||||||
 | 
					//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 | 
				
			||||||
 | 
					//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 | 
				
			||||||
 | 
					//POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "Scan.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace glslang {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					// read past any white space
 | 
				
			||||||
 | 
					void ConsumeWhiteSpace(TInputScanner& input, bool& foundNonSpaceTab)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    char c = input.peek();  // don't accidentally consume anything other than whitespace
 | 
				
			||||||
 | 
					    while (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
 | 
				
			||||||
 | 
					        if (c == '\r' || c == '\n')
 | 
				
			||||||
 | 
					            foundNonSpaceTab = true;
 | 
				
			||||||
 | 
					        input.get();
 | 
				
			||||||
 | 
					        c = input.peek();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// return true if a comment was actually consumed
 | 
				
			||||||
 | 
					bool ConsumeComment(TInputScanner& input)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (input.peek() != '/')
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    input.get();  // consume the '/'
 | 
				
			||||||
 | 
					    char c = input.peek();
 | 
				
			||||||
 | 
					    if (c == '/') {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // a '//' style comment
 | 
				
			||||||
 | 
					        input.get();  // consume the second '/'
 | 
				
			||||||
 | 
					        c = input.get();
 | 
				
			||||||
 | 
					        do {
 | 
				
			||||||
 | 
					            while (c > 0 && c != '\\' && c != '\r' && c != '\n')
 | 
				
			||||||
 | 
					                c = input.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (c <= 0 || c == '\r' || c == '\n') {
 | 
				
			||||||
 | 
					                while (c == '\r' || c == '\n')
 | 
				
			||||||
 | 
					                    c = input.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // we reached the end of the comment
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                // it's a '\', so we need to keep going, after skipping what's escaped
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                // read the skipped character
 | 
				
			||||||
 | 
					                c = input.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // if it's a two-character newline, skip both characters
 | 
				
			||||||
 | 
					                if (c == '\r' && input.peek() == '\n')
 | 
				
			||||||
 | 
					                    input.get();
 | 
				
			||||||
 | 
					                c = input.get();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } while (true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // put back the last non-comment character
 | 
				
			||||||
 | 
					        if (c > 0)
 | 
				
			||||||
 | 
					            input.unget();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    } else if (c == '*') {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // a '/*' style comment
 | 
				
			||||||
 | 
					        input.get();  // consume the '*'
 | 
				
			||||||
 | 
					        c = input.get();
 | 
				
			||||||
 | 
					        do {
 | 
				
			||||||
 | 
					            while (c > 0 && c != '*')
 | 
				
			||||||
 | 
					                c = input.get();
 | 
				
			||||||
 | 
					            if (c == '*') {
 | 
				
			||||||
 | 
					                c = input.get();
 | 
				
			||||||
 | 
					                if (c == '/')
 | 
				
			||||||
 | 
					                    break;  // end of comment
 | 
				
			||||||
 | 
					                // not end of comment
 | 
				
			||||||
 | 
					            } else // end of input
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					        } while (true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        // it's not a comment, put the '/' back
 | 
				
			||||||
 | 
					        input.unget();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// skip whitespace, then skip a comment, rinse, repeat
 | 
				
			||||||
 | 
					void ConsumeWhitespaceComment(TInputScanner& input, bool& foundNonSpaceTab)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    do {
 | 
				
			||||||
 | 
					        ConsumeWhiteSpace(input, foundNonSpaceTab);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					        // if not starting a comment now, then done
 | 
				
			||||||
 | 
					        char c = input.peek();
 | 
				
			||||||
 | 
					        if (c != '/' || c < 0)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // skip potential comment 
 | 
				
			||||||
 | 
					        foundNonSpaceTab = true;
 | 
				
			||||||
 | 
					        if (! ConsumeComment(input))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } while (true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns true if there was non-white space (e.g., a comment, newline) before the #version;
 | 
				
			||||||
 | 
					// otherwise, returns true.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// N.B. does not attempt to leave input in any particular known state
 | 
				
			||||||
 | 
					bool ScanVersion(TInputScanner& input, int& version, EProfile& profile)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // This function doesn't have to get all the semantics correct, 
 | 
				
			||||||
 | 
					    // just find the #version if there is a correct one present.
 | 
				
			||||||
 | 
					    // The preprocessor will have the responsibility of getting all the semantics right.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    version = 0;  // means not found
 | 
				
			||||||
 | 
					    profile = ENoProfile;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool foundNonSpaceTab = false;
 | 
				
			||||||
 | 
					    ConsumeWhitespaceComment(input, foundNonSpaceTab);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // #
 | 
				
			||||||
 | 
					    if (input.get() != '#')
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // whitespace
 | 
				
			||||||
 | 
					    char c;
 | 
				
			||||||
 | 
					    do {
 | 
				
			||||||
 | 
					        c = input.get();
 | 
				
			||||||
 | 
					    } while (c == ' ' || c == '\t');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (          c != 'v' ||
 | 
				
			||||||
 | 
					        input.get() != 'e' ||
 | 
				
			||||||
 | 
					        input.get() != 'r' ||
 | 
				
			||||||
 | 
					        input.get() != 's' ||
 | 
				
			||||||
 | 
					        input.get() != 'i' ||
 | 
				
			||||||
 | 
					        input.get() != 'o' ||
 | 
				
			||||||
 | 
					        input.get() != 'n')
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // whitespace
 | 
				
			||||||
 | 
					    do {
 | 
				
			||||||
 | 
					        c = input.get();
 | 
				
			||||||
 | 
					    } while (c == ' ' || c == '\t');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // version number
 | 
				
			||||||
 | 
					    while (c >= '0' && c <= '9') {
 | 
				
			||||||
 | 
					        version = 10 * version + (c - '0');
 | 
				
			||||||
 | 
					        c = input.get();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (version == 0)
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // whitespace
 | 
				
			||||||
 | 
					    while (c == ' ' || c == '\t')
 | 
				
			||||||
 | 
					        c = input.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // profile
 | 
				
			||||||
 | 
					    const int maxProfileLength = 13;  // not including any 0
 | 
				
			||||||
 | 
					    char profileString[maxProfileLength];
 | 
				
			||||||
 | 
					    int profileLength;
 | 
				
			||||||
 | 
					    for (profileLength = 0; profileLength < maxProfileLength; ++profileLength) {
 | 
				
			||||||
 | 
					        if (c < 0 || c == ' ' || c == '\t' || c == '\n' || c == '\r')
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        profileString[profileLength] = c;
 | 
				
			||||||
 | 
					        c = input.get();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (c > 0 && c != ' ' && c != '\t' && c != '\n' && c != '\r')
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (profileLength == 2 && strncmp(profileString, "es", profileLength) == 0)
 | 
				
			||||||
 | 
					        profile = EEsProfile;
 | 
				
			||||||
 | 
					    else if (profileLength == 4 && strncmp(profileString, "core", profileLength) == 0)
 | 
				
			||||||
 | 
					        profile = ECoreProfile;
 | 
				
			||||||
 | 
					    else if (profileLength == 13 && strncmp(profileString, "compatibility", profileLength) == 0)
 | 
				
			||||||
 | 
					        profile = ECompatibilityProfile;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return foundNonSpaceTab;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}; // end glslang namespace
 | 
				
			||||||
							
								
								
									
										115
									
								
								glslang/MachineIndependent/Scan.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								glslang/MachineIndependent/Scan.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,115 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					//Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 | 
				
			||||||
 | 
					//Copyright (C) 2013 LunarG, Inc.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					//modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					//are met:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					//    notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					//    copyright notice, this list of conditions and the following
 | 
				
			||||||
 | 
					//    disclaimer in the documentation and/or other materials provided
 | 
				
			||||||
 | 
					//    with the distribution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
 | 
				
			||||||
 | 
					//    contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					//    from this software without specific prior written permission.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
				
			||||||
 | 
					//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
				
			||||||
 | 
					//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
				
			||||||
 | 
					//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
				
			||||||
 | 
					//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 | 
				
			||||||
 | 
					//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
				
			||||||
 | 
					//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 | 
				
			||||||
 | 
					//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 | 
				
			||||||
 | 
					//POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "Versions.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace glslang {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// A character scanner that seamlessly, on read-only strings, reads across an
 | 
				
			||||||
 | 
					// array of strings without assuming null termination.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					class TInputScanner {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    TInputScanner(int n, const char* const i[], int L[]) : numSources(n), sources(i), lengths(L), currentSource(0), currentChar(0) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // return of -1 means end of strings,
 | 
				
			||||||
 | 
					    // anything else is the next character
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // retrieve the next character and advance one character
 | 
				
			||||||
 | 
					    char get()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (currentSource >= numSources)
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        char ret = sources[currentSource][currentChar];
 | 
				
			||||||
 | 
					        advance();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // advance one character
 | 
				
			||||||
 | 
					    void advance()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ++currentChar;
 | 
				
			||||||
 | 
					        if (currentChar >= lengths[currentSource]) {
 | 
				
			||||||
 | 
					            ++currentSource;
 | 
				
			||||||
 | 
					            currentChar = 0;
 | 
				
			||||||
 | 
					            while (currentSource < numSources && lengths[currentSource] == 0)
 | 
				
			||||||
 | 
					                ++currentSource;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // retrieve the next character, no advance
 | 
				
			||||||
 | 
					    char peek()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (currentSource >= numSources)
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return sources[currentSource][currentChar];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // go back one character
 | 
				
			||||||
 | 
					    void unget()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (currentChar > 0)
 | 
				
			||||||
 | 
					            --currentChar;
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            do {
 | 
				
			||||||
 | 
					                --currentSource;
 | 
				
			||||||
 | 
					            } while (currentSource > 0 && lengths[currentSource] == 0);
 | 
				
			||||||
 | 
					            currentChar = lengths[currentSource] - 1;
 | 
				
			||||||
 | 
					            if (currentChar < 0)
 | 
				
			||||||
 | 
					                currentChar = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					    int numSources;             // number of strings in source
 | 
				
			||||||
 | 
					    const char* const *sources; // array of strings
 | 
				
			||||||
 | 
					    const int *lengths;         // length of each string
 | 
				
			||||||
 | 
					    int currentSource;
 | 
				
			||||||
 | 
					    int currentChar;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The location of these is still pending a grand design for going to a singular
 | 
				
			||||||
 | 
					// scanner for version finding, preprocessing, and tokenizing:
 | 
				
			||||||
 | 
					void ConsumeWhiteSpace(TInputScanner& input, bool& foundNonSpaceTab);
 | 
				
			||||||
 | 
					bool ConsumeComment(TInputScanner& input);
 | 
				
			||||||
 | 
					void ConsumeWhitespaceComment(TInputScanner& input, bool& foundNonSpaceTab);
 | 
				
			||||||
 | 
					bool ScanVersion(TInputScanner& input, int& version, EProfile& profile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}; // end glslang namespace
 | 
				
			||||||
@ -43,6 +43,7 @@
 | 
				
			|||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include "SymbolTable.h"
 | 
					#include "SymbolTable.h"
 | 
				
			||||||
#include "ParseHelper.h"
 | 
					#include "ParseHelper.h"
 | 
				
			||||||
 | 
					#include "Scan.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../Include/ShHandle.h"
 | 
					#include "../Include/ShHandle.h"
 | 
				
			||||||
#include "InitializeDll.h"
 | 
					#include "InitializeDll.h"
 | 
				
			||||||
@ -206,132 +207,6 @@ void SetupBuiltinSymbolTable(int version, EProfile profile)
 | 
				
			|||||||
    SetGlobalPoolAllocatorPtr(savedGPA);
 | 
					    SetGlobalPoolAllocatorPtr(savedGPA);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// returns true if something whas consumed
 | 
					 | 
				
			||||||
bool ConsumeWhitespaceComment(const char*& s)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    const char* startPoint = s;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // first, skip white space    
 | 
					 | 
				
			||||||
    while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') {
 | 
					 | 
				
			||||||
        ++s;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // then, check for a comment
 | 
					 | 
				
			||||||
    if (*s == '/') {
 | 
					 | 
				
			||||||
        if (*(s+1) == '/') {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // a '//' style comment
 | 
					 | 
				
			||||||
            s += 2;
 | 
					 | 
				
			||||||
            do {
 | 
					 | 
				
			||||||
                while (*s && *s != '\\' && *s != '\r' && *s != '\n')
 | 
					 | 
				
			||||||
                    ++s;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (*s == '\r' || *s == '\n' || *s == 0) {
 | 
					 | 
				
			||||||
                    while (*s == '\r' || *s == '\n')
 | 
					 | 
				
			||||||
                        ++s;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    // we reached the end of the comment
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    // it's a '\', so we need to keep going, after skipping what's escaped
 | 
					 | 
				
			||||||
                    ++s;
 | 
					 | 
				
			||||||
                    if (*s == '\r' && *(s+1) == '\n')
 | 
					 | 
				
			||||||
                        s += 2;
 | 
					 | 
				
			||||||
                    else {
 | 
					 | 
				
			||||||
                        // skip the escaped character
 | 
					 | 
				
			||||||
                        if (*s)
 | 
					 | 
				
			||||||
                            ++s;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } while (true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        } else if (*(s+1) == '*') {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // a '/*' style comment
 | 
					 | 
				
			||||||
            s += 2;
 | 
					 | 
				
			||||||
            do {
 | 
					 | 
				
			||||||
                while (*s && *s != '*')
 | 
					 | 
				
			||||||
                    ++s;
 | 
					 | 
				
			||||||
                if (*s == '*') {
 | 
					 | 
				
			||||||
                    ++s;
 | 
					 | 
				
			||||||
                    if (*s == '/') {
 | 
					 | 
				
			||||||
                        ++s;
 | 
					 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                    } // else not end of comment, keep going
 | 
					 | 
				
			||||||
                } else // end of string
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
            } while (true);
 | 
					 | 
				
			||||||
        } // else it's not a comment
 | 
					 | 
				
			||||||
    } // else it's not a comment
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return startPoint != s;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ScanVersion(const char* const shaderStrings[], int numStrings, int& version, EProfile& profile)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // This function doesn't have to get all the semantics correct, 
 | 
					 | 
				
			||||||
    // just find the #version if there is a correct one present.
 | 
					 | 
				
			||||||
    // The CPP will have the responsibility of getting all the semantics right.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    version = 0;  // means not found
 | 
					 | 
				
			||||||
    profile = ENoProfile;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const char* s = &shaderStrings[0][0];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // TODO: semantics:  ES error check: #version must be on first line
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while (ConsumeWhitespaceComment(s))
 | 
					 | 
				
			||||||
        ;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // #
 | 
					 | 
				
			||||||
    if (*s != '#')
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    ++s;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // whitespace
 | 
					 | 
				
			||||||
    while (*s == ' ' || *s == '\t') {
 | 
					 | 
				
			||||||
        ++s;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // version
 | 
					 | 
				
			||||||
    if (strncmp(s, "version", 7) != 0)
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // whitespace
 | 
					 | 
				
			||||||
    s += 7;
 | 
					 | 
				
			||||||
    while (*s == ' ' || *s == '\t') {
 | 
					 | 
				
			||||||
        ++s;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // version number
 | 
					 | 
				
			||||||
    while (*s >= '0' && *s <= '9') {
 | 
					 | 
				
			||||||
        version = 10 * version + (*s - '0');
 | 
					 | 
				
			||||||
        ++s;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (version == 0)
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    // whitespace
 | 
					 | 
				
			||||||
    while (*s == ' ' || *s == '\t') {
 | 
					 | 
				
			||||||
        ++s;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // profile
 | 
					 | 
				
			||||||
    const char* end = s;
 | 
					 | 
				
			||||||
    while (*end != ' ' && *end != '\t' && *end != '\n' && *end != '\r') {
 | 
					 | 
				
			||||||
        if (*end == 0)
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        ++end;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    int profileLength = end - s;
 | 
					 | 
				
			||||||
    if (profileLength == 2 && strncmp(s, "es", profileLength) == 0)
 | 
					 | 
				
			||||||
        profile = EEsProfile;
 | 
					 | 
				
			||||||
    else if (profileLength == 4 && strncmp(s, "core", profileLength) == 0)
 | 
					 | 
				
			||||||
        profile = ECoreProfile;
 | 
					 | 
				
			||||||
    else if (profileLength == 13 && strncmp(s, "compatibility", profileLength) == 0)
 | 
					 | 
				
			||||||
        profile = ECompatibilityProfile;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool DeduceProfile(TInfoSink& infoSink, int version, EProfile& profile)
 | 
					bool DeduceProfile(TInfoSink& infoSink, int version, EProfile& profile)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const int FirstProfileVersion = 150;
 | 
					    const int FirstProfileVersion = 150;
 | 
				
			||||||
@ -382,7 +257,6 @@ bool DeduceProfile(TInfoSink& infoSink, int version, EProfile& profile)
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
}; // end anonymous namespace for local functions
 | 
					}; // end anonymous namespace for local functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ShInitialize()
 | 
					int ShInitialize()
 | 
				
			||||||
@ -479,6 +353,7 @@ int ShCompile(
 | 
				
			|||||||
    const ShHandle handle,
 | 
					    const ShHandle handle,
 | 
				
			||||||
    const char* const shaderStrings[],
 | 
					    const char* const shaderStrings[],
 | 
				
			||||||
    const int numStrings,
 | 
					    const int numStrings,
 | 
				
			||||||
 | 
					    const int* inputLengths,
 | 
				
			||||||
    const EShOptimizationLevel optLevel,
 | 
					    const EShOptimizationLevel optLevel,
 | 
				
			||||||
    const TBuiltInResource* resources,
 | 
					    const TBuiltInResource* resources,
 | 
				
			||||||
    int debugOptions,
 | 
					    int debugOptions,
 | 
				
			||||||
@ -497,17 +372,28 @@ int ShCompile(
 | 
				
			|||||||
    if (compiler == 0)
 | 
					    if (compiler == 0)
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GlobalPoolAllocator.push();
 | 
					 | 
				
			||||||
    compiler->infoSink.info.erase();
 | 
					    compiler->infoSink.info.erase();
 | 
				
			||||||
    compiler->infoSink.debug.erase();
 | 
					    compiler->infoSink.debug.erase();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (numStrings == 0)
 | 
					    if (numStrings == 0)
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GlobalPoolAllocator.push();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // move to length-based strings, rather than null-terminated strings
 | 
				
			||||||
 | 
					    int* lengths = new int[numStrings];
 | 
				
			||||||
 | 
					    for (int s = 0; s < numStrings; ++s) {
 | 
				
			||||||
 | 
					        if (inputLengths == 0 || inputLengths[s] < 0)
 | 
				
			||||||
 | 
					            lengths[s] = strlen(shaderStrings[s]);
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            lengths[s] = inputLengths[s];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int version;
 | 
					    int version;
 | 
				
			||||||
    EProfile profile;
 | 
					    EProfile profile;
 | 
				
			||||||
    bool versionStatementMissing = false;
 | 
					    bool versionStatementMissing = false;
 | 
				
			||||||
    ScanVersion(shaderStrings, numStrings, version, profile);
 | 
					    glslang::TInputScanner input(numStrings, shaderStrings, lengths);
 | 
				
			||||||
 | 
					    bool versionNotFirst = ScanVersion(input, version, profile);
 | 
				
			||||||
    if (version == 0) {
 | 
					    if (version == 0) {
 | 
				
			||||||
        version = defaultVersion;
 | 
					        version = defaultVersion;
 | 
				
			||||||
        versionStatementMissing = true;
 | 
					        versionStatementMissing = true;
 | 
				
			||||||
@ -533,6 +419,8 @@ int ShCompile(
 | 
				
			|||||||
    parseContext.initializeExtensionBehavior();
 | 
					    parseContext.initializeExtensionBehavior();
 | 
				
			||||||
    if (versionStatementMissing)
 | 
					    if (versionStatementMissing)
 | 
				
			||||||
        parseContext.warn(1, "statement missing: use #version on first line of shader", "#version", "");
 | 
					        parseContext.warn(1, "statement missing: use #version on first line of shader", "#version", "");
 | 
				
			||||||
 | 
					    else if (profile == EEsProfile && version >= 300 && versionNotFirst)
 | 
				
			||||||
 | 
					        parseContext.error(1, "statement must appear first in ESSL shader; before comments or newlines", "#version", "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GlobalParseContext = &parseContext;
 | 
					    GlobalParseContext = &parseContext;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -553,7 +441,7 @@ int ShCompile(
 | 
				
			|||||||
    if (parseContext.insertBuiltInArrayAtGlobalLevel())
 | 
					    if (parseContext.insertBuiltInArrayAtGlobalLevel())
 | 
				
			||||||
        success = false;
 | 
					        success = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int ret = PaParseStrings(const_cast<char**>(shaderStrings), 0, numStrings, parseContext, parseContext.getPreamble());
 | 
					    int ret = PaParseStrings(const_cast<char**>(shaderStrings), lengths, numStrings, parseContext, parseContext.getPreamble());
 | 
				
			||||||
    if (ret)
 | 
					    if (ret)
 | 
				
			||||||
        success = false;
 | 
					        success = false;
 | 
				
			||||||
    intermediate.addSymbolLinkageNodes(parseContext.treeRoot, parseContext.linkage, parseContext.language, symbolTable);
 | 
					    intermediate.addSymbolLinkageNodes(parseContext.treeRoot, parseContext.linkage, parseContext.language, symbolTable);
 | 
				
			||||||
@ -597,6 +485,7 @@ int ShCompile(
 | 
				
			|||||||
    // Throw away all the temporary memory used by the compilation process.
 | 
					    // Throw away all the temporary memory used by the compilation process.
 | 
				
			||||||
    //
 | 
					    //
 | 
				
			||||||
    GlobalPoolAllocator.pop();
 | 
					    GlobalPoolAllocator.pop();
 | 
				
			||||||
 | 
					    delete [] lengths;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return success ? 1 : 0;
 | 
					    return success ? 1 : 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -164,6 +164,7 @@ SH_IMPORT_EXPORT int ShCompile(
 | 
				
			|||||||
    const ShHandle,
 | 
					    const ShHandle,
 | 
				
			||||||
    const char* const shaderStrings[],
 | 
					    const char* const shaderStrings[],
 | 
				
			||||||
    const int numStrings,
 | 
					    const int numStrings,
 | 
				
			||||||
 | 
					    const int* lengths,
 | 
				
			||||||
    const EShOptimizationLevel,
 | 
					    const EShOptimizationLevel,
 | 
				
			||||||
    const TBuiltInResource *resources,
 | 
					    const TBuiltInResource *resources,
 | 
				
			||||||
    int debugOptions,
 | 
					    int debugOptions,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user