Initial import from TransGaming

git-svn-id: https://angleproject.googlecode.com/svn/trunk@2 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/Compiler/BaseTypes.h b/Compiler/BaseTypes.h
new file mode 100644
index 0000000..2265b96
--- /dev/null
+++ b/Compiler/BaseTypes.h
@@ -0,0 +1,130 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _BASICTYPES_INCLUDED_
+#define _BASICTYPES_INCLUDED_
+
+//
+// Precision qualifiers
+//
+enum TPrecision
+{
+	EbpHigh,
+	EbpMedium,
+	EbpLow,
+};
+
+__inline const char* getPrecisionString(TPrecision p)
+{
+	switch(p)
+	{
+	case EbpHigh:		return "highp";		break;
+	case EbpMedium:		return "mediump";	break;
+	case EbpLow:		return "lowp";		break;
+	default:			return "unknown precision";
+	}
+}
+
+//
+// Basic type.  Arrays, vectors, etc., are orthogonal to this.
+//
+enum TBasicType
+{
+	EbtVoid,
+	EbtFloat,
+	EbtInt,
+	EbtBool,
+	EbtGuardSamplerBegin,  // non type:  see implementation of IsSampler()
+	EbtSampler2D,
+	EbtSamplerCube,
+	EbtGuardSamplerEnd,    // non type:  see implementation of IsSampler()
+	EbtStruct,
+	EbtAddress,            // should be deprecated??
+};
+
+__inline bool IsSampler(TBasicType type)
+{
+	return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd;
+}
+
+//
+// Qualifiers and built-ins.  These are mainly used to see what can be read
+// or written, and by the machine dependent translator to know which registers
+// to allocate variables in.  Since built-ins tend to go to different registers
+// than varying or uniform, it makes sense they are peers, not sub-classes.
+//
+enum TQualifier
+{
+	EvqTemporary,     // For temporaries (within a function), read/write
+	EvqGlobal,        // For globals read/write
+	EvqConst,         // User defined constants and non-output parameters in functions
+	EvqAttribute,     // Readonly
+	EvqVaryingIn,     // readonly, fragment shaders only
+	EvqVaryingOut,    // vertex shaders only  read/write
+	EvqInvariantVaryingIn,     // readonly, fragment shaders only
+	EvqInvariantVaryingOut,    // vertex shaders only  read/write
+	EvqUniform,       // Readonly, vertex and fragment
+
+	// pack/unpack input and output
+	EvqInput,
+	EvqOutput,
+
+	// parameters
+	EvqIn,
+	EvqOut,
+	EvqInOut,
+	EvqConstReadOnly,
+
+	// built-ins written by vertex shader
+	EvqPosition,
+	EvqPointSize,
+
+	// built-ins read by fragment shader
+	EvqFragCoord,
+	EvqFrontFacing,
+	EvqPointCoord,
+
+	// built-ins written by fragment shader
+	EvqFragColor,
+	EvqFragData,
+
+	// end of list
+	EvqLast,
+};
+
+//
+// This is just for debug print out, carried along with the definitions above.
+//
+__inline const char* getQualifierString(TQualifier q)
+{
+	switch(q)
+	{
+	case EvqTemporary:      return "Temporary";      break;
+	case EvqGlobal:         return "Global";         break;
+	case EvqConst:          return "const";          break;
+	case EvqConstReadOnly:  return "const";          break;
+	case EvqAttribute:      return "attribute";      break;
+	case EvqVaryingIn:      return "varying";        break;
+	case EvqVaryingOut:     return "varying";        break;
+	case EvqInvariantVaryingIn: return "invariant varying";	break;
+	case EvqInvariantVaryingOut:return "invariant varying";	break;
+	case EvqUniform:        return "uniform";        break;
+	case EvqIn:             return "in";             break;
+	case EvqOut:            return "out";            break;
+	case EvqInOut:          return "inout";          break;
+	case EvqInput:          return "input";          break;
+	case EvqOutput:         return "output";         break;
+	case EvqPosition:       return "Position";       break;
+	case EvqPointSize:      return "PointSize";      break;
+	case EvqFragCoord:      return "FragCoord";      break;
+	case EvqFrontFacing:    return "FrontFacing";    break;
+	case EvqFragColor:      return "FragColor";      break;
+	case EvqFragData:       return "FragData";      break;
+	default:                return "unknown qualifier";
+	}
+}
+
+#endif // _BASICTYPES_INCLUDED_
diff --git a/Compiler/CodeGen.cpp b/Compiler/CodeGen.cpp
new file mode 100644
index 0000000..fa54c7e
--- /dev/null
+++ b/Compiler/CodeGen.cpp
@@ -0,0 +1,47 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "Common.h"
+#include "ShHandle.h"
+
+//
+// Here is where real machine specific high-level data would be defined.
+//
+class TGenericCompiler : public TCompiler {
+public:
+    TGenericCompiler(EShLanguage l, int dOptions) : TCompiler(l, infoSink), debugOptions(dOptions) { }
+    virtual bool compile(TIntermNode* root);
+    TInfoSink infoSink;
+    int debugOptions;
+};
+
+//
+// This function must be provided to create the actual
+// compile object used by higher level code.  It returns
+// a subclass of TCompiler.
+//
+TCompiler* ConstructCompiler(EShLanguage language, int debugOptions)
+{
+    return new TGenericCompiler(language, debugOptions);
+}
+
+//
+// Delete the compiler made by ConstructCompiler
+//
+void DeleteCompiler(TCompiler* compiler)
+{
+    delete compiler;
+}
+
+//
+//  Generate code from the given parse tree
+//
+bool TGenericCompiler::compile(TIntermNode *root)
+{
+    haveValidObjectCode = true;
+
+    return haveValidObjectCode;
+}
diff --git a/Compiler/Common.h b/Compiler/Common.h
new file mode 100644
index 0000000..1ab2e91
--- /dev/null
+++ b/Compiler/Common.h
@@ -0,0 +1,164 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _COMMON_INCLUDED_
+#define _COMMON_INCLUDED_
+
+#ifdef _WIN32
+    #include <basetsd.h>
+#elif defined (solaris)
+    #include <sys/int_types.h>
+    #define UINT_PTR uintptr_t
+#else
+    #include <stdint.h>
+    #define UINT_PTR uintptr_t
+#endif
+
+/* windows only pragma */
+#ifdef _MSC_VER
+    #pragma warning(disable : 4786) // Don't warn about too long identifiers
+    #pragma warning(disable : 4514) // unused inline method
+    #pragma warning(disable : 4201) // nameless union
+#endif
+
+//
+// Doing the push and pop below for warnings does not leave the warning state
+// the way it was.  This seems like a defect in the compiler.  We would like
+// to do this, but since it does not work correctly right now, it is turned
+// off.
+//
+//??#pragma warning(push, 3)
+
+	#include <set>
+    #include <vector>
+    #include <map>
+    #include <list>
+    #include <string>
+    #include <stdio.h>
+
+//??#pragma warning(pop)
+
+typedef int TSourceLoc;
+
+	#include <assert.h>
+
+#include "PoolAlloc.h"
+
+//
+// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
+//
+#define POOL_ALLOCATOR_NEW_DELETE(A)                                  \
+    void* operator new(size_t s) { return (A).allocate(s); }          \
+    void* operator new(size_t, void *_Where) { return (_Where);	}     \
+    void operator delete(void*) { }                                   \
+    void operator delete(void *, void *) { }                          \
+    void* operator new[](size_t s) { return (A).allocate(s); }        \
+    void* operator new[](size_t, void *_Where) { return (_Where);	} \
+    void operator delete[](void*) { }                                 \
+    void operator delete[](void *, void *) { }
+
+#define TBaseMap std::map
+#define TBaseList std::list
+#define TBaseSet std::set
+
+//
+// Pool version of string.
+//
+typedef pool_allocator<char> TStringAllocator;
+typedef std::basic_string <char, std::char_traits<char>, TStringAllocator > TString;
+inline TString* NewPoolTString(const char* s)
+{
+	void* memory = GlobalPoolAllocator.allocate(sizeof(TString));
+	return new(memory) TString(s);
+}
+
+//
+// Pool allocator versions of vectors, lists, and maps
+//
+template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
+public:
+    typedef typename std::vector<T, pool_allocator<T> >::size_type size_type;
+    TVector() : std::vector<T, pool_allocator<T> >() {}
+    TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {}
+    TVector(size_type i): std::vector<T, pool_allocator<T> >(i) {}
+};
+
+template <class T> class TList   : public TBaseList  <T, pool_allocator<T> > {
+public:
+    typedef typename TBaseList<T, pool_allocator<T> >::size_type size_type;
+    TList() : TBaseList<T, pool_allocator<T> >() {}
+    TList(const pool_allocator<T>& a) : TBaseList<T, pool_allocator<T> >(a) {}
+    TList(size_type i): TBaseList<T, pool_allocator<T> >(i) {}
+};
+
+// This is called TStlSet, because TSet is taken by an existing compiler class.
+template <class T, class CMP> class TStlSet : public std::set<T, CMP, pool_allocator<T> > {
+    // No pool allocator versions of constructors in std::set.
+};
+
+
+template <class K, class D, class CMP = std::less<K> > 
+class TMap : public TBaseMap<K, D, CMP, pool_allocator<std::pair<K, D> > > {
+public:
+    typedef pool_allocator<std::pair <K, D> > tAllocator;
+
+    TMap() : TBaseMap<K, D, CMP, tAllocator >() {}
+    // use correct two-stage name lookup supported in gcc 3.4 and above
+    TMap(const tAllocator& a) : TBaseMap<K, D, CMP, tAllocator>(TBaseMap<K, D, CMP, tAllocator >::key_compare(), a) {}
+};
+
+//
+// Persistent string memory.  Should only be used for strings that survive
+// across compiles/links.
+//
+typedef std::basic_string<char> TPersistString;
+
+//
+// templatized min and max functions.
+//
+template <class T> T Min(const T a, const T b) { return a < b ? a : b; }
+template <class T> T Max(const T a, const T b) { return a > b ? a : b; }
+
+//
+// Create a TString object from an integer.
+//
+inline const TString String(const int i, const int base = 10)
+{
+    char text[16];     // 32 bit ints are at most 10 digits in base 10
+    
+    #ifdef _WIN32
+        _itoa(i, text, base);
+    #else
+        // we assume base 10 for all cases
+        sprintf(text, "%d", i);
+    #endif
+
+    return text;
+}
+
+const unsigned int SourceLocLineMask = 0xffff;
+const unsigned int SourceLocStringShift = 16;
+
+__inline TPersistString FormatSourceLoc(const TSourceLoc loc)
+{
+    char locText[64];
+
+    int string = loc >> SourceLocStringShift;
+    int line = loc & SourceLocLineMask;
+
+    if (line)
+        sprintf(locText, "%d:%d", string, line);
+    else
+        sprintf(locText, "%d:? ", string);
+
+    return TPersistString(locText);
+}
+
+
+typedef TMap<TString, TString> TPragmaTable;
+typedef TMap<TString, TString>::tAllocator TPragmaTableAllocator;
+
+#endif // _COMMON_INCLUDED_
diff --git a/Compiler/Compiler.vcproj b/Compiler/Compiler.vcproj
new file mode 100644
index 0000000..7c380e9
--- /dev/null
+++ b/Compiler/Compiler.vcproj
@@ -0,0 +1,474 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="9.00"

+	Name="Compiler"

+	ProjectGUID="{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}"

+	RootNamespace="Compiler"

+	Keyword="Win32Proj"

+	TargetFrameworkVersion="131072"

+	>

+	<Platforms>

+		<Platform

+			Name="Win32"

+		/>

+	</Platforms>

+	<ToolFiles>

+	</ToolFiles>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(ConfigurationName)"

+			ConfigurationType="4"

+			CharacterSet="0"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				AdditionalIncludeDirectories="./; ../Include/"

+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"

+				MinimalRebuild="true"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="1"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="false"

+				DebugInformationFormat="4"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLibrarianTool"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"

+			IntermediateDirectory="$(ConfigurationName)"

+			ConfigurationType="4"

+			CharacterSet="0"

+			WholeProgramOptimization="1"

+			>

+			<Tool

+				Name="VCPreBuildEventTool"

+			/>

+			<Tool

+				Name="VCCustomBuildTool"

+			/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"

+			/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"

+			/>

+			<Tool

+				Name="VCMIDLTool"

+			/>

+			<Tool

+				Name="VCCLCompilerTool"

+				AdditionalIncludeDirectories="./; ../Include/"

+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"

+				RuntimeLibrary="0"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="false"

+				DebugInformationFormat="3"

+			/>

+			<Tool

+				Name="VCManagedResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCResourceCompilerTool"

+			/>

+			<Tool

+				Name="VCPreLinkEventTool"

+			/>

+			<Tool

+				Name="VCLibrarianTool"

+			/>

+			<Tool

+				Name="VCALinkTool"

+			/>

+			<Tool

+				Name="VCXDCMakeTool"

+			/>

+			<Tool

+				Name="VCBscMakeTool"

+			/>

+			<Tool

+				Name="VCFxCopTool"

+			/>

+			<Tool

+				Name="VCPostBuildEventTool"

+			/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"

+			>

+			<File

+				RelativePath=".\CodeGen.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\glslang.l"

+				>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCCustomBuildTool"

+						Description="Executing flex on $(InputPath)"

+						CommandLine="if EXIST $(InputDir)Gen_glslang.cpp del $(InputDir)Gen_glslang.cpp&#x0D;&#x0A;$(InputDir)Tools\flex.exe $(InputPath)&#x0D;&#x0A;"

+						AdditionalDependencies="glslang_tab.h"

+						Outputs="$(InputDir)Gen_glslang.cpp"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32"

+					>

+					<Tool

+						Name="VCCustomBuildTool"

+						Description="Executing flex on $(InputPath)"

+						CommandLine="if EXIST $(InputDir)Gen_glslang.cpp del $(InputDir)Gen_glslang.cpp&#x0D;&#x0A;$(InputDir)Tools\flex.exe $(InputPath)&#x0D;&#x0A;"

+						AdditionalDependencies="glslang_tab.h"

+						Outputs="$(InputDir)Gen_glslang.cpp"

+					/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath=".\glslang.y"

+				>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCCustomBuildTool"

+						Description="Executing Bison on $(InputPath)"

+						CommandLine="SET BISON_SIMPLE=$(InputDir)Tools\bison.simple&#x0D;&#x0A;SET BISON_HAIRY=$(InputDir)Tools\bison.simple&#x0D;&#x0A;if EXIST $(InputDir)Gen_$(InputName)_tab.cpp del $(InputDir)Gen_$(InputName)_tab.cpp&#x0D;&#x0A;$(InputDir)Tools\bison.exe -d -t -v $(InputName).y&#x0D;&#x0A;rename $(InputDir)$(InputName)_tab.c Gen_$(InputName)_tab.cpp&#x0D;&#x0A;"

+						Outputs="$(InputDir)Gen_$(InputName)_tab.cpp"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32"

+					>

+					<Tool

+						Name="VCCustomBuildTool"

+						Description="Executing Bison on $(InputPath)"

+						CommandLine="SET BISON_SIMPLE=$(InputDir)Tools\bison.simple&#x0D;&#x0A;SET BISON_HAIRY=$(InputDir)Tools\bison.simple&#x0D;&#x0A;if EXIST $(InputDir)Gen_$(InputName)_tab.cpp del $(InputDir)Gen_$(InputName)_tab.cpp&#x0D;&#x0A;$(InputDir)Tools\bison.exe -d -t -v $(InputName).y&#x0D;&#x0A;rename $(InputDir)$(InputName)_tab.c Gen_$(InputName)_tab.cpp&#x0D;&#x0A;"

+						Outputs="$(InputDir)Gen_$(InputName)_tab.cpp"

+					/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath=".\InfoSink.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\Initialize.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\InitializeDll.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\Intermediate.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\intermOut.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\IntermTraverse.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\Link.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\ossource.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\OutputHLSL.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\parseConst.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\ParseHelper.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\PoolAlloc.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\QualifierAlive.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\RemoveTree.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\ShaderLang.cpp"

+				>

+			</File>

+			<File

+				RelativePath=".\SymbolTable.cpp"

+				>

+			</File>

+			<Filter

+				Name="Preprocessor"

+				>

+				<File

+					RelativePath=".\Preprocessor\atom.c"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\cpp.c"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\cppstruct.c"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\memory.c"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\scanner.c"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\symbols.c"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\tokens.c"

+					>

+				</File>

+			</Filter>

+			<Filter

+				Name="Generated"

+				>

+				<File

+					RelativePath=".\Gen_glslang.cpp"

+					>

+				</File>

+				<File

+					RelativePath=".\Gen_glslang_tab.cpp"

+					>

+				</File>

+			</Filter>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"

+			>

+			<File

+				RelativePath=".\BaseTypes.h"

+				>

+			</File>

+			<File

+				RelativePath=".\Common.h"

+				>

+			</File>

+			<File

+				RelativePath=".\ConstantUnion.h"

+				>

+			</File>

+			<File

+				RelativePath=".\InfoSink.h"

+				>

+			</File>

+			<File

+				RelativePath=".\Initialize.h"

+				>

+			</File>

+			<File

+				RelativePath=".\InitializeDll.h"

+				>

+			</File>

+			<File

+				RelativePath=".\InitializeGlobals.h"

+				>

+			</File>

+			<File

+				RelativePath=".\InitializeParseContext.h"

+				>

+			</File>

+			<File

+				RelativePath=".\intermediate.h"

+				>

+			</File>

+			<File

+				RelativePath=".\localintermediate.h"

+				>

+			</File>

+			<File

+				RelativePath=".\MMap.h"

+				>

+			</File>

+			<File

+				RelativePath=".\osinclude.h"

+				>

+			</File>

+			<File

+				RelativePath=".\OutputHLSL.h"

+				>

+			</File>

+			<File

+				RelativePath=".\ParseHelper.h"

+				>

+			</File>

+			<File

+				RelativePath=".\PoolAlloc.h"

+				>

+			</File>

+			<File

+				RelativePath=".\QualifierAlive.h"

+				>

+			</File>

+			<File

+				RelativePath=".\RemoveTree.h"

+				>

+			</File>

+			<File

+				RelativePath=".\ResourceLimits.h"

+				>

+			</File>

+			<File

+				RelativePath=".\ShaderLang.h"

+				>

+			</File>

+			<File

+				RelativePath=".\ShHandle.h"

+				>

+			</File>

+			<File

+				RelativePath=".\SymbolTable.h"

+				>

+			</File>

+			<File

+				RelativePath=".\Types.h"

+				>

+			</File>

+			<File

+				RelativePath=".\unistd.h"

+				>

+			</File>

+			<Filter

+				Name="Preprocessor"

+				>

+				<File

+					RelativePath=".\Preprocessor\atom.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\compile.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\cpp.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\memory.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\parser.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\preprocess.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\scanner.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\slglobals.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\symbols.h"

+					>

+				</File>

+				<File

+					RelativePath=".\Preprocessor\tokens.h"

+					>

+				</File>

+			</Filter>

+			<Filter

+				Name="Generated"

+				>

+				<File

+					RelativePath=".\glslang_tab.h"

+					>

+				</File>

+			</Filter>

+		</Filter>

+		<Filter

+			Name="Resource Files"

+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"

+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"

+			>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/Compiler/ConstantUnion.h b/Compiler/ConstantUnion.h
new file mode 100644
index 0000000..b0ab971
--- /dev/null
+++ b/Compiler/ConstantUnion.h
@@ -0,0 +1,287 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _CONSTANT_UNION_INCLUDED_
+#define _CONSTANT_UNION_INCLUDED_
+
+
+class constUnion {
+public:
+
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)        
+    void setIConst(int i) {iConst = i; type = EbtInt; }
+    void setFConst(float f) {fConst = f; type = EbtFloat; }
+    void setBConst(bool b) {bConst = b; type = EbtBool; }
+
+    int getIConst() { return iConst; }
+    float getFConst() { return fConst; }
+    bool getBConst() { return bConst; }
+    int getIConst() const { return iConst; }
+    float getFConst() const { return fConst; }
+    bool getBConst() const { return bConst; }
+
+    bool operator==(const int i) const
+    {
+        if (i == iConst)
+            return true;
+
+        return false;
+    }
+
+    bool operator==(const float f) const
+    {
+        if (f == fConst)
+            return true;
+
+        return false;
+    }
+
+    bool operator==(const bool b) const
+    {
+        if (b == bConst)
+            return true;
+
+        return false;
+    }
+
+    bool operator==(const constUnion& constant) const
+    {
+        if (constant.type != type)
+            return false;
+
+        switch (type) {
+        case EbtInt:
+            if (constant.iConst == iConst)
+                return true;
+
+            break;
+        case EbtFloat:
+            if (constant.fConst == fConst)
+                return true;
+
+            break;
+        case EbtBool:
+            if (constant.bConst == bConst)
+                return true;
+
+            break;
+        }
+
+        return false;
+    }
+
+    bool operator!=(const int i) const
+    {
+        return !operator==(i);
+    }
+
+    bool operator!=(const float f) const
+    {
+        return !operator==(f);
+    }
+
+    bool operator!=(const bool b) const
+    {
+        return !operator==(b);
+    }
+
+    bool operator!=(const constUnion& constant) const
+    {
+        return !operator==(constant);
+    }
+
+    bool operator>(const constUnion& constant) const
+    { 
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:
+            if (iConst > constant.iConst)
+                return true;
+
+            return false;
+        case EbtFloat:
+            if (fConst > constant.fConst)
+                return true;
+
+            return false;
+        default:
+            assert(false && "Default missing");
+            return false;
+        }
+
+        return false;
+    }
+
+    bool operator<(const constUnion& constant) const
+    { 
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:
+            if (iConst < constant.iConst)
+                return true;
+
+            return false;
+        case EbtFloat:
+            if (fConst < constant.fConst)
+                return true;
+
+            return false;
+        default:
+            assert(false && "Default missing");
+            return false;
+        }
+
+        return false;
+    }
+
+    constUnion operator+(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
+        case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break;
+        default: assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator-(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
+        case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break;
+        default: assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator*(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
+        case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; 
+        default: assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator%(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator>>(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator<<(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator&(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst & constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator|(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst | constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator^(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst ^ constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator&&(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    constUnion operator||(const constUnion& constant) const
+    { 
+        constUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    TBasicType getType() { return type; }
+private:
+
+    union  {
+        int iConst;  // used for ivec, scalar ints
+        bool bConst; // used for bvec, scalar bools
+        float fConst;   // used for vec, mat, scalar floats
+    } ;
+
+    TBasicType type;
+};
+
+#endif // _CONSTANT_UNION_INCLUDED_
diff --git a/Compiler/InfoSink.cpp b/Compiler/InfoSink.cpp
new file mode 100644
index 0000000..9f2a188
--- /dev/null
+++ b/Compiler/InfoSink.cpp
@@ -0,0 +1,79 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "InfoSink.h"
+
+#ifdef _WIN32
+    #include <windows.h>
+#endif
+
+void TInfoSinkBase::append(const char *s)           
+{
+    if (outputStream & EString) {
+        checkMem(strlen(s)); 
+        sink.append(s); 
+    }
+
+#ifdef _WIN32
+    if (outputStream & EDebugger)
+        OutputDebugString(s);
+#endif
+
+    if (outputStream & EStdOut)
+        fprintf(stdout, "%s", s);
+}
+
+void TInfoSinkBase::append(int count, char c)       
+{ 
+    if (outputStream & EString) {
+        checkMem(count);         
+        sink.append(count, c); 
+    }
+
+#ifdef _WIN32
+    if (outputStream & EDebugger) {
+        char str[2];
+        str[0] = c;
+        str[1] = '\0';
+        OutputDebugString(str);
+    }
+#endif
+
+    if (outputStream & EStdOut)
+        fprintf(stdout, "%c", c);
+}
+
+void TInfoSinkBase::append(const TPersistString& t) 
+{ 
+    if (outputStream & EString) {
+        checkMem(t.size());  
+        sink.append(t); 
+    }
+
+#ifdef _WIN32
+    if (outputStream & EDebugger)
+        OutputDebugString(t.c_str());
+#endif
+
+    if (outputStream & EStdOut)
+        fprintf(stdout, "%s", t.c_str());
+}
+
+void TInfoSinkBase::append(const TString& t)
+{ 
+    if (outputStream & EString) {
+        checkMem(t.size());  
+        sink.append(t.c_str()); 
+    }
+
+#ifdef _WIN32
+    if (outputStream & EDebugger)
+        OutputDebugString(t.c_str());
+#endif
+
+    if (outputStream & EStdOut)
+        fprintf(stdout, "%s", t.c_str());
+}
diff --git a/Compiler/InfoSink.h b/Compiler/InfoSink.h
new file mode 100644
index 0000000..525a378
--- /dev/null
+++ b/Compiler/InfoSink.h
@@ -0,0 +1,109 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _INFOSINK_INCLUDED_
+#define _INFOSINK_INCLUDED_
+
+#include "Common.h"
+#include <math.h>
+
+//
+// TPrefixType is used to centralize how info log messages start.
+// See below.
+//
+enum TPrefixType {
+    EPrefixNone,
+    EPrefixWarning,
+    EPrefixError,
+    EPrefixInternalError,
+    EPrefixUnimplemented,
+    EPrefixNote
+};
+
+enum TOutputStream {
+    ENull = 0,
+    EDebugger = 0x01,
+    EStdOut = 0x02,
+    EString = 0x04,
+};
+//
+// Encapsulate info logs for all objects that have them.
+//
+// The methods are a general set of tools for getting a variety of
+// messages and types inserted into the log.
+//
+class TInfoSinkBase {
+public:
+    TInfoSinkBase() : outputStream(4) {}
+    void erase() { sink.erase(); }
+    TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; }
+    TInfoSinkBase& operator<<(char c)                  { append(1, c); return *this; }
+    TInfoSinkBase& operator<<(const char* s)           { append(s); return *this; }
+    TInfoSinkBase& operator<<(int n)                   { append(String(n)); return *this; }
+    TInfoSinkBase& operator<<(const unsigned int n)    { append(String(n)); return *this; }
+    TInfoSinkBase& operator<<(float n)                 { char buf[40]; 
+                                                     sprintf(buf, "%.8g", n);
+                                                     append(buf); 
+                                                     return *this; }
+    TInfoSinkBase& operator+(const TPersistString& t)  { append(t); return *this; }
+    TInfoSinkBase& operator+(const TString& t)         { append(t); return *this; }
+    TInfoSinkBase& operator<<(const TString& t)        { append(t); return *this; }
+    TInfoSinkBase& operator+(const char* s)            { append(s); return *this; }
+    const char* c_str() const { return sink.c_str(); }
+    void prefix(TPrefixType message) {
+        switch(message) {
+        case EPrefixNone:                                      break;
+        case EPrefixWarning:       append("WARNING: ");        break;
+        case EPrefixError:         append("ERROR: ");          break;
+        case EPrefixInternalError: append("INTERNAL ERROR: "); break;
+        case EPrefixUnimplemented: append("UNIMPLEMENTED: ");  break;
+        case EPrefixNote:          append("NOTE: ");           break;
+        default:                   append("UNKOWN ERROR: ");   break;
+        }
+    }
+    void location(TSourceLoc loc) {
+        append(FormatSourceLoc(loc).c_str());
+        append(": ");
+    }
+    void message(TPrefixType message, const char* s) {
+        prefix(message);
+        append(s);
+        append("\n");
+    }
+    void message(TPrefixType message, const char* s, TSourceLoc loc) {
+        prefix(message);
+        location(loc);
+        append(s);
+        append("\n");
+    }
+    
+    void setOutputStream(int output = 4)
+    {
+        outputStream = output;
+    }
+
+protected:
+    void append(const char *s); 
+
+    void append(int count, char c);
+    void append(const TPersistString& t);
+    void append(const TString& t);
+
+    void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2)  
+                                       sink.reserve(sink.capacity() +  sink.capacity() / 2); }
+    void appendToStream(const char* s);
+    TPersistString sink;
+    int outputStream;
+};
+
+class TInfoSink {
+public:
+    TInfoSinkBase info;
+    TInfoSinkBase debug;
+    TInfoSinkBase obj;
+};
+
+#endif // _INFOSINK_INCLUDED_
diff --git a/Compiler/Initialize.cpp b/Compiler/Initialize.cpp
new file mode 100644
index 0000000..2b7ecff
--- /dev/null
+++ b/Compiler/Initialize.cpp
@@ -0,0 +1,616 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Create strings that declare built-in definitions, add built-ins that
+// cannot be expressed in the files, and establish mappings between 
+// built-in functions and operators.
+//
+
+#include "intermediate.h"
+#include "Initialize.h"
+
+void TBuiltIns::initialize()
+{
+	//
+	// Initialize all the built-in strings for parsing.
+	//
+	TString BuiltInFunctions;
+	TString BuiltInFunctionsVertex;
+	TString BuiltInFunctionsFragment;
+	TString StandardUniforms;
+
+	{
+		//============================================================================
+		//
+		// Prototypes for built-in functions seen by both vertex and fragment shaders.
+		//
+		//============================================================================
+
+		TString& s = BuiltInFunctions;
+
+		//
+		// Angle and Trigonometric Functions.
+		//
+		s.append(TString("float radians(float degrees);"));
+		s.append(TString("vec2  radians(vec2  degrees);"));
+		s.append(TString("vec3  radians(vec3  degrees);"));
+		s.append(TString("vec4  radians(vec4  degrees);"));
+
+		s.append(TString("float degrees(float radians);"));
+		s.append(TString("vec2  degrees(vec2  radians);"));
+		s.append(TString("vec3  degrees(vec3  radians);"));
+		s.append(TString("vec4  degrees(vec4  radians);"));
+
+		s.append(TString("float sin(float angle);"));
+		s.append(TString("vec2  sin(vec2  angle);"));
+		s.append(TString("vec3  sin(vec3  angle);"));
+		s.append(TString("vec4  sin(vec4  angle);"));
+
+		s.append(TString("float cos(float angle);"));
+		s.append(TString("vec2  cos(vec2  angle);"));
+		s.append(TString("vec3  cos(vec3  angle);"));
+		s.append(TString("vec4  cos(vec4  angle);"));
+
+		s.append(TString("float tan(float angle);"));
+		s.append(TString("vec2  tan(vec2  angle);"));
+		s.append(TString("vec3  tan(vec3  angle);"));
+		s.append(TString("vec4  tan(vec4  angle);"));
+
+		s.append(TString("float asin(float x);"));
+		s.append(TString("vec2  asin(vec2  x);"));
+		s.append(TString("vec3  asin(vec3  x);"));
+		s.append(TString("vec4  asin(vec4  x);"));
+
+		s.append(TString("float acos(float x);"));
+		s.append(TString("vec2  acos(vec2  x);"));
+		s.append(TString("vec3  acos(vec3  x);"));
+		s.append(TString("vec4  acos(vec4  x);"));
+
+		s.append(TString("float atan(float y, float x);"));
+		s.append(TString("vec2  atan(vec2  y, vec2  x);"));
+		s.append(TString("vec3  atan(vec3  y, vec3  x);"));
+		s.append(TString("vec4  atan(vec4  y, vec4  x);"));
+
+		s.append(TString("float atan(float y_over_x);"));
+		s.append(TString("vec2  atan(vec2  y_over_x);"));
+		s.append(TString("vec3  atan(vec3  y_over_x);"));
+		s.append(TString("vec4  atan(vec4  y_over_x);"));
+
+		//
+		// Exponential Functions.
+		//
+		s.append(TString("float pow(float x, float y);"));
+		s.append(TString("vec2  pow(vec2  x, vec2  y);"));
+		s.append(TString("vec3  pow(vec3  x, vec3  y);"));
+		s.append(TString("vec4  pow(vec4  x, vec4  y);"));
+
+		s.append(TString("float exp(float x);"));
+		s.append(TString("vec2  exp(vec2  x);"));
+		s.append(TString("vec3  exp(vec3  x);"));
+		s.append(TString("vec4  exp(vec4  x);"));
+
+		s.append(TString("float log(float x);"));
+		s.append(TString("vec2  log(vec2  x);"));
+		s.append(TString("vec3  log(vec3  x);"));
+		s.append(TString("vec4  log(vec4  x);"));
+
+		s.append(TString("float exp2(float x);"));
+		s.append(TString("vec2  exp2(vec2  x);"));
+		s.append(TString("vec3  exp2(vec3  x);"));
+		s.append(TString("vec4  exp2(vec4  x);"));
+
+		s.append(TString("float log2(float x);"));
+		s.append(TString("vec2  log2(vec2  x);"));
+		s.append(TString("vec3  log2(vec3  x);"));
+		s.append(TString("vec4  log2(vec4  x);"));
+
+		s.append(TString("float sqrt(float x);"));
+		s.append(TString("vec2  sqrt(vec2  x);"));
+		s.append(TString("vec3  sqrt(vec3  x);"));
+		s.append(TString("vec4  sqrt(vec4  x);"));
+
+		s.append(TString("float inversesqrt(float x);"));
+		s.append(TString("vec2  inversesqrt(vec2  x);"));
+		s.append(TString("vec3  inversesqrt(vec3  x);"));
+		s.append(TString("vec4  inversesqrt(vec4  x);"));
+
+		//
+		// Common Functions.
+		//
+		s.append(TString("float abs(float x);"));
+		s.append(TString("vec2  abs(vec2  x);"));
+		s.append(TString("vec3  abs(vec3  x);"));
+		s.append(TString("vec4  abs(vec4  x);"));
+
+		s.append(TString("float sign(float x);"));
+		s.append(TString("vec2  sign(vec2  x);"));
+		s.append(TString("vec3  sign(vec3  x);"));
+		s.append(TString("vec4  sign(vec4  x);"));
+
+		s.append(TString("float floor(float x);"));
+		s.append(TString("vec2  floor(vec2  x);"));
+		s.append(TString("vec3  floor(vec3  x);"));
+		s.append(TString("vec4  floor(vec4  x);"));
+
+		s.append(TString("float ceil(float x);"));
+		s.append(TString("vec2  ceil(vec2  x);"));
+		s.append(TString("vec3  ceil(vec3  x);"));
+		s.append(TString("vec4  ceil(vec4  x);"));
+
+		s.append(TString("float fract(float x);"));
+		s.append(TString("vec2  fract(vec2  x);"));
+		s.append(TString("vec3  fract(vec3  x);"));
+		s.append(TString("vec4  fract(vec4  x);"));
+
+		s.append(TString("float mod(float x, float y);"));
+		s.append(TString("vec2  mod(vec2  x, float y);"));
+		s.append(TString("vec3  mod(vec3  x, float y);"));
+		s.append(TString("vec4  mod(vec4  x, float y);"));
+		s.append(TString("vec2  mod(vec2  x, vec2  y);"));
+		s.append(TString("vec3  mod(vec3  x, vec3  y);"));
+		s.append(TString("vec4  mod(vec4  x, vec4  y);"));
+
+		s.append(TString("float min(float x, float y);"));
+		s.append(TString("vec2  min(vec2  x, float y);"));
+		s.append(TString("vec3  min(vec3  x, float y);"));
+		s.append(TString("vec4  min(vec4  x, float y);"));
+		s.append(TString("vec2  min(vec2  x, vec2  y);"));
+		s.append(TString("vec3  min(vec3  x, vec3  y);"));
+		s.append(TString("vec4  min(vec4  x, vec4  y);"));
+
+		s.append(TString("float max(float x, float y);"));
+		s.append(TString("vec2  max(vec2  x, float y);"));
+		s.append(TString("vec3  max(vec3  x, float y);"));
+		s.append(TString("vec4  max(vec4  x, float y);"));
+		s.append(TString("vec2  max(vec2  x, vec2  y);"));
+		s.append(TString("vec3  max(vec3  x, vec3  y);"));
+		s.append(TString("vec4  max(vec4  x, vec4  y);"));
+
+		s.append(TString("float clamp(float x, float minVal, float maxVal);"));
+		s.append(TString("vec2  clamp(vec2  x, float minVal, float maxVal);"));
+		s.append(TString("vec3  clamp(vec3  x, float minVal, float maxVal);"));
+		s.append(TString("vec4  clamp(vec4  x, float minVal, float maxVal);"));
+		s.append(TString("vec2  clamp(vec2  x, vec2  minVal, vec2  maxVal);"));
+		s.append(TString("vec3  clamp(vec3  x, vec3  minVal, vec3  maxVal);"));
+		s.append(TString("vec4  clamp(vec4  x, vec4  minVal, vec4  maxVal);"));
+
+		s.append(TString("float mix(float x, float y, float a);"));
+		s.append(TString("vec2  mix(vec2  x, vec2  y, float a);"));
+		s.append(TString("vec3  mix(vec3  x, vec3  y, float a);"));
+		s.append(TString("vec4  mix(vec4  x, vec4  y, float a);"));
+		s.append(TString("vec2  mix(vec2  x, vec2  y, vec2  a);"));
+		s.append(TString("vec3  mix(vec3  x, vec3  y, vec3  a);"));
+		s.append(TString("vec4  mix(vec4  x, vec4  y, vec4  a);"));
+
+		s.append(TString("float step(float edge, float x);"));
+		s.append(TString("vec2  step(vec2  edge, vec2  x);"));
+		s.append(TString("vec3  step(vec3  edge, vec3  x);"));
+		s.append(TString("vec4  step(vec4  edge, vec4  x);"));
+		s.append(TString("vec2  step(float edge, vec2  x);"));
+		s.append(TString("vec3  step(float edge, vec3  x);"));
+		s.append(TString("vec4  step(float edge, vec4  x);"));
+
+		s.append(TString("float smoothstep(float edge0, float edge1, float x);"));
+		s.append(TString("vec2  smoothstep(vec2  edge0, vec2  edge1, vec2  x);"));
+		s.append(TString("vec3  smoothstep(vec3  edge0, vec3  edge1, vec3  x);"));
+		s.append(TString("vec4  smoothstep(vec4  edge0, vec4  edge1, vec4  x);"));
+		s.append(TString("vec2  smoothstep(float edge0, float edge1, vec2  x);"));
+		s.append(TString("vec3  smoothstep(float edge0, float edge1, vec3  x);"));
+		s.append(TString("vec4  smoothstep(float edge0, float edge1, vec4  x);"));
+
+		//
+		// Geometric Functions.
+		//
+		s.append(TString("float length(float x);"));
+		s.append(TString("float length(vec2  x);"));
+		s.append(TString("float length(vec3  x);"));
+		s.append(TString("float length(vec4  x);"));
+
+		s.append(TString("float distance(float p0, float p1);"));
+		s.append(TString("float distance(vec2  p0, vec2  p1);"));
+		s.append(TString("float distance(vec3  p0, vec3  p1);"));
+		s.append(TString("float distance(vec4  p0, vec4  p1);"));
+
+		s.append(TString("float dot(float x, float y);"));
+		s.append(TString("float dot(vec2  x, vec2  y);"));
+		s.append(TString("float dot(vec3  x, vec3  y);"));
+		s.append(TString("float dot(vec4  x, vec4  y);"));
+
+		s.append(TString("vec3 cross(vec3 x, vec3 y);"));
+		s.append(TString("float normalize(float x);"));
+		s.append(TString("vec2  normalize(vec2  x);"));
+		s.append(TString("vec3  normalize(vec3  x);"));
+		s.append(TString("vec4  normalize(vec4  x);"));
+
+		s.append(TString("float faceforward(float N, float I, float Nref);"));
+		s.append(TString("vec2  faceforward(vec2  N, vec2  I, vec2  Nref);"));
+		s.append(TString("vec3  faceforward(vec3  N, vec3  I, vec3  Nref);"));
+		s.append(TString("vec4  faceforward(vec4  N, vec4  I, vec4  Nref);"));
+
+		s.append(TString("float reflect(float I, float N);"));
+		s.append(TString("vec2  reflect(vec2  I, vec2  N);"));
+		s.append(TString("vec3  reflect(vec3  I, vec3  N);"));
+		s.append(TString("vec4  reflect(vec4  I, vec4  N);"));
+
+		s.append(TString("float refract(float I, float N, float eta);"));
+		s.append(TString("vec2  refract(vec2  I, vec2  N, float eta);"));
+		s.append(TString("vec3  refract(vec3  I, vec3  N, float eta);"));
+		s.append(TString("vec4  refract(vec4  I, vec4  N, float eta);"));
+
+		//
+		// Matrix Functions.
+		//
+		s.append(TString("mat2 matrixCompMult(mat2 x, mat2 y);"));
+		s.append(TString("mat3 matrixCompMult(mat3 x, mat3 y);"));
+		s.append(TString("mat4 matrixCompMult(mat4 x, mat4 y);"));
+
+		//
+		// Vector relational functions.
+		//
+		s.append(TString("bvec2 lessThan(vec2 x, vec2 y);"));
+		s.append(TString("bvec3 lessThan(vec3 x, vec3 y);"));
+		s.append(TString("bvec4 lessThan(vec4 x, vec4 y);"));
+
+		s.append(TString("bvec2 lessThan(ivec2 x, ivec2 y);"));
+		s.append(TString("bvec3 lessThan(ivec3 x, ivec3 y);"));
+		s.append(TString("bvec4 lessThan(ivec4 x, ivec4 y);"));
+
+		s.append(TString("bvec2 lessThanEqual(vec2 x, vec2 y);"));
+		s.append(TString("bvec3 lessThanEqual(vec3 x, vec3 y);"));
+		s.append(TString("bvec4 lessThanEqual(vec4 x, vec4 y);"));
+
+		s.append(TString("bvec2 lessThanEqual(ivec2 x, ivec2 y);"));
+		s.append(TString("bvec3 lessThanEqual(ivec3 x, ivec3 y);"));
+		s.append(TString("bvec4 lessThanEqual(ivec4 x, ivec4 y);"));
+
+		s.append(TString("bvec2 greaterThan(vec2 x, vec2 y);"));
+		s.append(TString("bvec3 greaterThan(vec3 x, vec3 y);"));
+		s.append(TString("bvec4 greaterThan(vec4 x, vec4 y);"));
+
+		s.append(TString("bvec2 greaterThan(ivec2 x, ivec2 y);"));
+		s.append(TString("bvec3 greaterThan(ivec3 x, ivec3 y);"));
+		s.append(TString("bvec4 greaterThan(ivec4 x, ivec4 y);"));
+
+		s.append(TString("bvec2 greaterThanEqual(vec2 x, vec2 y);"));
+		s.append(TString("bvec3 greaterThanEqual(vec3 x, vec3 y);"));
+		s.append(TString("bvec4 greaterThanEqual(vec4 x, vec4 y);"));
+
+		s.append(TString("bvec2 greaterThanEqual(ivec2 x, ivec2 y);"));
+		s.append(TString("bvec3 greaterThanEqual(ivec3 x, ivec3 y);"));
+		s.append(TString("bvec4 greaterThanEqual(ivec4 x, ivec4 y);"));
+
+		s.append(TString("bvec2 equal(vec2 x, vec2 y);"));
+		s.append(TString("bvec3 equal(vec3 x, vec3 y);"));
+		s.append(TString("bvec4 equal(vec4 x, vec4 y);"));
+
+		s.append(TString("bvec2 equal(ivec2 x, ivec2 y);"));
+		s.append(TString("bvec3 equal(ivec3 x, ivec3 y);"));
+		s.append(TString("bvec4 equal(ivec4 x, ivec4 y);"));
+
+		s.append(TString("bvec2 equal(bvec2 x, bvec2 y);"));
+		s.append(TString("bvec3 equal(bvec3 x, bvec3 y);"));
+		s.append(TString("bvec4 equal(bvec4 x, bvec4 y);"));
+
+		s.append(TString("bvec2 notEqual(vec2 x, vec2 y);"));
+		s.append(TString("bvec3 notEqual(vec3 x, vec3 y);"));
+		s.append(TString("bvec4 notEqual(vec4 x, vec4 y);"));
+
+		s.append(TString("bvec2 notEqual(ivec2 x, ivec2 y);"));
+		s.append(TString("bvec3 notEqual(ivec3 x, ivec3 y);"));
+		s.append(TString("bvec4 notEqual(ivec4 x, ivec4 y);"));
+
+		s.append(TString("bvec2 notEqual(bvec2 x, bvec2 y);"));
+		s.append(TString("bvec3 notEqual(bvec3 x, bvec3 y);"));
+		s.append(TString("bvec4 notEqual(bvec4 x, bvec4 y);"));
+
+		s.append(TString("bool any(bvec2 x);"));
+		s.append(TString("bool any(bvec3 x);"));
+		s.append(TString("bool any(bvec4 x);"));
+
+		s.append(TString("bool all(bvec2 x);"));
+		s.append(TString("bool all(bvec3 x);"));
+		s.append(TString("bool all(bvec4 x);"));
+
+		s.append(TString("bvec2 not(bvec2 x);"));
+		s.append(TString("bvec3 not(bvec3 x);"));
+		s.append(TString("bvec4 not(bvec4 x);"));
+
+		//
+		// Texture Functions.
+		//
+		s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord);"));
+		s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord);"));
+		s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord);"));
+
+		s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord);"));
+
+		//
+		// Noise functions.
+		//
+	//	s.append(TString("float noise1(float x);"));
+	//	s.append(TString("float noise1(vec2  x);"));
+	//	s.append(TString("float noise1(vec3  x);"));
+	//	s.append(TString("float noise1(vec4  x);"));
+
+	//	s.append(TString("vec2 noise2(float x);"));
+	//	s.append(TString("vec2 noise2(vec2  x);"));
+	//	s.append(TString("vec2 noise2(vec3  x);"));
+	//	s.append(TString("vec2 noise2(vec4  x);"));
+
+	//	s.append(TString("vec3 noise3(float x);"));
+	//	s.append(TString("vec3 noise3(vec2  x);"));
+	//	s.append(TString("vec3 noise3(vec3  x);"));
+	//	s.append(TString("vec3 noise3(vec4  x);"));
+
+	//	s.append(TString("vec4 noise4(float x);"));
+	//	s.append(TString("vec4 noise4(vec2  x);"));
+	//	s.append(TString("vec4 noise4(vec3  x);"));
+	//	s.append(TString("vec4 noise4(vec4  x);"));
+
+		s.append(TString("\n"));
+	}
+	{
+		//============================================================================
+		//
+		// Prototypes for built-in functions seen by vertex shaders only.
+		//
+		//============================================================================
+
+		TString& s = BuiltInFunctionsVertex;
+
+		//
+		// Geometric Functions.
+		//
+		s.append(TString("vec4 ftransform();"));
+
+		//
+		// Texture Functions.
+		//
+		s.append(TString("vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);"));
+		s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);"));
+		s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);"));
+
+		s.append(TString("vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);"));
+
+		s.append(TString("\n"));
+	}
+	{
+		//============================================================================
+		//
+		// Prototypes for built-in functions seen by fragment shaders only.
+		//
+		//============================================================================
+
+		TString& s = BuiltInFunctionsFragment;
+
+		//
+		// Texture Functions.
+		//
+		s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord, float bias);"));
+		s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);"));
+		s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);"));
+
+		s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord, float bias);"));
+
+	//	s.append(TString("float dFdx(float p);"));
+	//	s.append(TString("vec2  dFdx(vec2  p);"));
+	//	s.append(TString("vec3  dFdx(vec3  p);"));
+	//	s.append(TString("vec4  dFdx(vec4  p);"));
+
+	//	s.append(TString("float dFdy(float p);"));
+	//	s.append(TString("vec2  dFdy(vec2  p);"));
+	//	s.append(TString("vec3  dFdy(vec3  p);"));
+	//	s.append(TString("vec4  dFdy(vec4  p);"));
+
+		s.append(TString("float fwidth(float p);"));
+		s.append(TString("vec2  fwidth(vec2  p);"));
+		s.append(TString("vec3  fwidth(vec3  p);"));
+		s.append(TString("vec4  fwidth(vec4  p);"));
+
+		s.append(TString("\n"));
+	}
+	{
+		//============================================================================
+		//
+		// Standard Uniforms
+		//
+		//============================================================================
+
+		TString& s = StandardUniforms;
+
+		//
+		// Depth range in window coordinates
+		//
+		s.append(TString("struct gl_DepthRangeParameters {"));
+		s.append(TString("    float near;"));        // n       // FIXME: highp
+		s.append(TString("    float far;"));         // f       // FIXME: highp
+		s.append(TString("    float diff;"));        // f - n   // FIXME: highp
+		s.append(TString("};"));
+		s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;"));
+
+		s.append(TString("\n"));
+	}
+
+	builtInStrings[EShLangFragment].push_back(BuiltInFunctions.c_str());
+	builtInStrings[EShLangFragment].push_back(BuiltInFunctionsFragment);
+	builtInStrings[EShLangFragment].push_back(StandardUniforms);
+
+	builtInStrings[EShLangVertex].push_back(BuiltInFunctions);
+	builtInStrings[EShLangVertex].push_back(BuiltInFunctionsVertex);
+	builtInStrings[EShLangVertex].push_back(StandardUniforms);
+}
+
+void TBuiltIns::initialize(const TBuiltInResource &resources)
+{
+	TString builtIns;
+
+	// Implementation dependent constants
+	char builtInConstant[80];
+
+	sprintf(builtInConstant, "const int  gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs);
+	builtIns.append(TString(builtInConstant));
+
+	sprintf(builtInConstant, "const int  gl_MaxVertexUniformVectors = %d;", resources.maxVertexUniformVectors);
+	builtIns.append(TString(builtInConstant));       
+
+	sprintf(builtInConstant, "const int  gl_MaxVaryingVectors = %d;", resources.maxVaryingVectors);
+	builtIns.append(TString(builtInConstant));        
+
+	sprintf(builtInConstant, "const int  gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits);
+	builtIns.append(TString(builtInConstant));        
+
+	sprintf(builtInConstant, "const int  gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits);
+	builtIns.append(TString(builtInConstant));        
+
+	sprintf(builtInConstant, "const int  gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits);
+	builtIns.append(TString(builtInConstant));
+
+	sprintf(builtInConstant, "const int  gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors);
+	builtIns.append(TString(builtInConstant));
+
+	sprintf(builtInConstant, "const int  gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers);
+	builtIns.append(TString(builtInConstant));
+
+	builtInStrings[EShLangFragment].push_back(builtIns);
+	builtInStrings[EShLangVertex].push_back(builtIns);
+}
+
+void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable)
+{
+	//
+	// First, insert some special built-in variables that are not in 
+	// the built-in header files.
+	//
+	switch(language) {
+
+	case EShLangFragment: {
+			symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"),                   TType(EbtFloat, EvqFragCoord,   4)));   // FIXME: mediump
+			symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"),                 TType(EbtBool,  EvqFrontFacing, 1)));
+			symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"),                   TType(EbtFloat, EvqFragColor,   4)));   // FIXME: mediump
+			symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EvqFragData,    4)));   // FIXME: mediump
+			symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"),                  TType(EbtFloat, EvqPointCoord,  2)));   // FIXME: mediump
+
+		}
+		break;
+
+	case EShLangVertex:
+		symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"),    TType(EbtFloat, EvqPosition,    4)));   // FIXME: highp
+		symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"),   TType(EbtFloat, EvqPointSize,   1)));   // FIXME: mediump
+		break;
+	default: break;
+	}
+
+	//
+	// Next, identify which built-ins from the already loaded headers have
+	// a mapping to an operator.  Those that are not identified as such are
+	// expected to be resolved through a library of functions, versus as
+	// operations.
+	//
+	symbolTable.relateToOperator("not",              EOpVectorLogicalNot);
+
+	symbolTable.relateToOperator("matrixCompMult",   EOpMul);
+	symbolTable.relateToOperator("mod",              EOpMod);
+
+	symbolTable.relateToOperator("equal",            EOpVectorEqual);
+	symbolTable.relateToOperator("notEqual",         EOpVectorNotEqual);
+	symbolTable.relateToOperator("lessThan",         EOpLessThan);
+	symbolTable.relateToOperator("greaterThan",      EOpGreaterThan);
+	symbolTable.relateToOperator("lessThanEqual",    EOpLessThanEqual);
+	symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual);
+	
+	symbolTable.relateToOperator("radians",      EOpRadians);
+	symbolTable.relateToOperator("degrees",      EOpDegrees);
+	symbolTable.relateToOperator("sin",          EOpSin);
+	symbolTable.relateToOperator("cos",          EOpCos);
+	symbolTable.relateToOperator("tan",          EOpTan);
+	symbolTable.relateToOperator("asin",         EOpAsin);
+	symbolTable.relateToOperator("acos",         EOpAcos);
+	symbolTable.relateToOperator("atan",         EOpAtan);
+
+	symbolTable.relateToOperator("pow",          EOpPow);
+	symbolTable.relateToOperator("exp2",         EOpExp2);
+	symbolTable.relateToOperator("log",          EOpLog);
+	symbolTable.relateToOperator("exp",          EOpExp);
+	symbolTable.relateToOperator("log2",         EOpLog2);
+	symbolTable.relateToOperator("sqrt",         EOpSqrt);
+	symbolTable.relateToOperator("inversesqrt",  EOpInverseSqrt);
+
+	symbolTable.relateToOperator("abs",          EOpAbs);
+	symbolTable.relateToOperator("sign",         EOpSign);
+	symbolTable.relateToOperator("floor",        EOpFloor);
+	symbolTable.relateToOperator("ceil",         EOpCeil);
+	symbolTable.relateToOperator("fract",        EOpFract);
+	symbolTable.relateToOperator("min",          EOpMin);
+	symbolTable.relateToOperator("max",          EOpMax);
+	symbolTable.relateToOperator("clamp",        EOpClamp);
+	symbolTable.relateToOperator("mix",          EOpMix);
+	symbolTable.relateToOperator("step",         EOpStep);
+	symbolTable.relateToOperator("smoothstep",   EOpSmoothStep);
+
+	symbolTable.relateToOperator("length",       EOpLength);
+	symbolTable.relateToOperator("distance",     EOpDistance);
+	symbolTable.relateToOperator("dot",          EOpDot);
+	symbolTable.relateToOperator("cross",        EOpCross);
+	symbolTable.relateToOperator("normalize",    EOpNormalize);
+	symbolTable.relateToOperator("forward",      EOpFaceForward);
+	symbolTable.relateToOperator("reflect",      EOpReflect);
+	symbolTable.relateToOperator("refract",      EOpRefract);
+	
+	symbolTable.relateToOperator("any",          EOpAny);
+	symbolTable.relateToOperator("all",          EOpAll);
+
+	switch(language)
+	{
+	case EShLangVertex:
+		break;
+	case EShLangFragment:
+	//	symbolTable.relateToOperator("dFdx",         EOpDPdx);             
+	//	symbolTable.relateToOperator("dFdy",         EOpDPdy);             
+	//	symbolTable.relateToOperator("fwidth",       EOpFwidth);
+		break;
+	case EShLangPack:
+	case EShLangUnpack:
+		symbolTable.relateToOperator("itof",         EOpItof);
+		symbolTable.relateToOperator("ftoi",         EOpFtoi);
+		symbolTable.relateToOperator("skipPixels",   EOpSkipPixels);
+		symbolTable.relateToOperator("readInput",    EOpReadInput);
+		symbolTable.relateToOperator("writePixel",   EOpWritePixel);
+		symbolTable.relateToOperator("bitmapLSB",    EOpBitmapLsb);
+		symbolTable.relateToOperator("bitmapMSB",    EOpBitmapMsb);
+		symbolTable.relateToOperator("writeOutput",  EOpWriteOutput);
+		symbolTable.relateToOperator("readPixel",    EOpReadPixel);
+		break;
+	default: assert(false && "Language not supported");
+	}
+}
+
+void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources)
+{
+	//
+	// First, insert some special built-in variables that are not in 
+	// the built-in header files.
+	//
+	switch(language) {
+
+	case EShLangFragment: {
+			// Set up gl_FragData.  The array size.
+			TType fragData(EbtFloat, EvqFragColor,   4, false, true);
+			fragData.setArraySize(resources.maxDrawBuffers);
+			symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"),    fragData));
+		}
+		break;
+
+	default: break;
+	}
+}
+
+const char* GetPreprocessorBuiltinString()
+{
+	static const char *PreprocessorBuiltinString = "";
+
+	return PreprocessorBuiltinString;
+}
diff --git a/Compiler/Initialize.h b/Compiler/Initialize.h
new file mode 100644
index 0000000..99b0dfc
--- /dev/null
+++ b/Compiler/Initialize.h
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _INITIALIZE_INCLUDED_
+#define _INITIALIZE_INCLUDED_
+
+#include "ResourceLimits.h"
+#include "Common.h"
+#include "ShHandle.h"
+#include "SymbolTable.h"
+
+typedef TVector<TString> TBuiltInStrings;
+
+class TBuiltIns {
+public:
+	POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+	void initialize();
+	void initialize(const TBuiltInResource& resources);
+	TBuiltInStrings* getBuiltInStrings() { return builtInStrings; }
+protected:
+	TBuiltInStrings builtInStrings[EShLangCount];
+};
+
+void IdentifyBuiltIns(EShLanguage, TSymbolTable&);
+void IdentifyBuiltIns(EShLanguage, TSymbolTable&, const TBuiltInResource &resources);
+bool GenerateBuiltInSymbolTable(const TBuiltInResource* resources, TInfoSink&, TSymbolTable*, EShLanguage language = EShLangCount);
+bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language, TInfoSink& infoSink, const TBuiltInResource *resources, TSymbolTable*);
+const char* GetPreprocessorBuiltinString();
+extern "C" int InitPreprocessor(void);
+extern "C" int FinalizePreprocessor(void);
+
+#endif // _INITIALIZE_INCLUDED_
diff --git a/Compiler/InitializeDll.cpp b/Compiler/InitializeDll.cpp
new file mode 100644
index 0000000..fd7c3ab
--- /dev/null
+++ b/Compiler/InitializeDll.cpp
@@ -0,0 +1,119 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "InitializeDll.h"
+#include "InitializeGlobals.h"
+#include "InitializeParseContext.h"
+
+#include "ShaderLang.h"
+
+OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
+
+bool InitProcess()
+{
+    if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) {
+		//
+		// Function is re-entrant.
+		//
+        return true;
+	}
+
+    ThreadInitializeIndex = OS_AllocTLSIndex();
+
+    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "InitProcess(): Failed to allocate TLS area for init flag");
+        return false;
+	}
+
+
+    if (!InitializePoolIndex()) {
+        assert(0 && "InitProcess(): Failed to initalize global pool");
+        return false;
+	}
+
+    if (!InitializeParseContextIndex()) {
+        assert(0 && "InitProcess(): Failed to initalize parse context");
+        return false;
+	}
+
+	InitThread();
+    return true;
+}
+
+
+bool InitThread()
+{
+	//
+    // This function is re-entrant
+	//
+    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
+		assert(0 && "InitThread(): Process hasn't been initalised.");
+        return false;
+	}
+
+    if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
+        return true;
+
+	InitializeGlobalPools();
+
+	if (!InitializeGlobalParseContext())
+        return false;
+
+    if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
+		assert(0 && "InitThread(): Unable to set init flag.");
+        return false;
+	}
+
+    return true;
+}
+
+
+bool DetachThread()
+{
+    bool success = true;
+
+    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
+        return true;
+
+	//
+	// Function is re-entrant and this thread may not have been initalised.
+	//
+    if (OS_GetTLSValue(ThreadInitializeIndex) != 0) {
+        if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) {
+			assert(0 && "DetachThread(): Unable to clear init flag.");
+            success = false;
+		}
+
+		FreeGlobalPools();
+
+		if (!FreeParseContext())
+            success = false;
+	}
+
+    return success;
+}
+
+bool DetachProcess()
+{
+    bool success = true;
+
+    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
+        return true;
+
+    ShFinalize();
+
+    success = DetachThread();
+
+	FreePoolIndex();
+
+	if (!FreeParseContextIndex())
+        success = false;
+
+    OS_FreeTLSIndex(ThreadInitializeIndex);
+    ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
+
+    return success;
+}
diff --git a/Compiler/InitializeDll.h b/Compiler/InitializeDll.h
new file mode 100644
index 0000000..ec7b303
--- /dev/null
+++ b/Compiler/InitializeDll.h
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef __INITIALIZEDLL_H
+#define __INITIALIZEDLL_H
+
+
+#include "osinclude.h"
+
+
+bool InitProcess();
+bool InitThread();
+bool DetachThread();
+bool DetachProcess();
+
+#endif // __INITIALIZEDLL_H
+
diff --git a/Compiler/InitializeGlobals.h b/Compiler/InitializeGlobals.h
new file mode 100644
index 0000000..842a452
--- /dev/null
+++ b/Compiler/InitializeGlobals.h
@@ -0,0 +1,15 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef __INITIALIZE_GLOBALS_INCLUDED_
+#define __INITIALIZE_GLOBALS_INCLUDED_
+
+void InitializeGlobalPools();
+void FreeGlobalPools();
+bool InitializePoolIndex();
+void FreePoolIndex();
+
+#endif // __INITIALIZE_GLOBALS_INCLUDED_
diff --git a/Compiler/InitializeParseContext.h b/Compiler/InitializeParseContext.h
new file mode 100644
index 0000000..45fc3f3
--- /dev/null
+++ b/Compiler/InitializeParseContext.h
@@ -0,0 +1,17 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef __INITIALIZE_PARSE_CONTEXT_INCLUDED_
+#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
+#include "osinclude.h"
+
+bool InitializeParseContextIndex();
+bool InitializeGlobalParseContext();
+bool FreeParseContext();
+bool FreeParseContextIndex();
+
+
+#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
diff --git a/Compiler/IntermTraverse.cpp b/Compiler/IntermTraverse.cpp
new file mode 100644
index 0000000..6a61884
--- /dev/null
+++ b/Compiler/IntermTraverse.cpp
@@ -0,0 +1,293 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "intermediate.h"
+
+//
+// Traverse the intermediate representation tree, and
+// call a node type specific function for each node.
+// Done recursively through the member function Traverse().
+// Node types can be skipped if their function to call is 0,
+// but their subtree will still be traversed.
+// Nodes with children can have their whole subtree skipped
+// if preVisit is turned on and the type specific function
+// returns false.
+//
+// preVisit, postVisit, and rightToLeft control what order
+// nodes are visited in.
+//
+
+//
+// Traversal functions for terminals are straighforward....
+//
+void TIntermSymbol::traverse(TIntermTraverser* it)
+{
+	it->visitSymbol(this);
+}
+
+void TIntermConstantUnion::traverse(TIntermTraverser* it)
+{
+	it->visitConstantUnion(this);
+}
+
+//
+// Traverse a binary node.
+//
+void TIntermBinary::traverse(TIntermTraverser* it)
+{
+	bool visit = true;
+
+	//
+	// visit the node before children if pre-visiting.
+	//
+	if(it->preVisit)
+	{
+		visit = it->visitBinary(PreVisit, this);
+	}
+	
+	//
+	// Visit the children, in the right order.
+	//
+	if(visit)
+	{
+		it->incrementDepth();
+
+		if(it->rightToLeft) 
+		{
+			if(right)
+			{
+				right->traverse(it);
+			}
+			
+			if(it->inVisit)
+			{
+				visit = it->visitBinary(InVisit, this);
+			}
+
+			if(visit && left)
+			{
+				left->traverse(it);
+			}
+		}
+		else
+		{
+			if(left)
+			{
+				left->traverse(it);
+			}
+			
+			if(it->inVisit)
+			{
+				visit = it->visitBinary(InVisit, this);
+			}
+
+			if(visit && right)
+			{
+				right->traverse(it);
+			}
+		}
+
+		it->decrementDepth();
+	}
+
+	//
+	// Visit the node after the children, if requested and the traversal
+	// hasn't been cancelled yet.
+	//
+	if(visit && it->postVisit)
+	{
+		it->visitBinary(PostVisit, this);
+	}
+}
+
+//
+// Traverse a unary node.  Same comments in binary node apply here.
+//
+void TIntermUnary::traverse(TIntermTraverser* it)
+{
+	bool visit = true;
+
+	if (it->preVisit)
+		visit = it->visitUnary(PreVisit, this);
+
+	if (visit) {
+		it->incrementDepth();
+		operand->traverse(it);
+		it->decrementDepth();
+	}
+	
+	if (visit && it->postVisit)
+		it->visitUnary(PostVisit, this);
+}
+
+//
+// Traverse an aggregate node.  Same comments in binary node apply here.
+//
+void TIntermAggregate::traverse(TIntermTraverser* it)
+{
+	bool visit = true;
+	
+	if(it->preVisit)
+	{
+		visit = it->visitAggregate(PreVisit, this);
+	}
+	
+	if(visit)
+	{
+		it->incrementDepth();
+
+		if(it->rightToLeft)
+		{
+			for(TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++)
+			{
+				(*sit)->traverse(it);
+
+				if(visit && it->inVisit)
+				{
+					if(*sit != sequence.front())
+					{
+						visit = it->visitAggregate(InVisit, this);
+					}
+				}
+			}
+		}
+		else
+		{
+			for(TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
+			{
+				(*sit)->traverse(it);
+
+				if(visit && it->inVisit)
+				{
+					if(*sit != sequence.back())
+					{
+						visit = it->visitAggregate(InVisit, this);
+					}
+				}
+			}
+		}
+		
+		it->decrementDepth();
+	}
+
+	if(visit && it->postVisit)
+	{
+		it->visitAggregate(PostVisit, this);
+	}
+}
+
+//
+// Traverse a selection node.  Same comments in binary node apply here.
+//
+void TIntermSelection::traverse(TIntermTraverser* it)
+{
+	bool visit = true;
+
+	if (it->preVisit)
+		visit = it->visitSelection(PreVisit, this);
+	
+	if (visit) {
+		it->incrementDepth();
+		if (it->rightToLeft) {
+			if (falseBlock)
+				falseBlock->traverse(it);
+			if (trueBlock)
+				trueBlock->traverse(it);
+			condition->traverse(it);
+		} else {
+			condition->traverse(it);
+			if (trueBlock)
+				trueBlock->traverse(it);
+			if (falseBlock)
+				falseBlock->traverse(it);
+		}
+		it->decrementDepth();
+	}
+
+	if (visit && it->postVisit)
+		it->visitSelection(PostVisit, this);
+}
+
+//
+// Traverse a loop node.  Same comments in binary node apply here.
+//
+void TIntermLoop::traverse(TIntermTraverser* it)
+{
+	bool visit = true;
+
+	if(it->preVisit)
+	{
+		visit = it->visitLoop(PreVisit, this);
+	}
+	
+	if(visit)
+	{
+		it->incrementDepth();
+
+		if(it->rightToLeft)
+		{
+			if(terminal)
+			{
+				terminal->traverse(it);
+			}
+
+			if(body)
+			{
+				body->traverse(it);
+			}
+
+			if(test)
+			{
+				test->traverse(it);
+			}
+		}
+		else
+		{
+			if(test)
+			{
+				test->traverse(it);
+			}
+
+			if(body)
+			{
+				body->traverse(it);
+			}
+
+			if(terminal)
+			{
+				terminal->traverse(it);
+			}
+		}
+
+		it->decrementDepth();
+	}
+
+	if(visit && it->postVisit)
+	{
+		it->visitLoop(PostVisit, this);
+	}
+}
+
+//
+// Traverse a branch node.  Same comments in binary node apply here.
+//
+void TIntermBranch::traverse(TIntermTraverser* it)
+{
+	bool visit = true;
+
+	if (it->preVisit)
+		visit = it->visitBranch(PreVisit, this);
+	
+	if (visit && expression) {
+		it->incrementDepth();
+		expression->traverse(it);
+		it->decrementDepth();
+	}
+
+	if (visit && it->postVisit)
+		it->visitBranch(PostVisit, this);
+}
+
diff --git a/Compiler/Intermediate.cpp b/Compiler/Intermediate.cpp
new file mode 100644
index 0000000..54fa796
--- /dev/null
+++ b/Compiler/Intermediate.cpp
@@ -0,0 +1,1483 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Build the intermediate representation.
+//
+
+#include "localintermediate.h"
+#include "QualifierAlive.h"
+#include "RemoveTree.h"
+#include <float.h>
+
+bool CompareStructure(const TType& leftNodeType, constUnion* rightUnionArray, constUnion* leftUnionArray);
+
+////////////////////////////////////////////////////////////////////////////
+//
+// First set of functions are to help build the intermediate representation.
+// These functions are not member functions of the nodes.
+// They are called from parser productions.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+//
+// Add a terminal node for an identifier in an expression.
+//
+// Returns the added node.
+//
+TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
+{
+	TIntermSymbol* node = new TIntermSymbol(id, name, type);
+	node->setLine(line);
+
+	return node;
+}
+
+//
+// Connect two nodes with a new parent that does a binary operation on the nodes.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable)
+{
+	switch (op) {
+	case EOpLessThan:
+	case EOpGreaterThan:
+	case EOpLessThanEqual:
+	case EOpGreaterThanEqual:
+		if (left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector() || left->getType().getBasicType() == EbtStruct) {
+			return 0;
+		}
+		break;
+	case EOpLogicalOr:
+	case EOpLogicalXor:
+	case EOpLogicalAnd:
+		if (left->getType().getBasicType() != EbtBool || left->getType().isMatrix() || left->getType().isArray() || left->getType().isVector()) {
+			return 0;
+		}
+		break;
+	case EOpAdd:
+	case EOpSub:
+	case EOpDiv:
+	case EOpMul:
+		if (left->getType().getBasicType() == EbtStruct || left->getType().getBasicType() == EbtBool)
+			return 0;
+	default: break;
+	}
+
+	//
+	// First try converting the children to compatible types.
+	//
+
+	if (!(left->getType().getStruct() && right->getType().getStruct())) {
+		TIntermTyped* child = addConversion(op, left->getType(), right);
+		if (child)
+			right = child;
+		else {
+			child = addConversion(op, right->getType(), left);
+			if (child)
+				left = child;
+			else
+				return 0;
+		}
+	} else {
+		if (left->getType() != right->getType())
+			return 0;
+	}
+
+
+	//
+	// Need a new node holding things together then.  Make
+	// one and promote it to the right type.
+	//
+	TIntermBinary* node = new TIntermBinary(op);
+	if (line == 0)
+		line = right->getLine();
+	node->setLine(line);
+
+	node->setLeft(left);
+	node->setRight(right);
+	if (! node->promote(infoSink))
+		return 0;
+
+	TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
+	TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
+
+	if (leftTempConstant)
+		leftTempConstant = left->getAsConstantUnion();
+
+	if (rightTempConstant)
+		rightTempConstant = right->getAsConstantUnion();
+
+	//
+	// See if we can fold constants.
+	//
+
+	TIntermTyped* typedReturnNode = 0;
+	if ( leftTempConstant && rightTempConstant) {
+		typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
+
+		if (typedReturnNode)
+			return typedReturnNode;
+	}
+
+	return node;
+}
+
+//
+// Connect two nodes through an assignment.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
+{
+	//
+	// Like adding binary math, except the conversion can only go
+	// from right to left.
+	//
+	TIntermBinary* node = new TIntermBinary(op);
+	if (line == 0)
+		line = left->getLine();
+	node->setLine(line);
+
+	TIntermTyped* child = addConversion(op, left->getType(), right);
+	if (child == 0)
+		return 0;
+
+	node->setLeft(left);
+	node->setRight(child);
+	if (! node->promote(infoSink))
+		return 0;
+
+	return node;
+}
+
+//
+// Connect two nodes through an index operator, where the left node is the base
+// of an array or struct, and the right node is a direct or indirect offset.
+//
+// Returns the added node.
+// The caller should set the type of the returned node.
+//
+TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
+{
+	TIntermBinary* node = new TIntermBinary(op);
+	if (line == 0)
+		line = index->getLine();
+	node->setLine(line);
+	node->setLeft(base);
+	node->setRight(index);
+
+	// caller should set the type
+
+	return node;
+}
+
+//
+// Add one node as the parent of another that it operates on.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
+{
+	TIntermUnary* node;
+	TIntermTyped* child = childNode->getAsTyped();
+
+	if (child == 0) {
+		infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
+		return 0;
+	}
+
+	switch (op) {
+	case EOpLogicalNot:
+		if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
+			return 0;
+		}
+		break;
+
+	case EOpPostIncrement:
+	case EOpPreIncrement:
+	case EOpPostDecrement:
+	case EOpPreDecrement:
+	case EOpNegative:
+		if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
+			return 0;
+	default: break;
+	}
+
+	//
+	// Do we need to promote the operand?
+	//
+	// Note: Implicit promotions were removed from the language.
+	//
+	TBasicType newType = EbtVoid;
+	switch (op) {
+	case EOpConstructInt:   newType = EbtInt;   break;
+	case EOpConstructBool:  newType = EbtBool;  break;
+	case EOpConstructFloat: newType = EbtFloat; break;
+	default: break;
+	}
+
+	if (newType != EbtVoid) {
+		child = addConversion(op, TType(newType, EvqTemporary, child->getNominalSize(),
+															   child->isMatrix(),
+															   child->isArray()),
+							  child);
+		if (child == 0)
+			return 0;
+	}
+
+	//
+	// For constructors, we are now done, it's all in the conversion.
+	//
+	switch (op) {
+	case EOpConstructInt:
+	case EOpConstructBool:
+	case EOpConstructFloat:
+		return child;
+	default: break;
+	}
+
+	TIntermConstantUnion *childTempConstant = 0;
+	if (child->getAsConstantUnion())
+		childTempConstant = child->getAsConstantUnion();
+
+	//
+	// Make a new node for the operator.
+	//
+	node = new TIntermUnary(op);
+	if (line == 0)
+		line = child->getLine();
+	node->setLine(line);
+	node->setOperand(child);
+
+	if (! node->promote(infoSink))
+		return 0;
+
+	if (childTempConstant)  {
+		TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
+
+		if (newChild)
+			return newChild;
+	}
+
+	return node;
+}
+
+//
+// This is the safe way to change the operator on an aggregate, as it
+// does lots of error checking and fixing.  Especially for establishing
+// a function call's operation on it's set of parameters.  Sequences
+// of instructions are also aggregates, but they just direnctly set
+// their operator to EOpSequence.
+//
+// Returns an aggregate node, which could be the one passed in if
+// it was already an aggregate.
+//
+TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line)
+{
+	TIntermAggregate* aggNode;
+
+	//
+	// Make sure we have an aggregate.  If not turn it into one.
+	//
+	if (node) {
+		aggNode = node->getAsAggregate();
+		if (aggNode == 0 || aggNode->getOp() != EOpNull) {
+			//
+			// Make an aggregate containing this node.
+			//
+			aggNode = new TIntermAggregate();
+			aggNode->getSequence().push_back(node);
+			if (line == 0)
+				line = node->getLine();
+		}
+	} else
+		aggNode = new TIntermAggregate();
+
+	//
+	// Set the operator.
+	//
+	aggNode->setOperator(op);
+	if (line != 0)
+		aggNode->setLine(line);
+
+	return aggNode;
+}
+
+//
+// Convert one type to another.
+//
+// Returns the node representing the conversion, which could be the same
+// node passed in if no conversion was needed.
+//
+// Return 0 if a conversion can't be done.
+//
+TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
+{
+	//
+	// Does the base type allow operation?
+	//
+	switch (node->getBasicType()) {
+	case EbtVoid:
+	case EbtSampler2D:
+	case EbtSamplerCube:
+		return 0;
+	default: break;
+	}
+
+	//
+	// Otherwise, if types are identical, no problem
+	//
+	if (type == node->getType())
+		return node;
+
+	//
+	// If one's a structure, then no conversions.
+	//
+	if (type.getStruct() || node->getType().getStruct())
+		return 0;
+
+	//
+	// If one's an array, then no conversions.
+	//
+	if (type.isArray() || node->getType().isArray())
+		return 0;
+
+	TBasicType promoteTo;
+
+	switch (op) {
+	//
+	// Explicit conversions
+	//
+	case EOpConstructBool:
+		promoteTo = EbtBool;
+		break;
+	case EOpConstructFloat:
+		promoteTo = EbtFloat;
+		break;
+	case EOpConstructInt:
+		promoteTo = EbtInt;
+		break;
+	default:
+		//
+		// implicit conversions were removed from the language.
+		//
+		if (type.getBasicType() != node->getType().getBasicType())
+			return 0;
+		//
+		// Size and structure could still differ, but that's
+		// handled by operator promotion.
+		//
+		return node;
+	}
+
+	if (node->getAsConstantUnion()) {
+
+		return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
+	} else {
+
+		//
+		// Add a new newNode for the conversion.
+		//
+		TIntermUnary* newNode = 0;
+
+		TOperator newOp = EOpNull;
+		switch (promoteTo) {
+		case EbtFloat:
+			switch (node->getBasicType()) {
+			case EbtInt:   newOp = EOpConvIntToFloat;  break;
+			case EbtBool:  newOp = EOpConvBoolToFloat; break;
+			default:
+				infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+				return 0;
+			}
+			break;
+		case EbtBool:
+			switch (node->getBasicType()) {
+			case EbtInt:   newOp = EOpConvIntToBool;   break;
+			case EbtFloat: newOp = EOpConvFloatToBool; break;
+			default:
+				infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+				return 0;
+			}
+			break;
+		case EbtInt:
+			switch (node->getBasicType()) {
+			case EbtBool:   newOp = EOpConvBoolToInt;  break;
+			case EbtFloat:  newOp = EOpConvFloatToInt; break;
+			default:
+				infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
+				return 0;
+			}
+			break;
+		default:
+			infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine());
+			return 0;
+		}
+
+		TType type(promoteTo, EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
+		newNode = new TIntermUnary(newOp, type);
+		newNode->setLine(node->getLine());
+		newNode->setOperand(node);
+
+		return newNode;
+	}
+}
+
+//
+// Safe way to combine two nodes into an aggregate.  Works with null pointers,
+// a node that's not a aggregate yet, etc.
+//
+// Returns the resulting aggregate, unless 0 was passed in for
+// both existing nodes.
+//
+TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
+{
+	if (left == 0 && right == 0)
+		return 0;
+
+	TIntermAggregate* aggNode = 0;
+	if (left)
+		aggNode = left->getAsAggregate();
+	if (!aggNode || aggNode->getOp() != EOpNull) {
+		aggNode = new TIntermAggregate;
+		if (left)
+			aggNode->getSequence().push_back(left);
+	}
+
+	if (right)
+		aggNode->getSequence().push_back(right);
+
+	if (line != 0)
+		aggNode->setLine(line);
+
+	return aggNode;
+}
+
+//
+// Turn an existing node into an aggregate.
+//
+// Returns an aggregate, unless 0 was passed in for the existing node.
+//
+TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
+{
+	if (node == 0)
+		return 0;
+
+	TIntermAggregate* aggNode = new TIntermAggregate;
+	aggNode->getSequence().push_back(node);
+
+	if (line != 0)
+		aggNode->setLine(line);
+	else
+		aggNode->setLine(node->getLine());
+
+	return aggNode;
+}
+
+//
+// For "if" test nodes.  There are three children; a condition,
+// a true path, and a false path.  The two paths are in the
+// nodePair.
+//
+// Returns the selection node created.
+//
+TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line)
+{
+	//
+	// For compile time constant selections, prune the code and
+	// test now.
+	//
+
+	if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
+		if (cond->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
+			return nodePair.node1;
+		else
+			return nodePair.node2;
+	}
+
+	TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
+	node->setLine(line);
+
+	return node;
+}
+
+
+TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
+{
+	if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
+		return right;
+	} else {
+		TIntermTyped *commaAggregate = growAggregate(left, right, line);
+		commaAggregate->getAsAggregate()->setOperator(EOpComma);
+		commaAggregate->setType(right->getType());
+		commaAggregate->getTypePointer()->changeQualifier(EvqTemporary);
+		return commaAggregate;
+	}
+}
+
+//
+// For "?:" test nodes.  There are three children; a condition,
+// a true path, and a false path.  The two paths are specified
+// as separate parameters.
+//
+// Returns the selection node created, or 0 if one could not be.
+//
+TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
+{
+	//
+	// Get compatible types.
+	//
+	TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
+	if (child)
+		falseBlock = child;
+	else {
+		child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
+		if (child)
+			trueBlock = child;
+		else
+			return 0;
+	}
+
+	//
+	// See if all the operands are constant, then fold it otherwise not.
+	//
+
+	if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
+		if (cond->getAsConstantUnion()->getUnionArrayPointer()->getBConst())
+			return trueBlock;
+		else
+			return falseBlock;
+	}
+
+	//
+	// Make a selection node.
+	//
+	TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
+	node->setLine(line);
+
+	return node;
+}
+
+//
+// Constant terminal nodes.  Has a union that contains bool, float or int constants
+//
+// Returns the constant union node created.
+//
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(constUnion* unionArrayPointer, const TType& t, TSourceLoc line)
+{
+	TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
+	node->setLine(line);
+
+	return node;
+}
+
+TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
+{
+
+	TIntermAggregate* node = new TIntermAggregate(EOpSequence);
+
+	node->setLine(line);
+	TIntermConstantUnion* constIntNode;
+	TIntermSequence &sequenceVector = node->getSequence();
+	constUnion* unionArray;
+
+	for (int i = 0; i < fields.num; i++) {
+		unionArray = new constUnion[1];
+		unionArray->setIConst(fields.offsets[i]);
+		constIntNode = addConstantUnion(unionArray, TType(EbtInt, EvqConst), line);
+		sequenceVector.push_back(constIntNode);
+	}
+
+	return node;
+}
+
+//
+// Create loop nodes.
+//
+TIntermNode* TIntermediate::addLoop(TIntermNode *init, TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc line)
+{
+	TIntermNode* node = new TIntermLoop(init, body, test, terminal, testFirst);
+	node->setLine(line);
+
+	return node;
+}
+
+//
+// Add branches.
+//
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
+{
+	return addBranch(branchOp, 0, line);
+}
+
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
+{
+	TIntermBranch* node = new TIntermBranch(branchOp, expression);
+	node->setLine(line);
+
+	return node;
+}
+
+//
+// This is to be executed once the final root is put on top by the parsing
+// process.
+//
+bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language)
+{
+	if (root == 0)
+		return true;
+
+	//
+	// First, finish off the top level sequence, if any
+	//
+	TIntermAggregate* aggRoot = root->getAsAggregate();
+	if (aggRoot && aggRoot->getOp() == EOpNull)
+		aggRoot->setOperator(EOpSequence);
+
+	return true;
+}
+
+//
+// This deletes the tree.
+//
+void TIntermediate::remove(TIntermNode* root)
+{
+	if (root)
+		RemoveAllTreeNodes(root);
+}
+
+////////////////////////////////////////////////////////////////
+//
+// Member functions of the nodes used for building the tree.
+//
+////////////////////////////////////////////////////////////////
+
+//
+// Say whether or not an operation node changes the value of a variable.
+//
+// Returns true if state is modified.
+//
+bool TIntermOperator::modifiesState() const
+{
+	switch (op) {
+	case EOpPostIncrement:
+	case EOpPostDecrement:
+	case EOpPreIncrement:
+	case EOpPreDecrement:
+	case EOpAssign:
+	case EOpAddAssign:
+	case EOpSubAssign:
+	case EOpMulAssign:
+	case EOpVectorTimesMatrixAssign:
+	case EOpVectorTimesScalarAssign:
+	case EOpMatrixTimesScalarAssign:
+	case EOpMatrixTimesMatrixAssign:
+	case EOpDivAssign:
+	case EOpModAssign:
+	case EOpAndAssign:
+	case EOpInclusiveOrAssign:
+	case EOpExclusiveOrAssign:
+	case EOpLeftShiftAssign:
+	case EOpRightShiftAssign:
+		return true;
+	default:
+		return false;
+	}
+}
+
+//
+// returns true if the operator is for one of the constructors
+//
+bool TIntermOperator::isConstructor() const
+{
+	switch (op) {
+	case EOpConstructVec2:
+	case EOpConstructVec3:
+	case EOpConstructVec4:
+	case EOpConstructMat2:
+	case EOpConstructMat3:
+	case EOpConstructMat4:
+	case EOpConstructFloat:
+	case EOpConstructIVec2:
+	case EOpConstructIVec3:
+	case EOpConstructIVec4:
+	case EOpConstructInt:
+	case EOpConstructBVec2:
+	case EOpConstructBVec3:
+	case EOpConstructBVec4:
+	case EOpConstructBool:
+	case EOpConstructStruct:
+		return true;
+	default:
+		return false;
+	}
+}
+//
+// Make sure the type of a unary operator is appropriate for its
+// combination of operation and operand type.
+//
+// Returns false in nothing makes sense.
+//
+bool TIntermUnary::promote(TInfoSink&)
+{
+	switch (op) {
+	case EOpLogicalNot:
+		if (operand->getBasicType() != EbtBool)
+			return false;
+		break;
+	case EOpBitwiseNot:
+		if (operand->getBasicType() != EbtInt)
+			return false;
+		break;
+	case EOpNegative:
+	case EOpPostIncrement:
+	case EOpPostDecrement:
+	case EOpPreIncrement:
+	case EOpPreDecrement:
+		if (operand->getBasicType() == EbtBool)
+			return false;
+		break;
+
+	// operators for built-ins are already type checked against their prototype
+	case EOpAny:
+	case EOpAll:
+	case EOpVectorLogicalNot:
+		return true;
+
+	default:
+		if (operand->getBasicType() != EbtFloat)
+			return false;
+	}
+
+	setType(operand->getType());
+
+	return true;
+}
+
+//
+// Establishes the type of the resultant operation, as well as
+// makes the operator the correct one for the operands.
+//
+// Returns false if operator can't work on operands.
+//
+bool TIntermBinary::promote(TInfoSink& infoSink)
+{
+	int size = left->getNominalSize();
+	if (right->getNominalSize() > size)
+		size = right->getNominalSize();
+
+	TBasicType type = left->getBasicType();
+
+	//
+	// Arrays have to be exact matches.
+	//
+	if ((left->isArray() || right->isArray()) && (left->getType() != right->getType()))
+		return false;
+
+	//
+	// Base assumption:  just make the type the same as the left
+	// operand.  Then only deviations from this need be coded.
+	//
+	setType(TType(type, EvqTemporary, left->getNominalSize(), left->isMatrix()));
+
+	//
+	// Array operations.
+	//
+	if (left->isArray()) {
+
+		switch (op) {
+
+		//
+		// Promote to conditional
+		//
+		case EOpEqual:
+		case EOpNotEqual:
+			setType(TType(EbtBool));
+			break;
+
+		//
+		// Set array information.
+		//
+		case EOpAssign:
+		case EOpInitialize:
+			getType().setArraySize(left->getType().getArraySize());
+			getType().setArrayInformationType(left->getType().getArrayInformationType());
+			break;
+
+		default:
+			return false;
+		}
+
+		return true;
+	}
+
+	//
+	// All scalars.  Code after this test assumes this case is removed!
+	//
+	if (size == 1) {
+
+		switch (op) {
+
+		//
+		// Promote to conditional
+		//
+		case EOpEqual:
+		case EOpNotEqual:
+		case EOpLessThan:
+		case EOpGreaterThan:
+		case EOpLessThanEqual:
+		case EOpGreaterThanEqual:
+			setType(TType(EbtBool));
+			break;
+
+		//
+		// And and Or operate on conditionals
+		//
+		case EOpLogicalAnd:
+		case EOpLogicalOr:
+			if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
+				return false;
+			setType(TType(EbtBool));
+			break;
+
+		//
+		// Check for integer only operands.
+		//
+		case EOpMod:
+		case EOpRightShift:
+		case EOpLeftShift:
+		case EOpAnd:
+		case EOpInclusiveOr:
+		case EOpExclusiveOr:
+			if (left->getBasicType() != EbtInt || right->getBasicType() != EbtInt)
+				return false;
+			break;
+		case EOpModAssign:
+		case EOpAndAssign:
+		case EOpInclusiveOrAssign:
+		case EOpExclusiveOrAssign:
+		case EOpLeftShiftAssign:
+		case EOpRightShiftAssign:
+			if (left->getBasicType() != EbtInt || right->getBasicType() != EbtInt)
+				return false;
+			// fall through
+
+		//
+		// Everything else should have matching types
+		//
+		default:
+			if (left->getBasicType() != right->getBasicType() ||
+				left->isMatrix()     != right->isMatrix())
+				return false;
+		}
+
+		return true;
+	}
+
+	//
+	// Are the sizes compatible?
+	//
+	if ( left->getNominalSize() != size &&  left->getNominalSize() != 1 ||
+		right->getNominalSize() != size && right->getNominalSize() != 1)
+		return false;
+
+	//
+	// Can these two operands be combined?
+	//
+	switch (op) {
+	case EOpMul:
+		if (!left->isMatrix() && right->isMatrix()) {
+			if (left->isVector())
+				op = EOpVectorTimesMatrix;
+			else {
+				op = EOpMatrixTimesScalar;
+				setType(TType(type, EvqTemporary, size, true));
+			}
+		} else if (left->isMatrix() && !right->isMatrix()) {
+			if (right->isVector()) {
+				op = EOpMatrixTimesVector;
+				setType(TType(type, EvqTemporary, size, false));
+			} else {
+				op = EOpMatrixTimesScalar;
+			}
+		} else if (left->isMatrix() && right->isMatrix()) {
+			op = EOpMatrixTimesMatrix;
+		} else if (!left->isMatrix() && !right->isMatrix()) {
+			if (left->isVector() && right->isVector()) {
+				// leave as component product
+			} else if (left->isVector() || right->isVector()) {
+				op = EOpVectorTimesScalar;
+				setType(TType(type, EvqTemporary, size, false));
+			}
+		} else {
+			infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
+			return false;
+		}
+		break;
+	case EOpMulAssign:
+		if (!left->isMatrix() && right->isMatrix()) {
+			if (left->isVector())
+				op = EOpVectorTimesMatrixAssign;
+			else {
+				return false;
+			}
+		} else if (left->isMatrix() && !right->isMatrix()) {
+			if (right->isVector()) {
+				return false;
+			} else {
+				op = EOpMatrixTimesScalarAssign;
+			}
+		} else if (left->isMatrix() && right->isMatrix()) {
+			op = EOpMatrixTimesMatrixAssign;
+		} else if (!left->isMatrix() && !right->isMatrix()) {
+			if (left->isVector() && right->isVector()) {
+				// leave as component product
+			} else if (left->isVector() || right->isVector()) {
+				if (! left->isVector())
+					return false;
+				op = EOpVectorTimesScalarAssign;
+				setType(TType(type, EvqTemporary, size, false));
+			}
+		} else {
+			infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
+			return false;
+		}
+		break;
+	case EOpAssign:
+	case EOpInitialize:
+		if (left->getNominalSize() != right->getNominalSize())
+			return false;
+		// fall through
+	case EOpAdd:
+	case EOpSub:
+	case EOpDiv:
+	case EOpMod:
+	case EOpAddAssign:
+	case EOpSubAssign:
+	case EOpDivAssign:
+	case EOpModAssign:
+		if (left->isMatrix() && right->isVector() ||
+			left->isVector() && right->isMatrix() ||
+			left->getBasicType() != right->getBasicType())
+			return false;
+		setType(TType(type, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
+		break;
+
+	case EOpEqual:
+	case EOpNotEqual:
+	case EOpLessThan:
+	case EOpGreaterThan:
+	case EOpLessThanEqual:
+	case EOpGreaterThanEqual:
+		if (left->isMatrix() && right->isVector() ||
+			left->isVector() && right->isMatrix() ||
+			left->getBasicType() != right->getBasicType())
+			return false;
+		setType(TType(EbtBool));
+		break;
+
+default:
+		return false;
+	}
+
+	//
+	// One more check for assignment.  The Resulting type has to match the left operand.
+	//
+	switch (op) {
+	case EOpAssign:
+	case EOpInitialize:
+	case EOpAddAssign:
+	case EOpSubAssign:
+	case EOpMulAssign:
+	case EOpDivAssign:
+	case EOpModAssign:
+	case EOpAndAssign:
+	case EOpInclusiveOrAssign:
+	case EOpExclusiveOrAssign:
+	case EOpLeftShiftAssign:
+	case EOpRightShiftAssign:
+		if (getType() != left->getType())
+			return false;
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
+bool CompareStruct(const TType& leftNodeType, constUnion* rightUnionArray, constUnion* leftUnionArray)
+{
+	TTypeList* fields = leftNodeType.getStruct();
+
+	size_t structSize = fields->size();
+	int index = 0;
+
+	for (size_t j = 0; j < structSize; j++) {
+		int size = (*fields)[j].type->getObjectSize();
+		for (int i = 0; i < size; i++) {
+			if ((*fields)[j].type->getBasicType() == EbtStruct) {
+				if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index]))
+					return false;
+			} else {
+				if (leftUnionArray[index] != rightUnionArray[index])
+					return false;
+				index++;
+			}
+
+		}
+	}
+	return true;
+}
+
+bool CompareStructure(const TType& leftNodeType, constUnion* rightUnionArray, constUnion* leftUnionArray)
+{
+	if (leftNodeType.isArray()) {
+		TType typeWithoutArrayness = leftNodeType;
+		typeWithoutArrayness.clearArrayness();
+
+		int arraySize = leftNodeType.getArraySize();
+
+		for (int i = 0; i < arraySize; ++i) {
+			int offset = typeWithoutArrayness.getObjectSize() * i;
+			if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
+				return false;
+		}
+	} else
+		return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
+
+	return true;
+}
+
+//
+// The fold functions see if an operation on a constant can be done in place,
+// without generating run-time code.
+//
+// Returns the node to keep using, which may or may not be the node passed in.
+//
+
+TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
+{
+	constUnion *unionArray = getUnionArrayPointer();
+	int objectSize = getType().getObjectSize();
+
+	if (constantNode) {  // binary operations
+		TIntermConstantUnion *node = constantNode->getAsConstantUnion();
+		constUnion *rightUnionArray = node->getUnionArrayPointer();
+		TType returnType = getType();
+
+		// for a case like float f = 1.2 + vec4(2,3,4,5);
+		if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
+			rightUnionArray = new constUnion[objectSize];
+			for (int i = 0; i < objectSize; ++i)
+				rightUnionArray[i] = *node->getUnionArrayPointer();
+			returnType = getType();
+		} else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
+			// for a case like float f = vec4(2,3,4,5) + 1.2;
+			unionArray = new constUnion[constantNode->getType().getObjectSize()];
+			for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
+				unionArray[i] = *getUnionArrayPointer();
+			returnType = node->getType();
+			objectSize = constantNode->getType().getObjectSize();
+		}
+
+		constUnion* tempConstArray = 0;
+		TIntermConstantUnion *tempNode;
+
+		bool boolNodeFlag = false;
+		switch(op) {
+		case EOpAdd:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] + rightUnionArray[i];
+			}
+			break;
+		case EOpSub:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] - rightUnionArray[i];
+			}
+			break;
+
+		case EOpMul:
+		case EOpVectorTimesScalar:
+		case EOpMatrixTimesScalar:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] * rightUnionArray[i];
+			}
+			break;
+		case EOpMatrixTimesMatrix:
+			if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
+				infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
+				return 0;
+			}
+			{// support MSVC++6.0
+				int size = getNominalSize();
+				tempConstArray = new constUnion[size*size];
+				for (int row = 0; row < size; row++) {
+					for (int column = 0; column < size; column++) {
+						tempConstArray[size * column + row].setFConst(0.0f);
+						for (int i = 0; i < size; i++) {
+							tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
+						}
+					}
+				}
+			}
+			break;
+		case EOpDiv:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++) {
+					switch (getType().getBasicType()) {
+					case EbtFloat:
+						if (rightUnionArray[i] == 0.0f) {
+							infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
+							tempConstArray[i].setFConst(FLT_MAX);
+						} else
+							tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
+					break;
+
+					case EbtInt:
+						if (rightUnionArray[i] == 0) {
+							infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
+							tempConstArray[i].setIConst(INT_MAX);
+						} else
+							tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
+						break;
+					default:
+						infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
+						return 0;
+					}
+				}
+			}
+			break;
+
+		case EOpMatrixTimesVector:
+			if (node->getBasicType() != EbtFloat) {
+				infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
+				return 0;
+			}
+			tempConstArray = new constUnion[getNominalSize()];
+
+			{// support MSVC++6.0
+				for (int size = getNominalSize(), i = 0; i < size; i++) {
+					tempConstArray[i].setFConst(0.0f);
+					for (int j = 0; j < size; j++) {
+						tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
+					}
+				}
+			}
+
+			tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
+			tempNode->setLine(getLine());
+
+			return tempNode;
+
+		case EOpVectorTimesMatrix:
+			if (getType().getBasicType() != EbtFloat) {
+				infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
+				return 0;
+			}
+
+			tempConstArray = new constUnion[getNominalSize()];
+			{// support MSVC++6.0
+				for (int size = getNominalSize(), i = 0; i < size; i++) {
+					tempConstArray[i].setFConst(0.0f);
+					for (int j = 0; j < size; j++) {
+						tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
+					}
+				}
+			}
+			break;
+
+		case EOpMod:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] % rightUnionArray[i];
+			}
+			break;
+
+		case EOpRightShift:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
+			}
+			break;
+
+		case EOpLeftShift:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] << rightUnionArray[i];
+			}
+			break;
+
+		case EOpAnd:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] & rightUnionArray[i];
+			}
+			break;
+		case EOpInclusiveOr:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] | rightUnionArray[i];
+			}
+			break;
+		case EOpExclusiveOr:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
+			}
+			break;
+
+		case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] && rightUnionArray[i];
+			}
+			break;
+
+		case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					tempConstArray[i] = unionArray[i] || rightUnionArray[i];
+			}
+			break;
+
+		case EOpLogicalXor:
+			tempConstArray = new constUnion[objectSize];
+			{// support MSVC++6.0
+				for (int i = 0; i < objectSize; i++)
+					switch (getType().getBasicType()) {
+					case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
+					default: assert(false && "Default missing");
+					}
+			}
+			break;
+
+		case EOpLessThan:
+			assert(objectSize == 1);
+			tempConstArray = new constUnion[1];
+			tempConstArray->setBConst(*unionArray < *rightUnionArray);
+			returnType = TType(EbtBool, EvqConst);
+			break;
+		case EOpGreaterThan:
+			assert(objectSize == 1);
+			tempConstArray = new constUnion[1];
+			tempConstArray->setBConst(*unionArray > *rightUnionArray);
+			returnType = TType(EbtBool, EvqConst);
+			break;
+		case EOpLessThanEqual:
+		{
+			assert(objectSize == 1);
+			constUnion constant;
+			constant.setBConst(*unionArray > *rightUnionArray);
+			tempConstArray = new constUnion[1];
+			tempConstArray->setBConst(!constant.getBConst());
+			returnType = TType(EbtBool, EvqConst);
+			break;
+		}
+		case EOpGreaterThanEqual:
+		{
+			assert(objectSize == 1);
+			constUnion constant;
+			constant.setBConst(*unionArray < *rightUnionArray);
+			tempConstArray = new constUnion[1];
+			tempConstArray->setBConst(!constant.getBConst());
+			returnType = TType(EbtBool, EvqConst);
+			break;
+		}
+
+		case EOpEqual:
+			if (getType().getBasicType() == EbtStruct) {
+				if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
+					boolNodeFlag = true;
+			} else {
+				for (int i = 0; i < objectSize; i++) {
+					if (unionArray[i] != rightUnionArray[i]) {
+						boolNodeFlag = true;
+						break;  // break out of for loop
+					}
+				}
+			}
+
+			tempConstArray = new constUnion[1];
+			if (!boolNodeFlag) {
+				tempConstArray->setBConst(true);
+			}
+			else {
+				tempConstArray->setBConst(false);
+			}
+
+			tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EvqConst));
+			tempNode->setLine(getLine());
+
+			return tempNode;
+
+		case EOpNotEqual:
+			if (getType().getBasicType() == EbtStruct) {
+				if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
+					boolNodeFlag = true;
+			} else {
+				for (int i = 0; i < objectSize; i++) {
+					if (unionArray[i] == rightUnionArray[i]) {
+						boolNodeFlag = true;
+						break;  // break out of for loop
+					}
+				}
+			}
+
+			tempConstArray = new constUnion[1];
+			if (!boolNodeFlag) {
+				tempConstArray->setBConst(true);
+			}
+			else {
+				tempConstArray->setBConst(false);
+			}
+
+			tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EvqConst));
+			tempNode->setLine(getLine());
+
+			return tempNode;
+
+		default:
+			infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
+			return 0;
+		}
+		tempNode = new TIntermConstantUnion(tempConstArray, returnType);
+		tempNode->setLine(getLine());
+
+		return tempNode;
+	} else {
+		//
+		// Do unary operations
+		//
+		TIntermConstantUnion *newNode = 0;
+		constUnion* tempConstArray = new constUnion[objectSize];
+		for (int i = 0; i < objectSize; i++) {
+			switch(op) {
+			case EOpNegative:
+				switch (getType().getBasicType()) {
+				case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
+				case EbtInt:   tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
+				default:
+					infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
+					return 0;
+				}
+				break;
+			case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
+				switch (getType().getBasicType()) {
+				case EbtBool:  tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
+				default:
+					infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
+					return 0;
+				}
+				break;
+			default:
+				return 0;
+			}
+		}
+		newNode = new TIntermConstantUnion(tempConstArray, getType());
+		newNode->setLine(getLine());
+		return newNode;
+	}
+
+	return this;
+}
+
+TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
+{
+	constUnion *rightUnionArray = node->getUnionArrayPointer();
+	int size = node->getType().getObjectSize();
+
+	constUnion *leftUnionArray = new constUnion[size];
+
+	for (int i=0; i < size; i++) {
+
+		switch (promoteTo) {
+		case EbtFloat:
+			switch (node->getType().getBasicType()) {
+			case EbtInt:
+				leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getIConst()));
+				break;
+			case EbtBool:
+				leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getBConst()));
+				break;
+			case EbtFloat:
+				leftUnionArray[i] = rightUnionArray[i];
+				break;
+			default:
+				infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+				return 0;
+			}
+			break;
+		case EbtInt:
+			switch (node->getType().getBasicType()) {
+			case EbtInt:
+				leftUnionArray[i] = rightUnionArray[i];
+				break;
+			case EbtBool:
+				leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getBConst()));
+				break;
+			case EbtFloat:
+				leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getFConst()));
+				break;
+			default:
+				infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+				return 0;
+			}
+			break;
+		case EbtBool:
+			switch (node->getType().getBasicType()) {
+			case EbtInt:
+				leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0);
+				break;
+			case EbtBool:
+				leftUnionArray[i] = rightUnionArray[i];
+				break;
+			case EbtFloat:
+				leftUnionArray[i].setBConst(rightUnionArray[i].getFConst() != 0.0f);
+				break;
+			default:
+				infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
+				return 0;
+			}
+
+			break;
+		default:
+			infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
+			return 0;
+		}
+
+	}
+
+	const TType& t = node->getType();
+
+	return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
+}
+
+void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
+{
+	assert(!pragmaTable);
+	pragmaTable = new TPragmaTable();
+	*pragmaTable = pTable;
+}
+
diff --git a/Compiler/Link.cpp b/Compiler/Link.cpp
new file mode 100644
index 0000000..9f5819b
--- /dev/null
+++ b/Compiler/Link.cpp
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// The top level algorithms for linking multiple
+// shaders together.
+//
+#include "Common.h"
+#include "ShHandle.h"
+
+//
+// Actual link object, derived from the shader handle base classes.
+//
+class TGenericLinker : public TLinker {
+public:
+    TGenericLinker(EShExecutable e, int dOptions) : TLinker(e, infoSink), debugOptions(dOptions) { }
+    bool link(TCompilerList&, TUniformMap*) { return true; }
+	void getAttributeBindings(ShBindingTable const **t) const { }
+    TInfoSink infoSink;
+    int debugOptions;
+};
+
+//
+// The internal view of a uniform/float object exchanged with the driver.
+//
+class TUniformLinkedMap : public TUniformMap {
+public:
+    TUniformLinkedMap() { }
+    virtual int getLocation(const char* name) { return 0; }
+};
+
+TShHandleBase* ConstructLinker(EShExecutable executable, int debugOptions)
+{
+    return new TGenericLinker(executable, debugOptions);
+}
+
+void DeleteLinker(TShHandleBase* linker)
+{
+    delete linker;
+}
+
+TUniformMap* ConstructUniformMap()
+{
+    return new TUniformLinkedMap();
+}
+
+void DeleteUniformMap(TUniformMap* map)
+{
+    delete map;
+}
+
+TShHandleBase* ConstructBindings()
+{
+    return 0;
+}
+
+void DeleteBindingList(TShHandleBase* bindingList)
+{
+    delete bindingList;
+}
diff --git a/Compiler/MMap.h b/Compiler/MMap.h
new file mode 100644
index 0000000..a308671
--- /dev/null
+++ b/Compiler/MMap.h
@@ -0,0 +1,56 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _MMAP_INCLUDED_
+#define _MMAP_INCLUDED_
+
+//
+// Encapsulate memory mapped files
+//
+
+class TMMap {
+public:
+    TMMap(const char* fileName) : 
+        fSize(-1), // -1 is the error value returned by GetFileSize()
+        fp(NULL),
+        fBuff(0)   // 0 is the error value returned by MapViewOfFile()
+    {
+        if ((fp = fopen(fileName, "r")) == NULL)
+            return;
+        char c = getc(fp);
+        fSize = 0;
+        while (c != EOF) {
+            fSize++;
+            c = getc(fp);
+        }
+        if (c == EOF)
+            fSize++;
+        rewind(fp);
+        fBuff = (char*)malloc(sizeof(char) * fSize);
+        int count = 0;
+        c = getc(fp);
+        while (c != EOF) {
+            fBuff[count++] = c;
+            c = getc(fp);
+        }
+        fBuff[count++] = c;
+    }
+
+    char* getData() { return fBuff; }
+    int   getSize() { return fSize; }
+
+    ~TMMap() {
+        if (fp != NULL)
+            fclose(fp);
+    }
+    
+private:
+    int             fSize;      // size of file to map in
+    FILE *fp;
+    char*           fBuff;      // the actual data;
+};
+
+#endif // _MMAP_INCLUDED_
diff --git a/Compiler/OutputHLSL.cpp b/Compiler/OutputHLSL.cpp
new file mode 100644
index 0000000..eaa1589
--- /dev/null
+++ b/Compiler/OutputHLSL.cpp
@@ -0,0 +1,1184 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "OutputHLSL.h"
+
+#include "InfoSink.h"
+#include "debug.h"
+
+namespace sh
+{
+OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, true), context(context)
+{
+}
+
+void OutputHLSL::header()
+{
+    EShLanguage language = context.language;
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    if (language == EShLangFragment)
+    {
+        TString uniforms;
+        TString varyingInput;
+        TString varyingGlobals;
+
+        TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
+        int semanticIndex = 0;
+
+        for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
+        {
+            const TSymbol *symbol = (*namedSymbol).second;
+            const TString &name = symbol->getName();
+
+            if (symbol->isVariable())
+            {
+                const TVariable *variable = static_cast<const TVariable*>(symbol);
+                const TType &type = variable->getType();
+                TQualifier qualifier = type.getQualifier();
+
+                if (qualifier == EvqUniform)
+                {
+                    uniforms += "uniform " + typeString(type) + " " + name + arrayString(type) + ";\n";
+                }
+                else if (qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
+                {
+                    char semantic[100];
+                    sprintf(semantic, " : TEXCOORD%d", semanticIndex);
+                    semanticIndex += type.isArray() ? type.getArraySize() : 1;
+
+                    varyingInput += "    " + typeString(type) + " " + name + arrayString(type) + semantic + ";\n";
+                    varyingGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n";
+                }
+            }
+        }
+
+        out <<  uniforms;
+        out << "\n";
+        out << "struct PS_INPUT\n"   // FIXME: Prevent name clashes
+               "{\n";
+        out <<        varyingInput;
+        out << "};\n"
+               "\n";
+        out <<    varyingGlobals;
+        out << "\n"
+               "struct PS_OUTPUT\n"   // FIXME: Prevent name clashes
+               "{\n"
+               "    float4 gl_Color[1] : COLOR;\n"
+               "};\n"
+               "\n"
+               "static float4 gl_Color[1] = {float4(0, 0, 0, 0)};\n"
+               "\n"
+               "float4 gl_texture2D(sampler2D s, float2 t)\n"
+               "{\n"
+               "    return tex2D(s, t);\n"
+               "}\n"
+               "\n"
+               "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
+               "{\n"
+               "    return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n"
+               "}\n"
+               "float4 gl_texture2DBias(sampler2D s, float2 t, float bias)\n"
+               "{\n"
+               "    return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n"
+               "}\n"
+               "\n"
+               "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
+               "{\n"
+               "    return texCUBE(s, t);\n"
+               "}\n"
+               "\n";
+    }
+    else
+    {
+        TString uniforms;
+        TString attributeInput;
+        TString attributeGlobals;
+        TString varyingOutput;
+        TString varyingGlobals;
+        TString globals;
+
+        TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
+        int semanticIndex = 0;
+
+        for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
+        {
+            const TSymbol *symbol = (*namedSymbol).second;
+            const TString &name = symbol->getName();
+
+            if (symbol->isVariable())
+            {
+                const TVariable *variable = static_cast<const TVariable*>(symbol);
+                const TType &type = variable->getType();
+                TQualifier qualifier = type.getQualifier();
+
+                if (qualifier == EvqUniform)
+                {
+                    uniforms += "uniform " + typeString(type) + " " + name + arrayString(type) + ";\n";
+                }
+                else if (qualifier == EvqAttribute)
+                {
+                    char semantic[100];
+                    sprintf(semantic, " : TEXCOORD%d", semanticIndex);
+                    semanticIndex += type.isArray() ? type.getArraySize() : 1;
+
+                    attributeInput += "    " + typeString(type) + " " + name + arrayString(type) + semantic + ";\n";
+                    attributeGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n";
+                }
+                else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut)
+                {
+                    varyingOutput += "    " + typeString(type) + " " + name + arrayString(type) + " : TEXCOORD0;\n";   // Actual semantic index assigned during link
+                    varyingGlobals += "static " + typeString(type) + " " + name + arrayString(type) + " = " + initializer(type) + ";\n";
+                }
+                else if (qualifier == EvqGlobal)
+                {
+                    globals += typeString(type) + " " + name + arrayString(type) + ";\n";
+                }
+                else UNREACHABLE();
+            }
+        }
+
+        out << "uniform float2 gl_HalfPixelSize;\n";
+        out << "\n";
+        out <<  uniforms;
+        out << "\n";
+        out <<  globals;
+        out << "\n";
+        out << "struct VS_INPUT\n"   // FIXME: Prevent name clashes
+               "{\n";
+        out <<        attributeInput;
+        out << "};\n"
+               "\n";
+        out <<  attributeGlobals;
+        out << "\n"
+               "struct VS_OUTPUT\n"   // FIXME: Prevent name clashes
+               "{\n"
+               "    float4 gl_Position : POSITION;\n"
+               "    float gl_PointSize : PSIZE;\n";
+        out <<        varyingOutput;
+        out << "};\n"
+               "\n"
+               "static float4 gl_Position = float4(0, 0, 0, 0);\n"
+               "static float gl_PointSize = float(0);\n";
+        out <<  varyingGlobals;
+        out << "\n";
+    }
+
+    out << "float vec1(float x)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return x;\n"
+           "}\n"
+           "\n"
+           "float vec1(float2 xy)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return xy[0];\n"
+           "}\n"
+           "\n"
+           "float vec1(float3 xyz)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return xyz[0];\n"
+           "}\n"
+           "\n"
+           "float vec1(float4 xyzw)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return xyzw[0];\n"
+           "}\n"
+           "\n"
+           "float2 vec2(float x)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float2(x, x);\n"
+           "}\n"
+           "\n"
+           "float2 vec2(float x, float y)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float2(x, y);\n"
+           "}\n"
+           "\n"
+           "float2 vec2(float2 xy)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return xy;\n"
+           "}\n"
+           "\n"
+           "float2 vec2(float3 xyz)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float2(xyz[0], xyz[1]);\n"
+           "}\n"
+           "\n"
+           "float2 vec2(float4 xyzw)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float2(xyzw[0], xyzw[1]);\n"
+           "}\n"
+           "\n"
+           "float3 vec3(float x)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float3(x, x, x);\n"
+           "}\n"
+           "\n"
+           "float3 vec3(float x, float y, float z)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float3(x, y, z);\n"
+           "}\n"
+           "\n"
+           "float3 vec3(float2 xy, float z)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float3(xy[0], xy[1], z);\n"
+           "}\n"
+           "\n"
+           "float3 vec3(float x, float2 yz)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float3(x, yz[0], yz[1]);\n"
+           "}\n"
+           "\n"
+           "float3 vec3(float3 xyz)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return xyz;\n"
+           "}\n"
+           "\n"
+           "float3 vec3(float4 xyzw)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float3(xyzw[0], xyzw[1], xyzw[2]);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float x)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(x, x, x, x);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float x, float y, float z, float w)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(x, y, z, w);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float2 xy, float z, float w)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(xy[0], xy[1], z, w);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float x, float2 yz, float w)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(x, yz[0], yz[1], w);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float x, float y, float2 zw)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(x, y, zw[0], zw[1]);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float2 xy, float2 zw)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(xy[0], xy[1], zw[0], zw[1]);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float3 xyz, float w)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(xyz[0], xyz[1], xyz[2], w);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float x, float3 yzw)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return float4(x, yzw[0], yzw[1], yzw[2]);\n"
+           "}\n"
+           "\n"
+           "float4 vec4(float4 xyzw)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return xyzw;\n"
+           "}\n"
+           "\n"
+           "bool xor(bool p, bool q)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return (p || q) && !(p && q);\n"
+           "}\n"
+           "\n"
+           "float mod(float x, float y)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return x - y * floor(x / y);\n"
+           "}\n"
+           "float2 mod(float2 x, float y)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return x - y * floor(x / y);\n"
+           "}\n"
+           "float3 mod(float3 x, float y)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return x - y * floor(x / y);\n"
+           "}\n"
+           "float4 mod(float4 x, float y)\n"   // FIXME: Prevent name clashes
+           "{\n"
+           "    return x - y * floor(x / y);\n"
+           "}\n"
+           "\n";
+}
+
+void OutputHLSL::visitSymbol(TIntermSymbol *node)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    TString name = node->getSymbol();
+
+    if (name == "gl_FragColor")
+    {
+        out << "gl_Color[0]";
+    }
+    else if (name == "gl_FragData")
+    {
+        out << "gl_Color";
+    }
+    else
+    {
+        out << name;
+    }
+}
+
+bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    switch (node->getOp())
+    {
+      case EOpAssign:                  outputTriplet(visit, "(", " = ", ")");       break;
+      case EOpInitialize:              outputTriplet(visit, NULL, " = ", NULL);     break;
+      case EOpAddAssign:               outputTriplet(visit, NULL, " += ", NULL);    break;
+      case EOpSubAssign:               outputTriplet(visit, NULL, " -= ", NULL);    break;
+      case EOpMulAssign:               outputTriplet(visit, NULL, " *= ", NULL);    break;
+      case EOpVectorTimesMatrixAssign: UNIMPLEMENTED(); /* FIXME */ out << "matrix mult second child into first child";  break;
+      case EOpVectorTimesScalarAssign: outputTriplet(visit, NULL, " *= ", NULL);    break;
+      case EOpMatrixTimesScalarAssign: UNIMPLEMENTED(); /* FIXME */ out << "matrix scale second child into first child"; break;
+      case EOpMatrixTimesMatrixAssign: UNIMPLEMENTED(); /* FIXME */ out << "matrix mult second child into first child"; break;
+      case EOpDivAssign:               outputTriplet(visit, NULL, " /= ", NULL);    break;
+      case EOpModAssign:               UNIMPLEMENTED(); /* FIXME */ out << "mod second child into first child";          break;
+      case EOpAndAssign:               UNIMPLEMENTED(); /* FIXME */ out << "and second child into first child";          break;
+      case EOpInclusiveOrAssign:       UNIMPLEMENTED(); /* FIXME */ out << "or second child into first child";           break;
+      case EOpExclusiveOrAssign:       UNIMPLEMENTED(); /* FIXME */ out << "exclusive or second child into first child"; break;
+      case EOpLeftShiftAssign:         UNIMPLEMENTED(); /* FIXME */ out << "left shift second child into first child";   break;
+      case EOpRightShiftAssign:        UNIMPLEMENTED(); /* FIXME */ out << "right shift second child into first child";  break;
+      case EOpIndexDirect:             outputTriplet(visit, NULL, "[", "]"); break;
+      case EOpIndexIndirect:           outputTriplet(visit, NULL, "[", "]"); break;
+      case EOpIndexDirectStruct:       UNIMPLEMENTED(); /* FIXME */ out << "direct index for structure";   break;
+      case EOpVectorSwizzle:
+        if (visit == InVisit)
+        {
+            out << ".";
+
+            TIntermAggregate *swizzle = node->getRight()->getAsAggregate();
+
+            if (swizzle)
+            {
+                TIntermSequence &sequence = swizzle->getSequence();
+
+                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
+                {
+                    TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
+
+                    if (element)
+                    {
+                        int i = element->getUnionArrayPointer()[0].getIConst();
+
+                        switch (i)
+                        {
+                        case 0: out << "x"; break;
+                        case 1: out << "y"; break;
+                        case 2: out << "z"; break;
+                        case 3: out << "w"; break;
+                        default: UNREACHABLE();
+                        }
+                    }
+                    else UNREACHABLE();
+                }
+            }
+            else UNREACHABLE();
+
+            return false;   // Fully processed
+        }
+        break;
+      case EOpAdd:               outputTriplet(visit, "(", " + ", ")"); break;
+      case EOpSub:               outputTriplet(visit, "(", " - ", ")"); break;
+      case EOpMul:               outputTriplet(visit, "(", " * ", ")"); break;
+      case EOpDiv:               outputTriplet(visit, "(", " / ", ")"); break;
+      case EOpMod:               UNIMPLEMENTED(); /* FIXME */ out << "mod";                     break;
+      case EOpRightShift:        UNIMPLEMENTED(); /* FIXME */ out << "right-shift";  break;
+      case EOpLeftShift:         UNIMPLEMENTED(); /* FIXME */ out << "left-shift";   break;
+      case EOpAnd:               UNIMPLEMENTED(); /* FIXME */ out << "bitwise and";  break;
+      case EOpInclusiveOr:       UNIMPLEMENTED(); /* FIXME */ out << "inclusive-or"; break;
+      case EOpExclusiveOr:       UNIMPLEMENTED(); /* FIXME */ out << "exclusive-or"; break;
+      case EOpEqual:             outputTriplet(visit, "(", " == ", ")");  break;
+      case EOpNotEqual:          outputTriplet(visit, "(", " != ", ")");  break;
+      case EOpLessThan:          outputTriplet(visit, "(", " < ", ")");   break;
+      case EOpGreaterThan:       outputTriplet(visit, "(", " > ", ")");   break;
+      case EOpLessThanEqual:     outputTriplet(visit, "(", " <= ", ")");  break;
+      case EOpGreaterThanEqual:  outputTriplet(visit, "(", " >= ", ")");  break;
+      case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")");   break;
+      case EOpVectorTimesMatrix: UNIMPLEMENTED(); /* FIXME */ out << "vector-times-matrix";   break;
+      case EOpMatrixTimesVector: outputTriplet(visit, "mul(", ", ", ")"); break;
+      case EOpMatrixTimesScalar: UNIMPLEMENTED(); /* FIXME */ out << "matrix-scale";          break;
+      case EOpMatrixTimesMatrix: UNIMPLEMENTED(); /* FIXME */ out << "matrix-multiply";       break;
+      case EOpLogicalOr:         outputTriplet(visit, "(", " || ", ")");  break;
+      case EOpLogicalXor:        outputTriplet(visit, "xor(", ", ", ")"); break;   // FIXME: Prevent name clashes
+      case EOpLogicalAnd:        outputTriplet(visit, "(", " && ", ")");  break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    switch (node->getOp())
+    {
+      case EOpNegative:         outputTriplet(visit, "(-", NULL, ")");  break;
+      case EOpVectorLogicalNot: outputTriplet(visit, "(!", NULL, ")");  break;
+      case EOpLogicalNot:       outputTriplet(visit, "(!", NULL, ")");  break;
+      case EOpBitwiseNot:       outputTriplet(visit, "(~", NULL, ")");  break;
+      case EOpPostIncrement:    outputTriplet(visit, "(", NULL, "++)"); break;
+      case EOpPostDecrement:    outputTriplet(visit, "(", NULL, "--)"); break;
+      case EOpPreIncrement:     outputTriplet(visit, "(++", NULL, ")"); break;
+      case EOpPreDecrement:     outputTriplet(visit, "(--", NULL, ")"); break;
+      case EOpConvIntToBool:
+      case EOpConvFloatToBool:
+        switch (node->getOperand()->getType().getNominalSize())
+        {
+          case 1:    outputTriplet(visit, "bool(", NULL, ")");  break;
+          case 2:    outputTriplet(visit, "bool2(", NULL, ")"); break;
+          case 3:    outputTriplet(visit, "bool3(", NULL, ")"); break;
+          case 4:    outputTriplet(visit, "bool4(", NULL, ")"); break;
+          default: UNREACHABLE();
+        }
+        break;
+      case EOpConvBoolToFloat:
+      case EOpConvIntToFloat:
+        switch (node->getOperand()->getType().getNominalSize())
+        {
+          case 1:    outputTriplet(visit, "float(", NULL, ")");  break;
+          case 2:    outputTriplet(visit, "float2(", NULL, ")"); break;
+          case 3:    outputTriplet(visit, "float3(", NULL, ")"); break;
+          case 4:    outputTriplet(visit, "float4(", NULL, ")"); break;
+          default: UNREACHABLE();
+        }
+        break;
+      case EOpConvFloatToInt:
+      case EOpConvBoolToInt:
+        switch (node->getOperand()->getType().getNominalSize())
+        {
+          case 1:    outputTriplet(visit, "int(", NULL, ")");  break;
+          case 2:    outputTriplet(visit, "int2(", NULL, ")"); break;
+          case 3:    outputTriplet(visit, "int3(", NULL, ")"); break;
+          case 4:    outputTriplet(visit, "int4(", NULL, ")"); break;
+          default: UNREACHABLE();
+        }
+        break;
+      case EOpRadians:          outputTriplet(visit, "radians(", NULL, ")");   break;
+      case EOpDegrees:          outputTriplet(visit, "degrees(", NULL, ")");   break;
+      case EOpSin:              outputTriplet(visit, "sin(", NULL, ")");       break;
+      case EOpCos:              outputTriplet(visit, "cos(", NULL, ")");       break;
+      case EOpTan:              outputTriplet(visit, "tan(", NULL, ")");       break;
+      case EOpAsin:             outputTriplet(visit, "asin(", NULL, ")");      break;
+      case EOpAcos:             outputTriplet(visit, "acos(", NULL, ")");      break;
+      case EOpAtan:             outputTriplet(visit, "atan(", NULL, ")");      break;
+      case EOpExp:              outputTriplet(visit, "exp(", NULL, ")");       break;
+      case EOpLog:              outputTriplet(visit, "log(", NULL, ")");       break;
+      case EOpExp2:             outputTriplet(visit, "exp2(", NULL, ")");      break;
+      case EOpLog2:             outputTriplet(visit, "log2(", NULL, ")");      break;
+      case EOpSqrt:             outputTriplet(visit, "sqrt(", NULL, ")");      break;
+      case EOpInverseSqrt:      outputTriplet(visit, "rsqrt(", NULL, ")");     break;
+      case EOpAbs:              outputTriplet(visit, "abs(", NULL, ")");       break;
+      case EOpSign:             outputTriplet(visit, "sign(", NULL, ")");      break;
+      case EOpFloor:            outputTriplet(visit, "floor(", NULL, ")");     break;
+      case EOpCeil:             outputTriplet(visit, "ceil(", NULL, ")");      break;
+      case EOpFract:            outputTriplet(visit, "frac(", NULL, ")");      break;
+      case EOpLength:           outputTriplet(visit, "length(", NULL, ")");    break;
+      case EOpNormalize:        outputTriplet(visit, "normalize(", NULL, ")"); break;
+//      case EOpDPdx:             outputTriplet(visit, "ddx(", NULL, ")");       break;
+//      case EOpDPdy:             outputTriplet(visit, "ddy(", NULL, ")");       break;
+//      case EOpFwidth:           outputTriplet(visit, "fwidth(", NULL, ")");    break;        
+      case EOpAny:              outputTriplet(visit, "any(", NULL, ")");       break;
+      case EOpAll:              outputTriplet(visit, "all(", NULL, ")");       break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    EShLanguage language = context.language;
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    if (node->getOp() == EOpNull)
+    {
+        out.message(EPrefixError, "node is still EOpNull!");
+        return true;
+    }
+
+    switch (node->getOp())
+    {
+      case EOpSequence: outputTriplet(visit, NULL, ";\n", ";\n"); break;
+      case EOpDeclaration:
+        if (visit == PreVisit)
+        {
+            TIntermSequence &sequence = node->getSequence();
+            TIntermTyped *variable = sequence[0]->getAsTyped();
+            bool visit = true;
+
+            if (variable && variable->getQualifier() == EvqTemporary)
+            {
+                out << typeString(variable->getType()) + " ";
+
+                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
+                {
+                    TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
+
+                    if (symbol)
+                    {
+                        symbol->traverse(this);
+
+                        out << arrayString(symbol->getType());
+                    }
+                    else
+                    {
+                        (*sit)->traverse(this);
+                    }
+
+                    if (visit && this->inVisit)
+                    {
+                        if (*sit != sequence.back())
+                        {
+                            visit = this->visitAggregate(InVisit, node);
+                        }
+                    }
+                }
+
+                if (visit && this->postVisit)
+                {
+                    this->visitAggregate(PostVisit, node);
+                }
+            }
+            
+            return false;
+        }
+        else if (visit == InVisit)
+        {
+            out << ", ";
+        }
+        break;
+      case EOpComma:         UNIMPLEMENTED(); /* FIXME */ out << "Comma\n"; return true;
+      case EOpFunction:
+        {
+            const TString &mangledName = node->getName();
+            TString name = TString(mangledName.c_str(), mangledName.find_first_of('('));
+
+            if (visit == PreVisit)
+            {
+                if (name == "main")
+                {
+                    TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
+
+                    if (language == EShLangFragment)
+                    {
+                        out << "PS_OUTPUT main(PS_INPUT input)\n"   // FIXME: Prevent name clashes
+                               "{\n";
+
+                        for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
+                        {
+                            const TSymbol *symbol = (*namedSymbol).second;
+                            const TString &name = symbol->getName();
+
+                            if (symbol->isVariable())
+                            {
+                                const TVariable *variable = static_cast<const TVariable*>(symbol);
+                                const TType &type = variable->getType();
+                                TQualifier qualifier = type.getQualifier();
+
+                                if(qualifier == EvqVaryingIn)
+                                {
+                                    out << "    " + name + " = input." + name + ";\n";   // FIXME: Prevent name clashes
+                                }
+                            }
+                        }
+                    }
+                    else
+                    {
+                        out << "VS_OUTPUT main(VS_INPUT input)\n"   // FIXME: Prevent name clashes
+                               "{\n";
+
+                        for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
+                        {
+                            const TSymbol *symbol = (*namedSymbol).second;
+                            const TString &name = symbol->getName();
+
+                            if (symbol->isVariable())
+                            {
+                                const TVariable *variable = static_cast<const TVariable*>(symbol);
+                                const TType &type = variable->getType();
+                                TQualifier qualifier = type.getQualifier();
+
+                                if (qualifier == EvqAttribute)
+                                {
+                                    out << "    " + name + " = input." + name + ";\n";   // FIXME: Prevent name clashes
+                                }
+                            }
+                        }
+                    }
+
+                    // Erase the (empty) argument list
+                    TIntermSequence &sequence = node->getSequence();
+                    sequence.erase(sequence.begin());
+                }
+                else
+                {
+                    out << typeString(node->getType()) << " " << name << "(";
+
+                    TIntermSequence &sequence = node->getSequence();
+                    TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence();
+
+                    for (unsigned int i = 0; i < arguments.size(); i++)
+                    {
+                        TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
+
+                        if (symbol)
+                        {
+                            const TType &type = symbol->getType();
+                            const TString &name = symbol->getSymbol();
+
+                            out << typeString(type) + " " + name;
+
+                            if(i < arguments.size() - 1)
+                            {
+                                out << ", ";
+                            }
+                        }
+                        else UNREACHABLE();
+                    }
+
+                    sequence.erase(sequence.begin());
+
+                    out << ")\n"
+                           "{\n";
+                }
+            }
+            else if (visit == PostVisit)
+            {
+                if (name == "main")
+                {
+                    if (language == EShLangFragment)
+                    {
+                        out << "    PS_OUTPUT output;\n"                    // FIXME: Prevent name clashes
+                               "    output.gl_Color[0] = gl_Color[0];\n";   // FIXME: Prevent name clashes
+
+                        TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
+
+                        for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
+                        {
+                            const TSymbol *symbol = (*namedSymbol).second;
+                            const TString &name = symbol->getName();
+                        }
+                    }
+                    else
+                    {
+                        out << "    VS_OUTPUT output;\n"   // FIXME: Prevent name clashes
+                               "    output.gl_Position.x = gl_Position.x - gl_HalfPixelSize.x * gl_Position.w;\n"
+                               "    output.gl_Position.y = -(gl_Position.y - gl_HalfPixelSize.y * gl_Position.w);\n"
+                               "    output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
+                               "    output.gl_Position.w = gl_Position.w;\n"
+                               "    output.gl_PointSize = gl_PointSize;\n";
+
+                        TSymbolTableLevel *symbols = context.symbolTable.getGlobalLevel();
+
+                        for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++)
+                        {
+                            const TSymbol *symbol = (*namedSymbol).second;
+                            const TString &name = symbol->getName();
+
+                            if (symbol->isVariable())
+                            {
+                                const TVariable *variable = static_cast<const TVariable*>(symbol);
+                                TQualifier qualifier = variable->getType().getQualifier();
+
+                                if(qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut)
+                                {
+                                    out << "    output." + name + " = " + name + ";\n";   // FIXME: Prevent name clashes
+                                }
+                            }
+                        }
+                    }
+
+                    out << "    return output;\n"   // FIXME: Prevent name clashes
+                           "}\n";
+                }
+                else
+                {
+                    out << "}\n";
+                }
+            }
+        }
+        break;
+      case EOpFunctionCall:
+        {
+            if (visit == PreVisit)
+            {
+                const TString &mangledName = node->getName();
+                TString name = TString(mangledName.c_str(), mangledName.find_first_of('('));
+
+                if (node->isUserDefined())
+                {
+                    out << name << "(";
+                }
+                else
+                {
+                    if (name == "texture2D")
+                    {
+                        if (node->getSequence().size() == 2)
+                        {
+                            out << "gl_texture2D(";
+                        }
+                        else if (node->getSequence().size() == 3)
+                        {
+                            out << "gl_texture2DBias(";
+                        }
+                        else UNREACHABLE();
+                    }
+                    else if (name == "texture2DProj")
+                    {
+                        out << "gl_texture2DProj(";
+                    }
+                    else if (name == "texture2DLod")
+                    {
+                        out << "gl_texture2DLod(";
+                        UNIMPLEMENTED();   // FIXME: Move lod to last texture coordinate component
+                    }
+                    else if (name == "texture2DProjLod")
+                    {
+                        out << "gl_texture2DProjLod(";
+                        UNIMPLEMENTED();   // FIXME: Move lod to last texture coordinate component
+                    }
+                    else if (name == "textureCube")
+                    {
+                        out << "gl_textureCube(";   // FIXME: Incorrect sampling location
+                    }
+                    else
+                    {
+                        UNIMPLEMENTED();   // FIXME
+                    }
+                }
+            }
+            else if (visit == InVisit)
+            {
+                out << ", ";
+            }
+            else
+            {
+                out << ")";
+            }
+        }
+        break;
+      case EOpParameters:       outputTriplet(visit, "(", ", ", ")\n{\n");  break;
+      case EOpConstructFloat:   outputTriplet(visit, "vec1(", NULL, ")");   break;
+      case EOpConstructVec2:    outputTriplet(visit, "vec2(", ", ", ")");   break;
+      case EOpConstructVec3:    outputTriplet(visit, "vec3(", ", ", ")");   break;
+      case EOpConstructVec4:    outputTriplet(visit, "vec4(", ", ", ")");   break;
+      case EOpConstructBool:    UNIMPLEMENTED(); /* FIXME */ out << "Construct bool";  break;
+      case EOpConstructBVec2:   UNIMPLEMENTED(); /* FIXME */ out << "Construct bvec2"; break;
+      case EOpConstructBVec3:   UNIMPLEMENTED(); /* FIXME */ out << "Construct bvec3"; break;
+      case EOpConstructBVec4:   UNIMPLEMENTED(); /* FIXME */ out << "Construct bvec4"; break;
+      case EOpConstructInt:     UNIMPLEMENTED(); /* FIXME */ out << "Construct int";   break;
+      case EOpConstructIVec2:   UNIMPLEMENTED(); /* FIXME */ out << "Construct ivec2"; break;
+      case EOpConstructIVec3:   UNIMPLEMENTED(); /* FIXME */ out << "Construct ivec3"; break;
+      case EOpConstructIVec4:   UNIMPLEMENTED(); /* FIXME */ out << "Construct ivec4"; break;
+      case EOpConstructMat2:    outputTriplet(visit, "float2x2(", ", ", ")"); break;
+      case EOpConstructMat3:    outputTriplet(visit, "float3x3(", ", ", ")"); break;
+      case EOpConstructMat4:    UNIMPLEMENTED(); /* FIXME */ out << "Construct mat4";  break;
+      case EOpConstructStruct:  UNIMPLEMENTED(); /* FIXME */ out << "Construct structure";  break;
+      case EOpLessThan:         outputTriplet(visit, "(", " < ", ")");             break;
+      case EOpGreaterThan:      outputTriplet(visit, "(", " > ", ")");             break;
+      case EOpLessThanEqual:    outputTriplet(visit, "(", " <= ", ")");            break;
+      case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")");            break;
+      case EOpVectorEqual:      outputTriplet(visit, "(", " == ", ")");            break;
+      case EOpVectorNotEqual:   outputTriplet(visit, "(", " != ", ")");            break;
+      case EOpMod:              outputTriplet(visit, "mod(", ", ", ")");           break;   // FIXME: Prevent name clashes
+      case EOpPow:              outputTriplet(visit, "pow(", ", ", ")");           break;
+      case EOpAtan:
+        if (node->getSequence().size() == 1)
+        {
+            outputTriplet(visit, "atan(", ", ", ")");
+        }
+        else if (node->getSequence().size() == 2)
+        {
+            outputTriplet(visit, "atan2(", ", ", ")");
+        }
+        else UNREACHABLE();
+        break;
+      case EOpMin:           outputTriplet(visit, "min(", ", ", ")");           break;
+      case EOpMax:           outputTriplet(visit, "max(", ", ", ")");           break;
+      case EOpClamp:         outputTriplet(visit, "clamp(", ", ", ")");         break;
+      case EOpMix:           outputTriplet(visit, "lerp(", ", ", ")");          break;
+      case EOpStep:          outputTriplet(visit, "step(", ", ", ")");          break;
+      case EOpSmoothStep:    outputTriplet(visit, "smoothstep(", ", ", ")");    break;
+      case EOpDistance:      outputTriplet(visit, "distance(", ", ", ")");      break;
+      case EOpDot:           outputTriplet(visit, "dot(", ", ", ")");           break;
+      case EOpCross:         outputTriplet(visit, "cross(", ", ", ")");         break;
+      case EOpFaceForward:   UNIMPLEMENTED(); /* FIXME */ out << "face-forward";            break;
+      case EOpReflect:       outputTriplet(visit, "reflect(", ", ", ")");       break;
+      case EOpRefract:       outputTriplet(visit, "refract(", ", ", ")");       break;
+      case EOpMul:           outputTriplet(visit, "(", " * ", ")");             break;
+      case EOpItof:          UNIMPLEMENTED(); /* FIXME */ out << "itof";        break;
+      case EOpFtoi:          UNIMPLEMENTED(); /* FIXME */ out << "ftoi";        break;
+      case EOpSkipPixels:    UNIMPLEMENTED(); /* FIXME */ out << "skipPixels";  break;
+      case EOpReadInput:     UNIMPLEMENTED(); /* FIXME */ out << "readInput";   break;
+      case EOpWritePixel:    UNIMPLEMENTED(); /* FIXME */ out << "writePixel";  break;
+      case EOpBitmapLsb:     UNIMPLEMENTED(); /* FIXME */ out << "bitmapLSB";   break;
+      case EOpBitmapMsb:     UNIMPLEMENTED(); /* FIXME */ out << "bitmapMSB";   break;
+      case EOpWriteOutput:   UNIMPLEMENTED(); /* FIXME */ out << "writeOutput"; break;
+      case EOpReadPixel:     UNIMPLEMENTED(); /* FIXME */ out << "readPixel";   break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    out << "if(";
+
+    node->getCondition()->traverse(this);
+
+    out << ")\n"
+           "{\n";
+
+    node->getTrueBlock()->traverse(this);
+
+    out << ";}\n";
+
+    if (node->getFalseBlock())
+    {
+        out << "else\n"
+               "{\n";
+
+        node->getFalseBlock()->traverse(this);
+
+        out << ";}\n";
+    }
+
+    return false;
+}
+
+void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+    
+    int size = node->getType().getObjectSize();
+    bool matrix = node->getType().isMatrix();
+    TBasicType type = node->getUnionArrayPointer()[0].getType();
+
+    switch (type)
+    {
+      case EbtBool:
+        if (!matrix)
+        {
+            switch (size)
+            {
+              case 1: out << "bool(";  break;
+              case 2: out << "bool2("; break;
+              case 3: out << "bool3("; break;
+              case 4: out << "bool4("; break;
+              default: UNREACHABLE();
+            }
+        }
+        else
+        {
+            UNIMPLEMENTED();
+        }
+        break;
+      case EbtFloat:
+        if (!matrix)
+        {
+            switch (size)
+            {
+              case 1: out << "float(";  break;
+              case 2: out << "float2("; break;
+              case 3: out << "float3("; break;
+              case 4: out << "float4("; break;
+              default: UNREACHABLE();
+            }
+        }
+        else
+        {
+            switch (size)
+            {
+              case 4:  out << "float2x2("; break;
+              case 9:  out << "float3x3("; break;
+              case 16: out << "float4x4("; break;
+              default: UNREACHABLE();
+            }
+        }
+        break;
+      case EbtInt:
+        if (!matrix)
+        {
+            switch (size)
+            {
+              case 1: out << "int(";  break;
+              case 2: out << "int2("; break;
+              case 3: out << "int3("; break;
+              case 4: out << "int4("; break;
+              default: UNREACHABLE();
+            }
+        }
+        else
+        {
+            UNIMPLEMENTED();
+        }
+        break;
+      default:
+        UNIMPLEMENTED();   // FIXME
+    }
+
+    for (int i = 0; i < size; i++)
+    {
+        switch (type)
+        {
+          case EbtBool:
+            if (node->getUnionArrayPointer()[i].getBConst())
+            {
+                out << "true";
+            }
+            else
+            {
+                out << "false";
+            }
+            break;
+          case EbtFloat:
+            out << node->getUnionArrayPointer()[i].getFConst();           
+            break;
+          case EbtInt:
+            out << node->getUnionArrayPointer()[i].getIConst();
+            break;
+          default: 
+            UNIMPLEMENTED();   // FIXME
+        }
+
+        if (i != size - 1)
+        {
+            out << ", ";
+        }
+    }
+
+    out << ")";
+}
+
+bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    if (!node->testFirst())
+    {
+        out << "do\n"
+               "{\n";
+    }
+    else
+    {
+        out << "for(";
+        
+        if (node->getInit())
+        {
+            node->getInit()->traverse(this);
+        }
+
+        out << "; ";
+
+        if (node->getTest())
+        {
+            node->getTest()->traverse(this);
+        }
+
+        out << "; ";
+
+        if (node->getTerminal())
+        {
+            node->getTerminal()->traverse(this);
+        }
+
+        out << ")\n"
+               "{\n";
+    }
+
+    if (node->getBody())
+    {
+        node->getBody()->traverse(this);
+    }
+
+    out << "}\n";
+
+    if (!node->testFirst())
+    {
+        out << "while(\n";
+
+        node->getTest()->traverse(this);
+
+        out << ")";
+    }
+
+    out << ";\n";
+
+    return false;
+}
+
+bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    switch (node->getFlowOp())
+    {
+      case EOpKill:      outputTriplet(visit, "discard", NULL, NULL); break;
+      case EOpBreak:     UNIMPLEMENTED(); /* FIXME */          break;
+      case EOpContinue:  UNIMPLEMENTED(); /* FIXME */       break;
+      case EOpReturn:
+        if (visit == PreVisit)
+        {
+            if (node->getExpression())
+            {
+                out << "return ";
+            }
+            else
+            {
+                out << "return;\n";
+            }
+        }
+        else if (visit == PostVisit)
+        {
+            out << ";\n";
+        }
+        break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+void OutputHLSL::outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString)
+{
+    TInfoSinkBase &out = context.infoSink.obj;
+
+    if (visit == PreVisit && preString)
+    {
+        out << preString;
+    }
+    else if (visit == InVisit && inString)
+    {
+        out << inString;
+    }
+    else if (visit == PostVisit && postString)
+    {
+        out << postString;
+    }
+}
+
+TString OutputHLSL::typeString(const TType &type)
+{
+    if (type.isMatrix())
+    {
+        switch (type.getNominalSize())
+        {
+          case 2: return "float2x2";
+          case 3: return "float3x3";
+          case 4: return "float4x4";
+        }
+    }
+    else
+    {
+        switch (type.getBasicType())
+        {
+          case EbtFloat:
+            switch (type.getNominalSize())
+            {
+              case 1: return "float";
+              case 2: return "float2";
+              case 3: return "float3";
+              case 4: return "float4";
+            }
+          case EbtInt:
+            switch (type.getNominalSize())
+            {
+              case 1: return "int";
+              case 2: return "int2";
+              case 3: return "int3";
+              case 4: return "int4";
+            }
+          case EbtBool:
+            switch (type.getNominalSize())
+            {
+              case 1: return "bool";
+              case 2: return "bool2";
+              case 3: return "bool3";
+              case 4: return "bool4";
+            }
+          case EbtVoid:
+            return "void";
+          case EbtSampler2D:
+            return "sampler2D";
+          case EbtSamplerCube:
+            return "samplerCUBE";
+        }
+    }
+
+    UNIMPLEMENTED();   // FIXME
+    return "<unknown type>";
+}
+
+TString OutputHLSL::arrayString(const TType &type)
+{
+    if (!type.isArray())
+    {
+        return "";
+    }
+
+    char buffer[100];
+    sprintf(buffer, "[%d]", type.getArraySize());
+
+    return buffer;
+}
+
+TString OutputHLSL::initializer(const TType &type)
+{
+    TString string;
+
+    int arraySize = type.isArray() ? type.getArraySize() : 1;
+
+    if (type.isArray())
+    {
+        string += "{";
+    }
+
+    for (int element = 0; element < arraySize; element++)
+    {
+        string += typeString(type) + "(";
+
+        for (int component = 0; component < type.getNominalSize(); component++)
+        {
+            string += "0";
+
+            if (component < type.getNominalSize() - 1)
+            {
+                string += ", ";
+            }
+        }
+
+        string += ")";
+
+        if (element < arraySize - 1)
+        {
+            string += ", ";
+        }
+    }
+
+    if (type.isArray())
+    {
+        string += "}";
+    }
+
+    return string;
+}
+}
diff --git a/Compiler/OutputHLSL.h b/Compiler/OutputHLSL.h
new file mode 100644
index 0000000..a54e006
--- /dev/null
+++ b/Compiler/OutputHLSL.h
@@ -0,0 +1,42 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_OUTPUTHLSL_H_
+#define COMPILER_OUTPUTHLSL_H_
+
+#include "intermediate.h"
+#include "ParseHelper.h"
+
+namespace sh
+{
+class OutputHLSL : public TIntermTraverser
+{
+  public:
+    OutputHLSL(TParseContext &context);
+
+    void header();
+
+  protected:
+    void visitSymbol(TIntermSymbol*);
+    void visitConstantUnion(TIntermConstantUnion*);
+    bool visitBinary(Visit visit, TIntermBinary*);
+    bool visitUnary(Visit visit, TIntermUnary*);
+    bool visitSelection(Visit visit, TIntermSelection*);
+    bool visitAggregate(Visit visit, TIntermAggregate*);
+    bool visitLoop(Visit visit, TIntermLoop*);
+    bool visitBranch(Visit visit, TIntermBranch*);
+
+    void outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString);
+
+    static TString typeString(const TType &type);
+    static TString arrayString(const TType &type);
+    static TString initializer(const TType &type);
+
+    TParseContext &context;
+};
+}
+
+#endif   // COMPILER_OUTPUTHLSL_H_
diff --git a/Compiler/ParseHelper.cpp b/Compiler/ParseHelper.cpp
new file mode 100644
index 0000000..4062a56
--- /dev/null
+++ b/Compiler/ParseHelper.cpp
@@ -0,0 +1,1436 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "ParseHelper.h"
+#include "InitializeParseContext.h"
+#include "osinclude.h"
+#include <stdarg.h>
+///////////////////////////////////////////////////////////////////////
+//
+// Sub- vector and matrix fields
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Look at a '.' field selector string and change it into offsets
+// for a vector.
+//
+bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
+{
+	fields.num = (int) compString.size();
+	if (fields.num > 4) {
+		error(line, "illegal vector field selection", compString.c_str(), "");
+		return false;
+	}
+
+	enum {
+		exyzw,
+		ergba,
+		estpq,
+	} fieldSet[4];
+
+	for (int i = 0; i < fields.num; ++i) {
+		switch (compString[i])  {
+		case 'x': 
+			fields.offsets[i] = 0;
+			fieldSet[i] = exyzw;
+			break;
+		case 'r': 
+			fields.offsets[i] = 0;
+			fieldSet[i] = ergba;
+			break;
+		case 's':
+			fields.offsets[i] = 0;
+			fieldSet[i] = estpq;
+			break;
+		case 'y': 
+			fields.offsets[i] = 1;
+			fieldSet[i] = exyzw;
+			break;
+		case 'g': 
+			fields.offsets[i] = 1;
+			fieldSet[i] = ergba;
+			break;
+		case 't':
+			fields.offsets[i] = 1;
+			fieldSet[i] = estpq;
+			break;
+		case 'z': 
+			fields.offsets[i] = 2;
+			fieldSet[i] = exyzw;
+			break;
+		case 'b': 
+			fields.offsets[i] = 2;
+			fieldSet[i] = ergba;
+			break;
+		case 'p':
+			fields.offsets[i] = 2;
+			fieldSet[i] = estpq;
+			break;
+		
+		case 'w': 
+			fields.offsets[i] = 3;
+			fieldSet[i] = exyzw;
+			break;
+		case 'a': 
+			fields.offsets[i] = 3;
+			fieldSet[i] = ergba;
+			break;
+		case 'q':
+			fields.offsets[i] = 3;
+			fieldSet[i] = estpq;
+			break;
+		default:
+			error(line, "illegal vector field selection", compString.c_str(), "");
+			return false;
+		}
+	}
+
+	for (int i = 0; i < fields.num; ++i) {
+		if (fields.offsets[i] >= vecSize) {
+			error(line, "vector field selection out of range",  compString.c_str(), "");
+			return false;
+		}
+
+		if (i > 0) {
+			if (fieldSet[i] != fieldSet[i-1]) {
+				error(line, "illegal - vector component fields not from the same set", compString.c_str(), "");
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
+
+//
+// Look at a '.' field selector string and change it into offsets
+// for a matrix.
+//
+bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line)
+{
+	fields.wholeRow = false;
+	fields.wholeCol = false;
+	fields.row = -1;
+	fields.col = -1;
+
+	if (compString.size() != 2) {
+		error(line, "illegal length of matrix field selection", compString.c_str(), "");
+		return false;
+	}
+
+	if (compString[0] == '_') {
+		if (compString[1] < '0' || compString[1] > '3') {
+			error(line, "illegal matrix field selection", compString.c_str(), "");
+			return false;
+		}
+		fields.wholeCol = true;
+		fields.col = compString[1] - '0';
+	} else if (compString[1] == '_') {
+		if (compString[0] < '0' || compString[0] > '3') {
+			error(line, "illegal matrix field selection", compString.c_str(), "");
+			return false;
+		}
+		fields.wholeRow = true;
+		fields.row = compString[0] - '0';
+	} else {
+		if (compString[0] < '0' || compString[0] > '3' ||
+			compString[1] < '0' || compString[1] > '3') {
+			error(line, "illegal matrix field selection", compString.c_str(), "");
+			return false;
+		}
+		fields.row = compString[0] - '0';
+		fields.col = compString[1] - '0';
+	}
+
+	if (fields.row >= matSize || fields.col >= matSize) {
+		error(line, "matrix field selection out of range", compString.c_str(), "");
+		return false;
+	}
+
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// Errors
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Track whether errors have occurred.
+//
+void TParseContext::recover()
+{
+	recoveredFromError = true;
+}
+
+//
+// Used by flex/bison to output all syntax and parsing errors.
+//
+void C_DECL TParseContext::error(TSourceLoc nLine, const char *szReason, const char *szToken, 
+								 const char *szExtraInfoFormat, ...)
+{
+	char szExtraInfo[400];
+	va_list marker;
+	
+	va_start(marker, szExtraInfoFormat);
+	
+	_vsnprintf(szExtraInfo, sizeof(szExtraInfo), szExtraInfoFormat, marker);
+	
+	/* VC++ format: file(linenum) : error #: 'token' : extrainfo */
+	infoSink.info.prefix(EPrefixError);
+	infoSink.info.location(nLine);
+	infoSink.info << "'" << szToken <<  "' : " << szReason << " " << szExtraInfo << "\n";
+	
+	va_end(marker);
+
+	++numErrors;
+}
+
+//
+// Same error message for all places assignments don't work.
+//
+void TParseContext::assignError(int line, const char* op, TString left, TString right)
+{
+	error(line, "", op, "cannot convert from '%s' to '%s'",
+		  right.c_str(), left.c_str());
+}
+
+//
+// Same error message for all places unary operations don't work.
+//
+void TParseContext::unaryOpError(int line, const char* op, TString operand)
+{
+   error(line, " wrong operand type", op, 
+		  "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)",
+		  op, operand.c_str());
+}
+
+//
+// Same error message for all binary operations don't work.
+//
+void TParseContext::binaryOpError(int line, const char* op, TString left, TString right)
+{
+	error(line, " wrong operand types ", op, 
+			"no operation '%s' exists that takes a left-hand operand of type '%s' and "
+			"a right operand of type '%s' (or there is no acceptable conversion)", 
+			op, left.c_str(), right.c_str());
+}
+
+//
+// Both test and if necessary, spit out an error, to see if the node is really
+// an l-value that can be operated on this way.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node)
+{
+	TIntermSymbol* symNode = node->getAsSymbolNode();
+	TIntermBinary* binaryNode = node->getAsBinaryNode();
+
+	if (binaryNode) {
+		bool errorReturn;
+
+		switch(binaryNode->getOp()) {
+		case EOpIndexDirect:
+		case EOpIndexIndirect:
+		case EOpIndexDirectStruct:
+			return lValueErrorCheck(line, op, binaryNode->getLeft());
+		case EOpVectorSwizzle:
+			errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
+			if (!errorReturn) {
+				int offset[4] = {0,0,0,0};
+
+				TIntermTyped* rightNode = binaryNode->getRight();
+				TIntermAggregate *aggrNode = rightNode->getAsAggregate();
+				
+				for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); 
+											   p != aggrNode->getSequence().end(); p++) {
+					int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getIConst();
+					offset[value]++;     
+					if (offset[value] > 1) {
+						error(line, " l-value of swizzle cannot have duplicate components", op, "", "");
+
+						return true;
+					}
+				}
+			} 
+
+			return errorReturn;
+		default: 
+			break;
+		}
+		error(line, " l-value required", op, "", "");
+
+		return true;
+	}
+
+
+	const char* symbol = 0;
+	if (symNode != 0)
+		symbol = symNode->getSymbol().c_str();
+
+	const char* message = 0;
+	switch (node->getQualifier()) {
+	case EvqConst:          message = "can't modify a const";        break;
+	case EvqConstReadOnly:  message = "can't modify a const";        break;
+	case EvqAttribute:      message = "can't modify an attribute";   break;
+	case EvqUniform:        message = "can't modify a uniform";      break;
+	case EvqVaryingIn:      message = "can't modify a varying";      break;
+	case EvqInput:          message = "can't modify an input";       break;
+	case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
+	case EvqFrontFacing:    message = "can't modify gl_FrontFacing"; break;
+	case EvqPointCoord:     message = "can't modify gl_PointCoord";  break;
+	default:
+
+		//
+		// Type that can't be written to?
+		//
+		switch (node->getBasicType()) {
+		case EbtSampler2D:
+		case EbtSamplerCube:
+			message = "can't modify a sampler";
+			break;
+		case EbtVoid:
+			message = "can't modify void";
+			break;
+		default: 
+			break;
+		}
+	}
+
+	if (message == 0 && binaryNode == 0 && symNode == 0) {
+		error(line, " l-value required", op, "", "");
+
+		return true;
+	}
+
+
+	//
+	// Everything else is okay, no error.
+	//
+	if (message == 0)
+		return false;
+
+	//
+	// If we get here, we have an error and a message.
+	//
+	if (symNode)
+		error(line, " l-value required", op, "\"%s\" (%s)", symbol, message);
+	else
+		error(line, " l-value required", op, "(%s)", message);
+
+	return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// a constant.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::constErrorCheck(TIntermTyped* node)
+{
+	if (node->getQualifier() == EvqConst)
+		return false;
+
+	error(node->getLine(), "constant expression required", "", "");
+
+	return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// an integer.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
+{
+	if (node->getBasicType() == EbtInt && node->getNominalSize() == 1)
+		return false;
+
+	error(node->getLine(), "integer expression required", token, "");
+
+	return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if we are currently
+// globally scoped.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
+{
+	if (global)
+		return false;
+
+	error(line, "only allowed at global scope", token, "");
+
+	return true;
+}
+
+//
+// For now, keep it simple:  if it starts "gl_", it's reserved, independent
+// of scope.  Except, if the symbol table is at the built-in push-level,
+// which is when we are parsing built-ins.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
+{
+	if (!symbolTable.atBuiltInLevel()) {
+		if (identifier.substr(0, 3) == TString("gl_")) {
+			error(line, "reserved built-in name", "gl_", "");
+			return true;
+		}
+		if (identifier.find("__") != TString::npos) {
+			//error(line, "Two consecutive underscores are reserved for future use.", identifier.c_str(), "", "");
+			//return true;
+			infoSink.info.message(EPrefixWarning, "Two consecutive underscores are reserved for future use.", line);
+			return false;
+		}
+	}
+
+	return false;
+}
+
+//
+// Make sure there is enough data provided to the constructor to build
+// something of the type of the constructor.  Also returns the type of
+// the constructor.
+//
+// Returns true if there was an error in construction.
+//
+bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
+{
+	*type = function.getReturnType();
+
+	bool constructingMatrix = false;
+	switch(op) {
+	case EOpConstructMat2:
+	case EOpConstructMat3:
+	case EOpConstructMat4:
+		constructingMatrix = true;
+		break;
+	default: 
+		break;
+	}
+
+	//
+	// Note: It's okay to have too many components available, but not okay to have unused
+	// arguments.  'full' will go to true when enough args have been seen.  If we loop
+	// again, there is an extra argument, so 'overfull' will become true.
+	//
+
+	int size = 0;
+	bool constType = true;
+	bool full = false;
+	bool overFull = false;
+	bool matrixInMatrix = false;
+	bool arrayArg = false;
+	for (int i = 0; i < function.getParamCount(); ++i) {
+		size += function[i].type->getObjectSize();
+		
+		if (constructingMatrix && function[i].type->isMatrix())
+			matrixInMatrix = true;
+		if (full)
+			overFull = true;
+		if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
+			full = true;
+		if (function[i].type->getQualifier() != EvqConst)
+			constType = false;
+		if (function[i].type->isArray())
+			arrayArg = true;
+	}
+	
+	if (constType)
+		type->changeQualifier(EvqConst);
+
+	if (type->isArray() && type->getArraySize() != function.getParamCount()) {
+		error(line, "array constructor needs one argument per array element", "constructor", "");
+		return true;
+	}
+
+	if (arrayArg && op != EOpConstructStruct) {
+		error(line, "constructing from a non-dereferenced array", "constructor", "");
+		return true;
+	}
+
+	if (matrixInMatrix && !type->isArray()) {
+		error(line, "constructing matrix from matrix", "constructor", "(reserved)");
+		return true;
+	}
+
+	if (overFull) {
+		error(line, "too many arguments", "constructor", "");
+		return true;
+	}
+	
+	if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->size() != function.getParamCount()) {
+		error(line, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
+		return true;
+	}
+
+	if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
+		(op == EOpConstructStruct && size < type->getObjectSize())) {
+		error(line, "not enough data provided for construction", "constructor", "");
+		return true;
+	}
+
+	TIntermTyped* typed = node->getAsTyped();
+	if (typed == 0) {
+		error(line, "constructor argument does not have a type", "constructor", "");
+		return true;
+	}
+	if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
+		error(line, "cannot convert a sampler", "constructor", "");
+		return true;
+	}
+	if (typed->getBasicType() == EbtVoid) {
+		error(line, "cannot convert a void", "constructor", "");
+		return true;
+	}
+
+	return false;
+}
+
+// This function checks to see if a void variable has been declared and raise an error message for such a case
+//
+// returns true in case of an error
+//
+bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType)
+{
+	if (pubType.type == EbtVoid) {
+		error(line, "illegal use of type 'void'", identifier.c_str(), "");
+		return true;
+	} 
+
+	return false;
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
+//
+// returns true in case of an error
+//
+bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
+{
+	if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
+		error(line, "boolean expression expected", "", "");
+		return true;
+	} 
+
+	return false;
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
+//
+// returns true in case of an error
+//
+bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
+{
+	if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
+		error(line, "boolean expression expected", "", "");
+		return true;
+	} 
+
+	return false;
+}
+
+bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
+{
+	if (pType.type == EbtStruct) {
+		if (containsSampler(*pType.userDef)) {
+			error(line, reason, TType::getBasicString(pType.type), "(structure contains a sampler)");
+		
+			return true;
+		}
+		
+		return false;
+	} else if (IsSampler(pType.type)) {
+		error(line, reason, TType::getBasicString(pType.type), "");
+
+		return true;
+	}
+
+	return false;
+}
+
+bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
+{
+	if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
+		pType.type == EbtStruct) {
+		error(line, "cannot be used with a structure", getQualifierString(pType.qualifier), "");
+		
+		return true;
+	}
+
+	if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
+		return true;
+
+	return false;
+}
+
+bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
+{
+	if ((qualifier == EvqOut || qualifier == EvqInOut) && 
+			 type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
+		error(line, "samplers cannot be output parameters", type.getBasicString(), "");
+		return true;
+	}
+
+	return false;
+}
+
+bool TParseContext::containsSampler(TType& type)
+{
+	if (IsSampler(type.getBasicType()))
+		return true;
+
+	if (type.getBasicType() == EbtStruct) {
+		TTypeList& structure = *type.getStruct();
+		for (unsigned int i = 0; i < structure.size(); ++i) {
+			if (containsSampler(*structure[i].type))
+				return true;
+		}
+	}
+
+	return false;
+}
+
+//
+// Do size checking for an array type's size.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
+{
+	TIntermConstantUnion* constant = expr->getAsConstantUnion();
+	if (constant == 0 || constant->getBasicType() != EbtInt) {
+		error(line, "array size must be a constant integer expression", "", "");
+		return true;
+	}
+
+	size = constant->getUnionArrayPointer()->getIConst();
+
+	if (size <= 0) {
+		error(line, "array size must be a positive integer", "", "");
+		size = 1;
+		return true;
+	}
+
+	return false;
+}
+
+//
+// See if this qualifier can be an array.
+//
+// Returns true if there is an error.
+//
+bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
+{
+	if (type.qualifier == EvqAttribute) {
+		error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), "");
+		return true;
+	}
+
+	if (type.qualifier == EvqConst && extensionErrorCheck(line, "GL_3DL_array_objects"))
+		return true;
+
+	return false;
+}
+
+//
+// See if this type can be an array.
+//
+// Returns true if there is an error.
+//
+bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
+{
+	//
+	// Can the type be an array?
+	//
+	if (type.array) {
+		error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str(), "");
+		return true;
+	}
+
+	return false;
+}
+
+//
+// Do all the semantic checking for declaring an array, with and 
+// without a size, and make the right changes to the symbol table.
+//
+// size == 0 means no specified size.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable)
+{
+	//
+	// Don't check for reserved word use until after we know it's not in the symbol table,
+	// because reserved arrays can be redeclared.
+	//
+
+	bool builtIn = false; 
+	bool sameScope = false;
+	TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope);
+	if (symbol == 0 || !sameScope) {
+		if (reservedErrorCheck(line, identifier))
+			return true;
+		
+		variable = new TVariable(&identifier, TType(type));
+
+		if (type.arraySize)
+			variable->getType().setArraySize(type.arraySize);
+
+		if (! symbolTable.insert(*variable)) {
+			delete variable;
+			error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), "");
+			return true;
+		}
+	} else {
+		if (! symbol->isVariable()) {
+			error(line, "variable expected", identifier.c_str(), "");
+			return true;
+		}
+
+		variable = static_cast<TVariable*>(symbol);
+		if (! variable->getType().isArray()) {
+			error(line, "redeclaring non-array as array", identifier.c_str(), "");
+			return true;
+		}
+		if (variable->getType().getArraySize() > 0) {
+			error(line, "redeclaration of array with size", identifier.c_str(), "");
+			return true;
+		}
+		
+		if (! variable->getType().sameElementType(TType(type))) {
+			error(line, "redeclaration of array with a different type", identifier.c_str(), "");
+			return true;
+		}
+
+		TType* t = variable->getArrayInformationType();
+		while (t != 0) {
+			if (t->getMaxArraySize() > type.arraySize) {
+				error(line, "higher index value already used for the array", identifier.c_str(), "");
+				return true;
+			}
+			t->setArraySize(type.arraySize);
+			t = t->getArrayInformationType();
+		}
+
+		if (type.arraySize)
+			variable->getType().setArraySize(type.arraySize);
+	} 
+
+	if (voidErrorCheck(line, identifier, type))
+		return true;
+
+	return false;
+}
+
+bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
+{
+	bool builtIn = false;
+	TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn);
+	if (symbol == 0) {
+		error(line, " undeclared identifier", node->getSymbol().c_str(), "");
+		return true;
+	}
+	TVariable* variable = static_cast<TVariable*>(symbol);
+
+	type->setArrayInformationType(variable->getArrayInformationType());
+	variable->updateArrayInformationType(type);
+
+	// special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
+	// its an error
+	if (node->getSymbol() == "gl_FragData") {
+		TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn);
+		if (fragData == 0) {
+			infoSink.info.message(EPrefixInternalError, "gl_MaxDrawBuffers not defined", line);
+			return true;
+		}
+
+		int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
+		if (fragDataValue <= size) {
+			error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers", "");
+			return true;
+		}
+	}
+
+	// we dont want to update the maxArraySize when this flag is not set, we just want to include this 
+	// node type in the chain of node types so that its updated when a higher maxArraySize comes in.
+	if (!updateFlag)
+		return false;
+
+	size++;
+	variable->getType().setMaxArraySize(size);
+	type->setMaxArraySize(size);
+	TType* tt = type;
+
+	while(tt->getArrayInformationType() != 0) {
+		tt = tt->getArrayInformationType();
+		tt->setMaxArraySize(size);
+	}
+
+	return false;
+}
+
+//
+// Enforce non-initializer type/qualifier rules.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type)
+{
+	//
+	// Make the qualifier make sense.
+	//
+	if (type.qualifier == EvqConst) {
+		type.qualifier = EvqTemporary;
+		error(line, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
+		return true;
+	}
+
+	return false;
+}
+
+//
+// Do semantic checking for a variable declaration that has no initializer,
+// and update the symbol table.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type)
+{
+	if (reservedErrorCheck(line, identifier))
+		recover();
+
+	TVariable* variable = new TVariable(&identifier, TType(type));
+
+	if (! symbolTable.insert(*variable)) {
+		error(line, "redefinition", variable->getName().c_str(), "");
+		delete variable;
+		return true;
+	}
+
+	if (voidErrorCheck(line, identifier, type))
+		return true;
+
+	return false;
+}
+
+bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
+{    
+	if (qualifier != EvqConst && qualifier != EvqTemporary) {
+		error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier), "");
+		return true;
+	}
+	if (qualifier == EvqConst && paramQualifier != EvqIn) {
+		error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
+		return true;
+	}
+
+	if (qualifier == EvqConst)
+		type->changeQualifier(EvqConstReadOnly);
+	else
+		type->changeQualifier(paramQualifier);
+
+	return false;
+}
+
+bool TParseContext::extensionErrorCheck(int line, const char* extension)
+{       
+	if (extensionBehavior[extension] == EBhWarn) {
+		infoSink.info.message(EPrefixWarning, ("extension " + TString(extension) + " is being used").c_str(), line);
+		return false;
+	}
+	if (extensionBehavior[extension] == EBhDisable) {
+		error(line, "extension", extension, "is disabled");
+		return true;
+	}
+
+	return false;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Non-Errors.
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+//
+// Look up a function name in the symbol table, and make sure it is a function.
+//
+// Return the function symbol if found, otherwise 0.
+//
+const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn)
+{
+	const TSymbol* symbol = symbolTable.find(call->getMangledName(), builtIn);
+
+	if (symbol == 0) {        
+		error(line, "no matching overloaded function found", call->getName().c_str(), "");
+		return 0;
+	}
+
+	if (! symbol->isFunction()) {
+		error(line, "function name expected", call->getName().c_str(), "");
+		return 0;
+	}
+	
+	const TFunction* function = static_cast<const TFunction*>(symbol);
+	
+	return function;
+}
+
+//
+// Initializers show up in several places in the grammar.  Have one set of
+// code to handle them here.
+//
+bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, 
+									   TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
+{
+	TType type = TType(pType);
+
+	if (variable == 0) {
+		if (reservedErrorCheck(line, identifier))
+			return true;
+
+		if (voidErrorCheck(line, identifier, pType))
+			return true;
+
+		//
+		// add variable to symbol table
+		//
+		variable = new TVariable(&identifier, type);
+		if (! symbolTable.insert(*variable)) {
+			error(line, "redefinition", variable->getName().c_str(), "");
+			return true;
+			// don't delete variable, it's used by error recovery, and the pool 
+			// pop will take care of the memory
+		}
+	}
+
+	//
+	// identifier must be of type constant, a global, or a temporary
+	//
+	TQualifier qualifier = variable->getType().getQualifier();
+	if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
+		error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString(), "");
+		return true;
+	}
+	//
+	// test for and propagate constant
+	//
+
+	if (qualifier == EvqConst) {
+		if (qualifier != initializer->getType().getQualifier()) {
+			error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
+			variable->getType().changeQualifier(EvqTemporary);
+			return true;
+		}
+		if (type != initializer->getType()) {
+			error(line, " non-matching types for const initializer ", 
+				variable->getType().getQualifierString(), "");
+			variable->getType().changeQualifier(EvqTemporary);
+			return true;
+		}
+		if (initializer->getAsConstantUnion()) { 
+			constUnion* unionArray = variable->getConstPointer();
+
+			if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) {
+				*unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0];
+			} else {
+				variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
+			}
+		} else if (initializer->getAsSymbolNode()) {
+			const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
+			const TVariable* tVar = static_cast<const TVariable*>(symbol);
+
+			constUnion* constArray = tVar->getConstPointer();
+			variable->shareConstPointer(constArray);
+		} else {
+			error(line, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().c_str());
+			variable->getType().changeQualifier(EvqTemporary);
+			return true;
+		}
+	}
+ 
+	if (qualifier != EvqConst) {
+		TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
+		intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
+		if (intermNode == 0) {
+			assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
+			return true;
+		}
+	} else 
+		intermNode = 0;
+
+	return false;
+}
+
+bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
+{
+	if (!aggrNode->isConstructor())
+		return false;
+
+	bool allConstant = true;
+
+	// check if all the child nodes are constants so that they can be inserted into 
+	// the parent node
+	if (aggrNode) {
+		TIntermSequence &childSequenceVector = aggrNode->getSequence() ;
+		for (TIntermSequence::iterator p = childSequenceVector.begin(); 
+									p != childSequenceVector.end(); p++) {
+			if (!(*p)->getAsTyped()->getAsConstantUnion())
+				return false;
+		}
+	}
+
+	return allConstant;
+}
+
+// This function is used to test for the correctness of the parameters passed to various constructor functions
+// and also convert them to the right datatype if it is allowed and required. 
+//
+// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
+//
+TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
+{
+	if (node == 0)
+		return 0;
+
+	TIntermAggregate* aggrNode = node->getAsAggregate();
+	
+	TTypeList::iterator memberTypes;
+	if (op == EOpConstructStruct)
+		memberTypes = type->getStruct()->begin();
+	
+	TType elementType = *type;
+	if (type->isArray())
+		elementType.clearArrayness();
+
+	bool singleArg;
+	if (aggrNode) {
+		if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
+			singleArg = true;
+		else
+			singleArg = false;
+	} else
+		singleArg = true;
+
+	TIntermTyped *newNode;
+	if (singleArg) {
+		// If structure constructor or array constructor is being called 
+		// for only one parameter inside the structure, we need to call constructStruct function once.
+		if (type->isArray())
+			newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
+		else if (op == EOpConstructStruct)
+			newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false);
+		else
+			newNode = constructBuiltIn(type, op, node, node->getLine(), false);
+
+		if (newNode && newNode->getAsAggregate()) {
+			TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type);
+			if (constConstructor)
+				return constConstructor;
+		}
+
+		return newNode;
+	}
+	
+	//
+	// Handle list of arguments.
+	//
+	TIntermSequence &sequenceVector = aggrNode->getSequence() ;    // Stores the information about the parameter to the constructor
+	// if the structure constructor contains more than one parameter, then construct
+	// each parameter
+	
+	int paramCount = 0;  // keeps a track of the constructor parameter number being checked    
+	
+	// for each parameter to the constructor call, check to see if the right type is passed or convert them 
+	// to the right type if possible (and allowed).
+	// for structure constructors, just check if the right type is passed, no conversion is allowed.
+	
+	for (TIntermSequence::iterator p = sequenceVector.begin(); 
+								   p != sequenceVector.end(); p++, paramCount++) {
+		if (type->isArray())
+			newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
+		else if (op == EOpConstructStruct)
+			newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true);
+		else
+			newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
+		
+		if (newNode) {
+			*p = newNode;
+		}
+	}
+
+	TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line);
+	TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
+	if (constConstructor)
+		return constConstructor;
+
+	return constructor;
+}
+
+TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
+{
+	bool canBeFolded = areAllChildConst(aggrNode);
+	aggrNode->setType(type);
+	if (canBeFolded) {
+		bool returnVal = false;
+		constUnion* unionArray = new constUnion[type.getObjectSize()];
+		if (aggrNode->getSequence().size() == 1)  {
+			returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable,  type, true);
+		}
+		else {
+			returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable,  type);
+		}
+		if (returnVal)
+			return 0;
+
+		return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
+	}
+
+	return 0;
+}
+
+// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
+// for the parameter to the constructor (passed to this function). Essentially, it converts
+// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a 
+// float, then float is converted to int.
+//
+// Returns 0 for an error or the constructed node.
+//
+TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset)
+{
+	TIntermTyped* newNode;
+	TOperator basicOp;
+
+	//
+	// First, convert types as needed.
+	//
+	switch (op) {
+	case EOpConstructVec2:
+	case EOpConstructVec3:
+	case EOpConstructVec4:
+	case EOpConstructMat2:
+	case EOpConstructMat3:
+	case EOpConstructMat4:
+	case EOpConstructFloat:
+		basicOp = EOpConstructFloat;
+		break;
+
+	case EOpConstructIVec2:
+	case EOpConstructIVec3:
+	case EOpConstructIVec4:
+	case EOpConstructInt:
+		basicOp = EOpConstructInt;
+		break;
+
+	case EOpConstructBVec2:
+	case EOpConstructBVec3:
+	case EOpConstructBVec4:
+	case EOpConstructBool:
+		basicOp = EOpConstructBool;
+		break;
+
+	default:
+		error(line, "unsupported construction", "", "");
+		recover();
+
+		return 0;
+	}
+	newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable);
+	if (newNode == 0) {
+		error(line, "can't convert", "constructor", "");
+		return 0;
+	}
+
+	//
+	// Now, if there still isn't an operation to do the construction, and we need one, add one.
+	//
+	
+	// Otherwise, skip out early.
+	if (subset || (newNode != node && newNode->getType() == *type))
+		return newNode;
+
+	// setAggregateOperator will insert a new node for the constructor, as needed.
+	return intermediate.setAggregateOperator(newNode, op, line);
+}
+
+// This function tests for the type of the parameters to the structures constructors. Raises
+// an error message if the expected type does not match the parameter passed to the constructor.
+//
+// Returns 0 for an error or the input node itself if the expected and the given parameter types match.
+//
+TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset)
+{
+	if (*type == node->getAsTyped()->getType()) {
+		if (subset)
+			return node->getAsTyped();
+		else
+			return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
+	} else {
+		error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
+				node->getAsTyped()->getType().getBasicString(), type->getBasicString());
+		recover();
+	}
+
+	return 0;
+}
+
+//
+// This function returns the tree representation for the vector field(s) being accessed from contant vector.
+// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
+// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
+// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of 
+// a constant matrix.
+//
+TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
+{
+	TIntermTyped* typedNode;
+	TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+
+	constUnion *unionArray;
+	if (tempConstantNode) {
+		unionArray = tempConstantNode->getUnionArrayPointer();
+
+		if (!unionArray) {  // this error message should never be raised
+			infoSink.info.message(EPrefixInternalError, "constUnion not initialized in addConstVectorNode function", line);
+			recover();
+
+			return node;
+		}
+	} else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
+		error(line, "Cannot offset into the vector", "Error", "");
+		recover();
+
+		return 0;
+	}
+
+	constUnion* constArray = new constUnion[fields.num];
+
+	for (int i = 0; i < fields.num; i++) {
+		if (fields.offsets[i] >= node->getType().getObjectSize()) {
+			error(line, "", "[", "vector field selection out of range '%d'", fields.offsets[i]);
+			recover();
+			fields.offsets[i] = 0;
+		}
+		
+		constArray[i] = unionArray[fields.offsets[i]];
+
+	} 
+	typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
+	return typedNode;
+}
+
+//
+// This function returns the column being accessed from a constant matrix. The values are retrieved from
+// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input 
+// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a 
+// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
+//
+TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
+{
+	TIntermTyped* typedNode;
+	TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+
+	if (index >= node->getType().getNominalSize()) {
+		error(line, "", "[", "matrix field selection out of range '%d'", index);
+		recover();
+		index = 0;
+	}
+
+	if (tempConstantNode) {
+		 constUnion* unionArray = tempConstantNode->getUnionArrayPointer();
+		 int size = tempConstantNode->getType().getNominalSize();
+		 typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
+	} else {
+		error(line, "Cannot offset into the matrix", "Error", "");
+		recover();
+
+		return 0;
+	}
+
+	return typedNode;
+}
+
+
+//
+// This function returns an element of an array accessed from a constant array. The values are retrieved from
+// the symbol table and parse-tree is built for the type of the element. The input 
+// to the function could either be a symbol node (a[0] where a is a constant array)that represents a 
+// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
+//
+TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line)
+{
+	TIntermTyped* typedNode;
+	TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+	TType arrayElementType = node->getType();
+	arrayElementType.clearArrayness();
+
+	if (index >= node->getType().getArraySize()) {
+		error(line, "", "[", "array field selection out of range '%d'", index);
+		recover();
+		index = 0;
+	}
+
+	int arrayElementSize = arrayElementType.getObjectSize();
+
+	if (tempConstantNode) {
+		 constUnion* unionArray = tempConstantNode->getUnionArrayPointer();
+		 typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
+	} else {
+		error(line, "Cannot offset into the array", "Error", "");
+		recover();
+
+		return 0;
+	}
+
+	return typedNode;
+}
+
+
+//
+// This function returns the value of a particular field inside a constant structure from the symbol table. 
+// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
+// function and returns the parse-tree with the values of the embedded/nested struct.
+//
+TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line)
+{
+	TTypeList* fields = node->getType().getStruct();
+	TIntermTyped *typedNode;
+	int instanceSize = 0;
+	unsigned int index = 0;
+	TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
+
+	for ( index = 0; index < fields->size(); ++index) {
+		if ((*fields)[index].type->getFieldName() == identifier) {
+			break;
+		} else {
+			instanceSize += (*fields)[index].type->getObjectSize();
+		}
+	}
+
+	if (tempConstantNode) {
+		 constUnion* constArray = tempConstantNode->getUnionArrayPointer();
+
+		 typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
+	} else {
+		error(line, "Cannot offset into the structure", "Error", "");
+		recover();
+
+		return 0;
+	}
+
+	return typedNode;
+}
+
+//
+// Initialize all supported extensions to disable
+//
+void TParseContext::initializeExtensionBehavior()
+{
+	//
+	// example code: extensionBehavior["test"] = EBhDisable; // where "test" is the name of 
+	// supported extension
+	//
+	extensionBehavior["GL_ARB_texture_rectangle"] = EBhRequire;
+	extensionBehavior["GL_3DL_array_objects"] = EBhDisable;
+}
+
+OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+
+bool InitializeParseContextIndex()
+{
+	if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
+		assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
+		return false;
+	}
+
+	//
+	// Allocate a TLS index.
+	//
+	GlobalParseContextIndex = OS_AllocTLSIndex();
+	
+	if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+		assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
+		return false;
+	}
+
+	return true;
+}
+
+bool InitializeGlobalParseContext()
+{
+	if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+		assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalised");
+		return false;
+	}
+
+	TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+	if (lpParseContext != 0) {
+		assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
+		return false;
+	}
+
+	TThreadParseContext *lpThreadData = new TThreadParseContext();
+	if (lpThreadData == 0) {
+		assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
+		return false;
+	}
+
+	lpThreadData->lpGlobalParseContext = 0;
+	OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
+
+	return true;
+}
+
+TParseContextPointer& GetGlobalParseContext()
+{
+	//
+	// Minimal error checking for speed
+	//
+
+	TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+
+	return lpParseContext->lpGlobalParseContext;
+}
+
+bool FreeParseContext()
+{
+	if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+		assert(0 && "FreeParseContext(): Parse Context index not initalised");
+		return false;
+	}
+
+	TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+	if (lpParseContext)
+		delete lpParseContext;
+
+	return true;
+}
+
+bool FreeParseContextIndex()
+{
+	OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
+
+	if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
+		assert(0 && "FreeParseContextIndex(): Parse Context index not initalised");
+		return false;
+	}
+
+	GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+
+	return OS_FreeTLSIndex(tlsiIndex);
+}
diff --git a/Compiler/ParseHelper.h b/Compiler/ParseHelper.h
new file mode 100644
index 0000000..bb61220
--- /dev/null
+++ b/Compiler/ParseHelper.h
@@ -0,0 +1,121 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef _PARSER_HELPER_INCLUDED_
+#define _PARSER_HELPER_INCLUDED_
+
+#include "ShHandle.h"
+#include "SymbolTable.h"
+#include "localintermediate.h"
+
+struct TMatrixFields {
+	bool wholeRow;
+	bool wholeCol;
+	int row;
+	int col;
+};
+
+typedef enum {
+	EBhRequire,
+	EBhEnable,
+	EBhWarn,
+	EBhDisable
+} TBehavior;
+
+struct TPragma {
+	TPragma(bool o, bool d) : optimize(o), debug(d) { }
+	bool optimize;
+	bool debug;
+	TPragmaTable pragmaTable;
+};
+
+//
+// The following are extra variables needed during parsing, grouped together so
+// they can be passed to the parser without needing a global.
+//
+struct TParseContext {
+	TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is) :
+			intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0),
+			recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0),
+			inTypeParen(false), contextPragma(true, false) {  }
+	TIntermediate& intermediate; // to hold and build a parse tree
+	TSymbolTable& symbolTable;   // symbol table that goes with the language currently being parsed
+	TInfoSink& infoSink;
+	EShLanguage language;        // vertex or fragment language (future: pack or unpack)
+	TIntermNode* treeRoot;       // root of parse tree being created
+	bool recoveredFromError;     // true if a parse error has occurred, but we continue to parse
+	int numErrors;
+	bool lexAfterType;           // true if we've recognized a type, so can only be looking for an identifier
+	int loopNestingLevel;        // 0 if outside all loops
+	bool inTypeParen;            // true if in parentheses, looking only for an identifier
+	const TType* currentFunctionType;  // the return type of the function that's currently being parsed
+	bool functionReturnsValue;   // true if a non-void function has a return
+	TMap<TString, TBehavior> extensionBehavior;
+	void initializeExtensionBehavior();
+
+	void C_DECL error(TSourceLoc, const char *szReason, const char *szToken,
+					  const char *szExtraInfoFormat, ...);
+	bool reservedErrorCheck(int line, const TString& identifier);
+	void recover();
+
+	bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
+	bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line);
+	void assignError(int line, const char* op, TString left, TString right);
+	void unaryOpError(int line, const char* op, TString operand);
+	void binaryOpError(int line, const char* op, TString left, TString right);
+	bool lValueErrorCheck(int line, const char* op, TIntermTyped*);
+	bool constErrorCheck(TIntermTyped* node);
+	bool integerErrorCheck(TIntermTyped* node, const char* token);
+	bool globalErrorCheck(int line, bool global, const char* token);
+	bool constructorErrorCheck(int line, TIntermNode*, TFunction&, TOperator, TType*);
+	bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size);
+	bool arrayQualifierErrorCheck(int line, TPublicType type);
+	bool arrayTypeErrorCheck(int line, TPublicType type);
+	bool arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable);
+	bool voidErrorCheck(int, const TString&, const TPublicType&);
+	bool boolErrorCheck(int, const TIntermTyped*);
+	bool boolErrorCheck(int, const TPublicType&);
+	bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
+	bool structQualifierErrorCheck(int line, const TPublicType& pType);
+	bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type);
+	bool containsSampler(TType& type);
+	bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type);
+	bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type);
+	bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
+	bool extensionErrorCheck(int line, const char*);
+	const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
+	bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
+							TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
+	bool areAllChildConst(TIntermAggregate* aggrNode);
+	TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc);
+	TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
+	TIntermTyped* constructStruct(TIntermNode*, TType*, int, TSourceLoc, bool subset);
+	TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, TSourceLoc, bool subset);
+	TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
+	TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
+	TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);
+	TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
+	bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
+	struct TPragma contextPragma;
+	TString HashErrMsg;
+	bool AfterEOF;
+};
+
+int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext&);
+void PaReservedWord();
+int PaIdentOrType(TString& id, TParseContext&, TSymbol*&);
+int PaParseComment(int &lineno, TParseContext&);
+void setInitialState();
+
+typedef TParseContext* TParseContextPointer;
+extern TParseContextPointer& GetGlobalParseContext();
+#define GlobalParseContext GetGlobalParseContext()
+
+typedef struct TThreadParseContextRec
+{
+	TParseContext *lpGlobalParseContext;
+} TThreadParseContext;
+
+#endif // _PARSER_HELPER_INCLUDED_
diff --git a/Compiler/PoolAlloc.cpp b/Compiler/PoolAlloc.cpp
new file mode 100644
index 0000000..013e752
--- /dev/null
+++ b/Compiler/PoolAlloc.cpp
@@ -0,0 +1,314 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "PoolAlloc.h"
+#include "Common.h"
+
+#include "InitializeGlobals.h"
+#include "osinclude.h"
+
+OS_TLSIndex PoolIndex = TLS_OUT_OF_INDEXES;
+
+void InitializeGlobalPools()
+{
+	TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));    
+	if (globalPools)
+		return;
+
+	TPoolAllocator *globalPoolAllocator = new TPoolAllocator(true);
+
+	TThreadGlobalPools* threadData = new TThreadGlobalPools();
+	
+	threadData->globalPoolAllocator = globalPoolAllocator;
+		
+	OS_SetTLSValue(PoolIndex, threadData);     
+	globalPoolAllocator->push();
+}
+
+void FreeGlobalPools()
+{
+	// Release the allocated memory for this thread.
+	TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));    
+	if (!globalPools)
+		return;
+	
+	GlobalPoolAllocator.popAll();
+	delete &GlobalPoolAllocator;       
+	delete globalPools;
+}
+
+bool InitializePoolIndex()
+{
+	// Allocate a TLS index.
+	if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
+		return false;
+
+	return true;
+}
+
+void FreePoolIndex()
+{
+	// Release the TLS index.
+	OS_FreeTLSIndex(PoolIndex);
+}
+
+TPoolAllocator& GetGlobalPoolAllocator()
+{
+	TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
+
+	return *threadData->globalPoolAllocator;
+}
+
+void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator)
+{
+	TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
+
+	threadData->globalPoolAllocator = poolAllocator;
+}
+
+//
+// Implement the functionality of the TPoolAllocator class, which
+// is documented in PoolAlloc.h.
+//
+TPoolAllocator::TPoolAllocator(bool g, int growthIncrement, int allocationAlignment) : 
+	global(g),
+	pageSize(growthIncrement),
+	alignment(allocationAlignment),
+	freeList(0),
+	inUseList(0),
+	numCalls(0)
+{
+	//
+	// Don't allow page sizes we know are smaller than all common
+	// OS page sizes.
+	//
+	if (pageSize < 4*1024)
+		pageSize = 4*1024;
+
+	//
+	// A large currentPageOffset indicates a new page needs to
+	// be obtained to allocate memory.
+	//
+	currentPageOffset = pageSize;
+
+	//
+	// Adjust alignment to be at least pointer aligned and
+	// power of 2.
+	//
+	size_t minAlign = sizeof(void*);
+	alignment &= ~(minAlign - 1);
+	if (alignment < minAlign)
+		alignment = minAlign;
+	size_t a = 1;
+	while (a < alignment)
+		a <<= 1;
+	alignment = a;
+	alignmentMask = a - 1;
+
+	//
+	// Align header skip
+	//
+	headerSkip = minAlign;
+	if (headerSkip < sizeof(tHeader)) {
+		headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
+	}
+}
+
+TPoolAllocator::~TPoolAllocator()
+{
+	if (!global) {
+		//
+		// Then we know that this object is not being 
+		// allocated after other, globally scoped objects
+		// that depend on it.  So we can delete the "in use" memory.
+		//
+		while (inUseList) {
+			tHeader* next = inUseList->nextPage;
+			inUseList->~tHeader();
+			delete [] reinterpret_cast<char*>(inUseList);
+			inUseList = next;
+		}
+	}
+
+	//
+	// Always delete the free list memory - it can't be being
+	// (correctly) referenced, whether the pool allocator was
+	// global or not.  We should not check the guard blocks
+	// here, because we did it already when the block was
+	// placed into the free list.
+	//
+	while (freeList) {
+		tHeader* next = freeList->nextPage;
+		delete [] reinterpret_cast<char*>(freeList);
+		freeList = next;
+	}
+}
+
+// Support MSVC++ 6.0
+const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
+const unsigned char TAllocation::guardBlockEndVal   = 0xfe;
+const unsigned char TAllocation::userDataFill       = 0xcd;
+
+#   ifdef GUARD_BLOCKS
+	const size_t TAllocation::guardBlockSize = 16;
+#   else
+	const size_t TAllocation::guardBlockSize = 0;
+#   endif
+
+//
+// Check a single guard block for damage
+//
+void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
+{
+	for (size_t x = 0; x < guardBlockSize; x++) {
+		if (blockMem[x] != val) {
+			char assertMsg[80];
+
+			// We don't print the assert message.  It's here just to be helpful.
+			sprintf(assertMsg, "PoolAlloc: Damage %s %lu byte allocation at 0x%p\n",
+					locText, size, data());
+			assert(0 && "PoolAlloc: Damage in guard block");
+		}
+	}
+}
+
+
+void TPoolAllocator::push()
+{
+	tAllocState state = { currentPageOffset, inUseList };
+
+	stack.push_back(state);
+		
+	//
+	// Indicate there is no current page to allocate from.
+	//
+	currentPageOffset = pageSize;
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred since the last push(), or since the
+// last pop(), or since the object's creation.
+//
+// The deallocated pages are saved for future allocations.
+//
+void TPoolAllocator::pop()
+{
+	if (stack.size() < 1)
+		return;
+
+	tHeader* page = stack.back().page;
+	currentPageOffset = stack.back().offset;
+
+	while (inUseList != page) {
+		// invoke destructor to free allocation list
+		inUseList->~tHeader();
+		
+		tHeader* nextInUse = inUseList->nextPage;
+		if (inUseList->pageCount > 1)
+			delete [] reinterpret_cast<char*>(inUseList);
+		else {
+			inUseList->nextPage = freeList;
+			freeList = inUseList;
+		}
+		inUseList = nextInUse;
+	}
+
+	stack.pop_back();
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred.
+//
+void TPoolAllocator::popAll()
+{
+	while (stack.size() > 0)
+		pop();
+}
+
+void* TPoolAllocator::allocate(size_t numBytes)
+{
+	// If we are using guard blocks, all allocations are bracketed by
+	// them: [guardblock][allocation][guardblock].  numBytes is how
+	// much memory the caller asked for.  allocationSize is the total
+	// size including guard blocks.  In release build,
+	// guardBlockSize=0 and this all gets optimized away.
+	size_t allocationSize = TAllocation::allocationSize(numBytes);
+	
+	//
+	// Just keep some interesting statistics.
+	//
+	++numCalls;
+	totalBytes += numBytes;
+
+	//
+	// Do the allocation, most likely case first, for efficiency.
+	// This step could be moved to be inline sometime.
+	//
+	if (currentPageOffset + allocationSize <= pageSize) {
+		//
+		// Safe to allocate from currentPageOffset.
+		//
+		unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
+		currentPageOffset += allocationSize;
+		currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;
+
+		return initializeAllocation(inUseList, memory, numBytes);
+	}
+
+	if (allocationSize + headerSkip > pageSize) {
+		//
+		// Do a multi-page allocation.  Don't mix these with the others.
+		// The OS is efficient and allocating and free-ing multiple pages.
+		//
+		size_t numBytesToAlloc = allocationSize + headerSkip;
+		tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
+		if (memory == 0)
+			return 0;
+
+		// Use placement-new to initialize header
+		new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
+		inUseList = memory;
+
+		currentPageOffset = pageSize;  // make next allocation come from a new page
+
+		// No guard blocks for multi-page allocations (yet)
+		return reinterpret_cast<void*>(reinterpret_cast<UINT_PTR>(memory) + headerSkip);
+	}
+
+	//
+	// Need a simple page to allocate from.
+	//
+	tHeader* memory;
+	if (freeList) {
+		memory = freeList;
+		freeList = freeList->nextPage;
+	} else {
+		memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
+		if (memory == 0)
+			return 0;
+	}
+
+	// Use placement-new to initialize header
+	new(memory) tHeader(inUseList, 1);
+	inUseList = memory;
+	
+	unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
+	currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
+
+	return initializeAllocation(inUseList, ret, numBytes);
+}
+
+
+//
+// Check all allocations in a list for damage by calling check on each.
+//
+void TAllocation::checkAllocList() const
+{
+	for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
+		alloc->check();
+}
diff --git a/Compiler/PoolAlloc.h b/Compiler/PoolAlloc.h
new file mode 100644
index 0000000..bd417b7
--- /dev/null
+++ b/Compiler/PoolAlloc.h
@@ -0,0 +1,321 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _POOLALLOC_INCLUDED_
+#define _POOLALLOC_INCLUDED_
+
+#ifdef _DEBUG
+#  define GUARD_BLOCKS  // define to enable guard block sanity checking
+#endif
+
+//
+// This header defines an allocator that can be used to efficiently
+// allocate a large number of small requests for heap memory, with the 
+// intention that they are not individually deallocated, but rather 
+// collectively deallocated at one time.
+//
+// This simultaneously
+//
+// * Makes each individual allocation much more efficient; the
+//     typical allocation is trivial.
+// * Completely avoids the cost of doing individual deallocation.
+// * Saves the trouble of tracking down and plugging a large class of leaks.
+//
+// Individual classes can use this allocator by supplying their own
+// new and delete methods.
+//
+// STL containers can use this allocator by using the pool_allocator
+// class as the allocator (second) template argument.
+//
+
+#include <stddef.h>
+#include <vector>
+
+// If we are using guard blocks, we must track each indivual
+// allocation.  If we aren't using guard blocks, these
+// never get instantiated, so won't have any impact.
+// 
+
+class TAllocation {
+public:
+	TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) :
+		size(size), mem(mem), prevAlloc(prev) {
+		// Allocations are bracketed:
+		//    [allocationHeader][initialGuardBlock][userData][finalGuardBlock]
+		// This would be cleaner with if (guardBlockSize)..., but that
+		// makes the compiler print warnings about 0 length memsets,
+		// even with the if() protecting them.
+#       ifdef GUARD_BLOCKS
+			memset(preGuard(),  guardBlockBeginVal, guardBlockSize);
+			memset(data(),      userDataFill,       size);
+			memset(postGuard(), guardBlockEndVal,   guardBlockSize);
+#       endif
+	}
+	
+	void check() const {
+		checkGuardBlock(preGuard(),  guardBlockBeginVal, "before");
+		checkGuardBlock(postGuard(), guardBlockEndVal,   "after");
+	}
+
+	void checkAllocList() const;
+
+	// Return total size needed to accomodate user buffer of 'size',
+	// plus our tracking data.
+	inline static size_t allocationSize(size_t size) {
+		return size + 2 * guardBlockSize + headerSize();
+	}
+	
+	// Offset from surrounding buffer to get to user data buffer.
+	inline static unsigned char* offsetAllocation(unsigned char* m) {
+		return m + guardBlockSize + headerSize();
+	}
+
+private:
+	void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const;
+
+	// Find offsets to pre and post guard blocks, and user data buffer
+	unsigned char* preGuard()  const { return mem + headerSize(); }
+	unsigned char* data()      const { return preGuard() + guardBlockSize; }
+	unsigned char* postGuard() const { return data() + size; }
+
+	size_t size;                  // size of the user data area
+	unsigned char* mem;           // beginning of our allocation (pts to header)
+	TAllocation* prevAlloc;       // prior allocation in the chain
+
+	// Support MSVC++ 6.0
+	const static unsigned char guardBlockBeginVal;
+	const static unsigned char guardBlockEndVal;
+	const static unsigned char userDataFill;
+
+	const static size_t guardBlockSize;
+#   ifdef GUARD_BLOCKS    
+	inline static size_t headerSize() { return sizeof(TAllocation); }
+#   else
+	inline static size_t headerSize() { return 0; }
+#   endif
+};
+	
+//
+// There are several stacks.  One is to track the pushing and popping
+// of the user, and not yet implemented.  The others are simply a 
+// repositories of free pages or used pages.
+//
+// Page stacks are linked together with a simple header at the beginning
+// of each allocation obtained from the underlying OS.  Multi-page allocations
+// are returned to the OS.  Individual page allocations are kept for future
+// re-use.
+//
+// The "page size" used is not, nor must it match, the underlying OS
+// page size.  But, having it be about that size or equal to a set of 
+// pages is likely most optimal.
+//
+class TPoolAllocator {
+public:
+	TPoolAllocator(bool global = false, int growthIncrement = 8*1024, int allocationAlignment = 16);
+
+	//
+	// Don't call the destructor just to free up the memory, call pop()
+	//
+	~TPoolAllocator();
+
+	//
+	// Call push() to establish a new place to pop memory too.  Does not
+	// have to be called to get things started.
+	//
+	void push();
+
+	//
+	// Call pop() to free all memory allocated since the last call to push(),
+	// or if no last call to push, frees all memory since first allocation.
+	//
+	void pop();
+
+	//
+	// Call popAll() to free all memory allocated.
+	//
+	void popAll();
+
+	//
+	// Call allocate() to actually acquire memory.  Returns 0 if no memory
+	// available, otherwise a properly aligned pointer to 'numBytes' of memory.
+	//
+	void* allocate(size_t numBytes);
+
+	//
+	// There is no deallocate.  The point of this class is that
+	// deallocation can be skipped by the user of it, as the model
+	// of use is to simultaneously deallocate everything at once
+	// by calling pop(), and to not have to solve memory leak problems.
+	//
+
+protected:
+	friend struct tHeader;
+	
+	struct tHeader {
+		tHeader(tHeader* nextPage, size_t pageCount) :
+#ifdef GUARD_BLOCKS
+		lastAllocation(0),
+#endif
+		nextPage(nextPage), pageCount(pageCount) { }
+
+		~tHeader() {
+#ifdef GUARD_BLOCKS
+			if (lastAllocation)
+				lastAllocation->checkAllocList();
+#endif
+		}
+
+		tHeader* nextPage;
+		size_t pageCount;
+#ifdef GUARD_BLOCKS
+		TAllocation* lastAllocation;
+#endif
+	};
+
+	struct tAllocState {
+		size_t offset;
+		tHeader* page;
+	};
+	typedef std::vector<tAllocState> tAllocStack;
+
+	// Track allocations if and only if we're using guard blocks
+	void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) {
+#       ifdef GUARD_BLOCKS
+		new(memory) TAllocation(numBytes, memory, block->lastAllocation);
+		block->lastAllocation = reinterpret_cast<TAllocation*>(memory);
+#       endif
+
+		// This is optimized entirely away if GUARD_BLOCKS is not defined.
+		return TAllocation::offsetAllocation(memory);
+	}
+
+	bool global;            // should be true if this object is globally scoped
+	size_t pageSize;        // granularity of allocation from the OS
+	size_t alignment;       // all returned allocations will be aligned at 
+							//      this granularity, which will be a power of 2
+	size_t alignmentMask;
+	size_t headerSkip;      // amount of memory to skip to make room for the
+							//      header (basically, size of header, rounded
+							//      up to make it aligned
+	size_t currentPageOffset;  // next offset in top of inUseList to allocate from
+	tHeader* freeList;      // list of popped memory
+	tHeader* inUseList;     // list of all memory currently being used
+	tAllocStack stack;      // stack of where to allocate from, to partition pool
+
+	int numCalls;           // just an interesting statistic
+	size_t totalBytes;      // just an interesting statistic
+private:
+	TPoolAllocator& operator=(const TPoolAllocator&);  // dont allow assignment operator
+	TPoolAllocator(const TPoolAllocator&);  // dont allow default copy constructor
+};
+
+
+//
+// There could potentially be many pools with pops happening at
+// different times.  But a simple use is to have a global pop
+// with everyone using the same global allocator.
+//
+typedef TPoolAllocator* PoolAllocatorPointer;
+extern TPoolAllocator& GetGlobalPoolAllocator();
+#define GlobalPoolAllocator GetGlobalPoolAllocator()
+
+
+struct TThreadGlobalPools
+{
+		TPoolAllocator* globalPoolAllocator;
+};
+
+void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator);
+
+//
+// This STL compatible allocator is intended to be used as the allocator
+// parameter to templatized STL containers, like vector and map.
+//
+// It will use the pools for allocation, and not
+// do any deallocation, but will still do destruction.
+//
+template<class T>
+class pool_allocator {
+public:
+	typedef size_t size_type;
+	typedef ptrdiff_t difference_type;
+	typedef T *pointer;
+	typedef const T *const_pointer;
+	typedef T& reference;
+	typedef const T& const_reference;
+	typedef T value_type;
+	template<class Other> 
+		struct rebind {
+			typedef pool_allocator<Other> other;
+		};
+	pointer address(reference x) const { return &x; }
+	const_pointer address(const_reference x) const { return &x; }
+
+#ifdef USING_SGI_STL
+	pool_allocator()  { }
+#else
+	pool_allocator() : allocator(GlobalPoolAllocator) { }
+	pool_allocator(TPoolAllocator& a) : allocator(a) { }
+	pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1300
+	template<class Other>
+#ifdef USING_SGI_STL
+		pool_allocator(const pool_allocator<Other>& p) /*: allocator(p.getAllocator())*/ { }
+#else
+		pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
+#endif
+#endif
+
+#ifndef _WIN32
+		template<class Other>
+			pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
+#endif
+
+#ifdef USING_SGI_STL
+	static pointer allocate(size_type n) { 
+		return reinterpret_cast<pointer>(getAllocator().allocate(n)); }
+	pointer allocate(size_type n, const void*) { 
+		return reinterpret_cast<pointer>(getAllocator().allocate(n)); }
+
+	static void deallocate(void*, size_type) { }
+	static void deallocate(pointer, size_type) { }
+#else
+	pointer allocate(size_type n) { 
+		return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); }
+	pointer allocate(size_type n, const void*) { 
+		return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); }
+
+	void deallocate(void*, size_type) { }
+	void deallocate(pointer, size_type) { }
+#endif
+
+	pointer _Charalloc(size_t n) {
+		return reinterpret_cast<pointer>(getAllocator().allocate(n)); }
+
+	void construct(pointer p, const T& val) { new ((void *)p) T(val); }
+	void destroy(pointer p) { p->T::~T(); }
+
+	bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); }
+	bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); }
+
+	size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); }
+	size_type max_size(int size) const { return static_cast<size_type>(-1) / size; }
+
+#ifdef USING_SGI_STL
+	//void setAllocator(TPoolAllocator* a) { allocator = a; }
+	static  TPoolAllocator& getAllocator() { return GlobalPoolAllocator; }
+#else
+	void setAllocator(TPoolAllocator* a) { allocator = *a; }
+	TPoolAllocator& getAllocator() const { return allocator; }
+
+protected:
+	TPoolAllocator& allocator;
+#endif
+};
+
+#endif // _POOLALLOC_INCLUDED_
diff --git a/Compiler/Preprocessor/atom.c b/Compiler/Preprocessor/atom.c
new file mode 100644
index 0000000..204fb0d
--- /dev/null
+++ b/Compiler/Preprocessor/atom.c
@@ -0,0 +1,740 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+//
+// atom.c
+//
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "slglobals.h"
+
+#undef malloc
+#undef realloc
+#undef free
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////// String table: //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+static const struct {
+    int val;
+    const char *str;
+} tokens[] = {
+    { CPP_AND_OP,         "&&" },
+    { CPP_AND_ASSIGN,     "&=" },
+    { CPP_SUB_ASSIGN,     "-=" },
+    { CPP_MOD_ASSIGN,     "%=" },
+    { CPP_ADD_ASSIGN,     "+=" },
+    { CPP_DIV_ASSIGN,     "/=" },
+    { CPP_MUL_ASSIGN,     "*=" },
+    { CPP_RIGHT_BRACKET,  ":>" },
+    { CPP_EQ_OP,          "==" },
+    { CPP_XOR_OP,         "^^" }, 
+    { CPP_XOR_ASSIGN,     "^=" }, 
+    { CPP_FLOATCONSTANT,  "<float-const>" },
+    { CPP_GE_OP,          ">=" },
+    { CPP_RIGHT_OP,       ">>" },
+    { CPP_RIGHT_ASSIGN,   ">>=" }, 
+    { CPP_IDENTIFIER,     "<ident>" },
+    { CPP_INTCONSTANT,    "<int-const>" },
+    { CPP_LE_OP,          "<=" },
+    { CPP_LEFT_OP,        "<<" },
+    { CPP_LEFT_ASSIGN,    "<<=" },
+    { CPP_LEFT_BRACKET,   "<:" },
+    { CPP_LEFT_BRACE,     "<%" }, 
+    { CPP_DEC_OP,         "--" },
+    { CPP_RIGHT_BRACE,    "%>" }, 
+    { CPP_NE_OP,          "!=" },
+    { CPP_OR_OP,          "||" },
+    { CPP_OR_ASSIGN,      "|=" }, 
+    { CPP_INC_OP,         "++" },
+    { CPP_STRCONSTANT,    "<string-const>" },
+    { CPP_TYPEIDENTIFIER, "<type-ident>" },
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////// String table: //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define INIT_STRING_TABLE_SIZE 16384
+
+typedef struct StringTable_Rec {
+    char *strings;
+    int nextFree;
+    int size;
+} StringTable;
+
+/*
+ * InitStringTable() - Initialize the string table.
+ *
+ */
+
+static int InitStringTable(StringTable *stable)
+{
+    stable->strings = (char *) malloc(INIT_STRING_TABLE_SIZE);
+    if (!stable->strings)
+        return 0;
+    // Zero-th offset means "empty" so don't use it.
+    stable->nextFree = 1;
+    stable->size = INIT_STRING_TABLE_SIZE;
+    return 1;
+} // InitStringTable
+
+/*
+ * FreeStringTable() - Free the string table.
+ *
+ */
+
+static void FreeStringTable(StringTable *stable)
+{
+    if (stable->strings)
+        free(stable->strings);
+    stable->strings = NULL;
+    stable->nextFree = 0;
+    stable->size = 0;
+} // FreeStringTable
+
+/*
+ * HashString() - Hash a string with the base hash function.
+ *
+ */
+
+static int HashString(const char *s)
+{
+    int hval = 0;
+
+    while (*s) {
+        hval = (hval*13507 + *s*197) ^ (hval >> 2);
+        s++;
+    }
+    return hval & 0x7fffffff;
+} // HashString
+
+/*
+ * HashString2() - Hash a string with the incrimenting hash function.
+ *
+ */
+
+static int HashString2(const char *s)
+{
+    int hval = 0;
+
+    while (*s) {
+        hval = (hval*729 + *s*37) ^ (hval >> 1);
+        s++;
+    }
+    return hval;
+} // HashString2
+
+/*
+ * AddString() - Add a string to a string table.  Return it's offset.
+ *
+ */
+
+static int AddString(StringTable *stable, const char *s)
+{
+    int len, loc;
+    char *str;
+
+    len = (int) strlen(s);
+    if (stable->nextFree + len + 1 >= stable->size) {
+        assert(stable->size < 1000000);
+        str = (char *) malloc(stable->size*2);
+        memcpy(str, stable->strings, stable->size);
+        free(stable->strings);
+        stable->strings = str;
+    }
+    loc = stable->nextFree;
+    strcpy(&stable->strings[loc], s);
+    stable->nextFree += len + 1;
+    return loc;
+} // AddString
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////// Hash table: ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define INIT_HASH_TABLE_SIZE 2047
+#define HASH_TABLE_MAX_COLLISIONS 3
+
+typedef struct HashEntry_Rec {
+    int index;      // String table offset of string representation
+    int value;      // Atom (symbol) value
+} HashEntry;
+
+typedef struct HashTable_Rec {
+    HashEntry *entry;
+    int size;
+    int entries;
+    int counts[HASH_TABLE_MAX_COLLISIONS + 1];
+} HashTable;
+
+/*
+ * InitHashTable() - Initialize the hash table.
+ *
+ */
+
+static int InitHashTable(HashTable *htable, int fsize)
+{
+    int ii;
+
+    htable->entry = (HashEntry *) malloc(sizeof(HashEntry)*fsize);
+    if (!htable->entry)
+        return 0;
+    htable->size = fsize;
+    for (ii = 0; ii < fsize; ii++) {
+        htable->entry[ii].index = 0;
+        htable->entry[ii].value = 0;
+    }
+    htable->entries = 0;
+    for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++)
+        htable->counts[ii] = 0;
+    return 1;
+} // InitHashTable
+
+/*
+ * FreeHashTable() - Free the hash table.
+ *
+ */
+
+static void FreeHashTable(HashTable *htable)
+{
+    if (htable->entry)
+        free(htable->entry);
+    htable->entry = NULL;
+    htable->size = 0;
+    htable->entries = 0;
+} // FreeHashTable
+
+/*
+ * Empty() - See if a hash table entry is empty.
+ *
+ */
+
+static int Empty(HashTable *htable, int hashloc)
+{
+    assert(hashloc >= 0 && hashloc < htable->size);
+    if (htable->entry[hashloc].index == 0) {
+        return 1;
+    } else {
+        return 0;
+    }
+} // Empty
+
+/*
+ * Match() - See if a hash table entry is matches a string.
+ *
+ */
+
+static int Match(HashTable *htable, StringTable *stable, const char *s, int hashloc)
+{
+    int strloc;
+
+    strloc = htable->entry[hashloc].index;
+    if (!strcmp(s, &stable->strings[strloc])) {
+        return 1;
+    } else {
+        return 0;
+    }
+} // Match
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////// Atom table: ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define INIT_ATOM_TABLE_SIZE 1024
+
+
+struct AtomTable_Rec {
+    StringTable stable; // String table.
+    HashTable htable;   // Hashes string to atom number and token value.  Multiple strings can
+                        // have the same token value but each unique string is a unique atom.
+    int *amap;          // Maps atom value to offset in string table.  Atoms all map to unique
+                        // strings except for some undefined values in the lower, fixed part
+                        // of the atom table that map to "<undefined>".  The lowest 256 atoms
+                        // correspond to single character ASCII values except for alphanumeric
+                        // characters and '_', which can be other tokens.  Next come the
+                        // language tokens with their atom values equal to the token value.
+                        // Then come predefined atoms, followed by user specified identifiers.
+    int *arev;          // Reversed atom for symbol table use.
+    int nextFree;
+    int size;
+};
+
+static AtomTable latable = { { 0 } };
+AtomTable *atable = &latable;
+
+static int AddAtomFixed(AtomTable *atable, const char *s, int atom);
+
+/*
+ * GrowAtomTable() - Grow the atom table to at least "size" if it's smaller.
+ *
+ */
+
+static int GrowAtomTable(AtomTable *atable, int size)
+{
+    int *newmap, *newrev;
+
+    if (atable->size < size) {
+        if (atable->amap) {
+            newmap = realloc(atable->amap, sizeof(int)*size);
+            newrev = realloc(atable->arev, sizeof(int)*size);
+        } else {
+            newmap = malloc(sizeof(int)*size);
+            newrev = malloc(sizeof(int)*size);
+            atable->size = 0;
+        }
+        if (!newmap || !newrev) {
+            /* failed to grow -- error */
+            if (newmap)
+                atable->amap = newmap;
+            if (newrev)
+                atable->amap = newrev;
+            return -1;
+        }
+        memset(&newmap[atable->size], 0, (size - atable->size) * sizeof(int));
+        memset(&newrev[atable->size], 0, (size - atable->size) * sizeof(int));
+        atable->amap = newmap;
+        atable->arev = newrev;
+        atable->size = size;
+    }
+    return 0;
+} // GrowAtomTable
+
+/*
+ * lReverse() - Reverse the bottom 20 bits of a 32 bit int.
+ *
+ */
+
+static int lReverse(int fval)
+{
+    unsigned int in = fval;
+    int result = 0, cnt = 0;
+
+    while(in) {
+        result <<= 1;
+        result |= in&1;
+        in >>= 1;
+        cnt++;
+    }
+
+    // Don't use all 31 bits.  One million atoms is plenty and sometimes the
+    // upper bits are used for other things.
+
+    if (cnt < 20)
+        result <<= 20 - cnt;
+    return result;
+} // lReverse
+
+/*
+ * AllocateAtom() - Allocate a new atom.  Associated with the "undefined" value of -1.
+ *
+ */
+
+static int AllocateAtom(AtomTable *atable)
+{
+    if (atable->nextFree >= atable->size)
+        GrowAtomTable(atable, atable->nextFree*2);
+    atable->amap[atable->nextFree] = -1;
+    atable->arev[atable->nextFree] = lReverse(atable->nextFree);
+    atable->nextFree++;
+    return atable->nextFree - 1;
+} // AllocateAtom
+
+/*
+ * SetAtomValue() - Allocate a new atom associated with "hashindex".
+ *
+ */
+
+static void SetAtomValue(AtomTable *atable, int atomnumber, int hashindex)
+{
+    atable->amap[atomnumber] = atable->htable.entry[hashindex].index;
+    atable->htable.entry[hashindex].value = atomnumber;
+} // SetAtomValue
+
+/*
+ * FindHashLoc() - Find the hash location for this string.  Return -1 it hash table is full.
+ *
+ */
+
+static int FindHashLoc(AtomTable *atable, const char *s)
+{
+    int hashloc, hashdelta, count;
+    int FoundEmptySlot = 0;
+    int collision[HASH_TABLE_MAX_COLLISIONS + 1];
+
+    hashloc = HashString(s) % atable->htable.size;
+    if (!Empty(&atable->htable, hashloc)) {
+        if (Match(&atable->htable, &atable->stable, s, hashloc))
+            return hashloc;
+        collision[0] = hashloc;
+        hashdelta = HashString2(s);
+        count = 0;
+        while (count < HASH_TABLE_MAX_COLLISIONS) {
+            hashloc = ((hashloc + hashdelta) & 0x7fffffff) % atable->htable.size;
+            if (!Empty(&atable->htable, hashloc)) {
+                if (Match(&atable->htable, &atable->stable, s, hashloc)) {
+                    return hashloc;
+                }
+            } else {
+                FoundEmptySlot = 1;
+                break;
+            }
+            count++;
+            collision[count] = hashloc;
+        }
+
+        if (!FoundEmptySlot) {
+            if (cpp->options.DumpAtomTable) {
+                int ii;
+                char str[200];
+                sprintf(str, "*** Hash failed with more than %d collisions. Must increase hash table size. ***",
+                       HASH_TABLE_MAX_COLLISIONS);
+                CPPShInfoLogMsg(str);
+
+                sprintf(str, "*** New string \"%s\", hash=%04x, delta=%04x", s, collision[0], hashdelta);
+                CPPShInfoLogMsg(str);
+                for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++) {
+                    sprintf(str, "*** Collides on try %d at hash entry %04x with \"%s\"",
+                           ii + 1, collision[ii], GetAtomString(atable, atable->htable.entry[collision[ii]].value));
+                    CPPShInfoLogMsg(str);
+                }
+            }
+            return -1;
+        } else {
+            atable->htable.counts[count]++;
+        }
+    }
+    return hashloc;
+} // FindHashLoc
+
+/*
+ * IncreaseHashTableSize()
+ *
+ */
+
+static int IncreaseHashTableSize(AtomTable *atable)
+{
+    int ii, strloc, oldhashloc, value, size;
+    AtomTable oldtable;
+    char *s;
+
+    // Save the old atom table and create a new one:
+
+    oldtable = *atable;
+    size = oldtable.htable.size*2 + 1;
+    if (!InitAtomTable(atable, size))
+        return 0;
+
+    // Add all the existing values to the new atom table preserving their atom values:
+
+    for (ii = atable->nextFree; ii < oldtable.nextFree; ii++) {
+        strloc = oldtable.amap[ii];
+        s = &oldtable.stable.strings[strloc];
+        oldhashloc = FindHashLoc(&oldtable, s);
+        assert(oldhashloc >= 0);
+        value = oldtable.htable.entry[oldhashloc].value;
+        AddAtomFixed(atable, s, value);
+    }
+    FreeAtomTable(&oldtable);
+    return 1;
+} // IncreaseHashTableSize
+
+/*
+ * LookUpAddStringHash() - Lookup a string in the hash table.  If it's not there, add it and
+ *        initialize the atom value in the hash table to 0.  Return the hash table index.
+ */
+
+static int LookUpAddStringHash(AtomTable *atable, const char *s)
+{
+    int hashloc, strloc;
+
+    while(1) {
+        hashloc = FindHashLoc(atable, s);
+        if (hashloc >= 0)
+            break;
+        IncreaseHashTableSize(atable);
+    }
+
+    if (Empty(&atable->htable, hashloc)) {
+        atable->htable.entries++;
+        strloc = AddString(&atable->stable, s);
+        atable->htable.entry[hashloc].index = strloc;
+        atable->htable.entry[hashloc].value = 0;
+    }
+    return hashloc;
+} // LookUpAddStringHash
+
+/*
+ * LookUpAddString() - Lookup a string in the hash table.  If it's not there, add it and
+ *        initialize the atom value in the hash table to the next atom number.
+ *        Return the atom value of string.
+ */
+
+int LookUpAddString(AtomTable *atable, const char *s)
+{
+    int hashindex, atom;
+
+    hashindex = LookUpAddStringHash(atable, s);
+    atom = atable->htable.entry[hashindex].value;
+    if (atom == 0) {
+        atom = AllocateAtom(atable);
+        SetAtomValue(atable, atom, hashindex);
+    }
+    return atom;
+} // LookUpAddString
+
+/*
+ * GetAtomString()
+ *
+ */
+
+const  char *GetAtomString(AtomTable *atable, int atom)
+{
+    int soffset;
+
+    if (atom > 0 && atom < atable->nextFree) {
+        soffset = atable->amap[atom];
+        if (soffset > 0 && soffset < atable->stable.nextFree) {
+            return &atable->stable.strings[soffset];
+        } else {
+            return "<internal error: bad soffset>";
+        }
+    } else {
+        if (atom == 0) {
+            return "<null atom>";
+        } else {
+            if (atom == EOF) {
+                return "<EOF>";
+            } else {
+                return "<invalid atom>";
+            }
+        }
+    }
+} // GetAtomString
+
+/*
+ * GetReversedAtom()
+ *
+ */
+
+int GetReversedAtom(AtomTable *atable, int atom)
+{
+    if (atom > 0 && atom < atable->nextFree) {
+        return atable->arev[atom];
+    } else {
+        return 0;
+    }
+} // GetReversedAtom
+
+/*
+ * AddAtom() - Add a string to the atom, hash and string tables if it isn't already there.
+ *         Return it's atom index.
+ */
+
+int AddAtom(AtomTable *atable, const char *s)
+{
+    int atom;
+
+    atom = LookUpAddString(atable, s);
+    return atom;
+} // AddAtom
+
+/*
+ * AddAtomFixed() - Add an atom to the hash and string tables if it isn't already there.
+ *         Assign it the atom value of "atom".
+ */
+
+static int AddAtomFixed(AtomTable *atable, const char *s, int atom)
+{
+    int hashindex, lsize;
+
+    hashindex = LookUpAddStringHash(atable, s);
+    if (atable->nextFree >= atable->size || atom >= atable->size) {
+        lsize = atable->size*2;
+        if (lsize <= atom)
+            lsize = atom + 1;
+        GrowAtomTable(atable, lsize);
+    }
+    atable->amap[atom] = atable->htable.entry[hashindex].index;
+    atable->htable.entry[hashindex].value = atom;
+    //if (atom >= atable->nextFree)
+    //    atable->nextFree = atom + 1;
+    while (atom >= atable->nextFree) {
+        atable->arev[atable->nextFree] = lReverse(atable->nextFree);
+        atable->nextFree++;
+    }
+    return atom;
+} // AddAtomFixed
+
+/*
+ * InitAtomTable() - Initialize the atom table.
+ *
+ */
+
+int InitAtomTable(AtomTable *atable, int htsize)
+{
+    int ii;
+
+    htsize = htsize <= 0 ? INIT_HASH_TABLE_SIZE : htsize;
+    if (!InitStringTable(&atable->stable))
+        return 0;
+    if (!InitHashTable(&atable->htable, htsize))
+        return 0;
+
+    atable->nextFree = 0;
+    atable->amap = NULL;
+    atable->size = 0;
+    GrowAtomTable(atable, INIT_ATOM_TABLE_SIZE);
+    if (!atable->amap)
+        return 0;
+
+    // Initialize lower part of atom table to "<undefined>" atom:
+
+    AddAtomFixed(atable, "<undefined>", 0);
+    for (ii = 0; ii < FIRST_USER_TOKEN_SY; ii++)
+        atable->amap[ii] = atable->amap[0];
+
+    // Add single character tokens to the atom table:
+
+    {
+		const char *s = "~!%^&*()-+=|,.<>/?;:[]{}#";
+        char t[2];
+
+        t[1] = '\0';
+        while (*s) {
+            t[0] = *s;
+            AddAtomFixed(atable, t, s[0]);
+            s++;
+        }
+    }
+
+    // Add multiple character scanner tokens :
+
+    for (ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++)
+        AddAtomFixed(atable, tokens[ii].str, tokens[ii].val);
+
+    // Add error symbol if running in error mode:
+
+    if (cpp->options.ErrorMode)
+        AddAtomFixed(atable, "error", ERROR_SY);
+
+    AddAtom(atable, "<*** end fixed atoms ***>");
+
+    return 1;
+} // InitAtomTable
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////// Debug Printing Functions: //////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * PrintAtomTable()
+ *
+ */
+
+void PrintAtomTable(AtomTable *atable)
+{
+    int ii;
+    char str[200];
+
+    for (ii = 0; ii < atable->nextFree; ii++) {
+        sprintf(str, "%d: \"%s\"", ii, &atable->stable.strings[atable->amap[ii]]);
+        CPPDebugLogMsg(str);
+    }
+    sprintf(str, "Hash table: size=%d, entries=%d, collisions=",
+           atable->htable.size, atable->htable.entries);
+    CPPDebugLogMsg(str);
+    for (ii = 0; ii < HASH_TABLE_MAX_COLLISIONS; ii++) {
+        sprintf(str, " %d", atable->htable.counts[ii]);
+        CPPDebugLogMsg(str);
+    }
+
+} // PrintAtomTable
+
+
+/*
+ * GetStringOfAtom()
+ *
+ */
+
+char* GetStringOfAtom(AtomTable *atable, int atom)
+{
+	 char* chr_str;
+	 chr_str=&atable->stable.strings[atable->amap[atom]];
+	 return chr_str;
+} // GetStringOfAtom
+
+/*
+ * FreeAtomTable() - Free the atom table and associated memory
+ *
+ */
+
+void FreeAtomTable(AtomTable *atable)
+{
+    FreeStringTable(&atable->stable);
+    FreeHashTable(&atable->htable);
+    if (atable->amap)
+        free(atable->amap);
+    if (atable->arev)
+        free(atable->arev);
+    atable->amap = NULL;
+    atable->arev = NULL;
+    atable->nextFree = 0;
+    atable->size = 0;
+} // FreeAtomTable
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////// End of atom.c ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/Compiler/Preprocessor/atom.h b/Compiler/Preprocessor/atom.h
new file mode 100644
index 0000000..9d42037
--- /dev/null
+++ b/Compiler/Preprocessor/atom.h
@@ -0,0 +1,68 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// atom.h
+//
+
+#if !defined(__ATOM_H)
+#define __ATOM_H 1
+
+typedef struct AtomTable_Rec AtomTable;
+
+extern AtomTable *atable;
+
+int InitAtomTable(AtomTable *atable, int htsize);
+void FreeAtomTable(AtomTable *atable);
+int AddAtom(AtomTable *atable, const char *s);
+void PrintAtomTable(AtomTable *atable);
+int LookUpAddString(AtomTable *atable, const char *s);
+const char *GetAtomString(AtomTable *atable, int atom);
+int GetReversedAtom(AtomTable *atable, int atom);
+char* GetStringOfAtom(AtomTable *atable, int atom);
+#endif // !defined(__ATOM_H)
diff --git a/Compiler/Preprocessor/compile.h b/Compiler/Preprocessor/compile.h
new file mode 100644
index 0000000..9e87afc
--- /dev/null
+++ b/Compiler/Preprocessor/compile.h
@@ -0,0 +1,104 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// compile.h
+//
+
+#if !defined(__COMPILE_H)
+#define __COMPILE_H 1
+
+int InitCPPStruct(void);
+
+typedef struct Options_Rec{
+    const char *profileString;
+    int ErrorMode;
+    int Quiet;
+	
+    // Debug The Compiler options:
+    int DumpAtomTable;
+} Options;
+
+struct CPPStruct_Rec {
+    // Public members
+    SourceLoc *pLastSourceLoc;  // Set at the start of each statement by the tree walkers
+    Options options;            // Compile options and parameters
+
+    // Private members
+    SourceLoc lastSourceLoc;
+
+    // Scanner data:
+
+    SourceLoc *tokenLoc;        // Source location of most recent token seen by the scanner
+    int mostRecentToken;        // Most recent token seen by the scanner
+    InputSrc *currentInput;
+    int previous_token;
+    int notAVersionToken;      // used to make sure that #version is the first token seen in the file, if present
+    
+	void *pC;                   // storing the parseContext of the compile object in cpp.  
+     
+    // Private members:
+    SourceLoc ltokenLoc;
+	int ifdepth;                //current #if-#else-#endif nesting in the cpp.c file (pre-processor)    
+    int elsedepth[64];          //Keep a track of #if depth..Max allowed is 64.   
+    int elsetracker;            //#if-#else and #endif constructs...Counter.
+    const char *ErrMsg;
+    int CompileError;           //Indicate compile error when #error, #else,#elif mismatch.
+
+    //
+    // Globals used to communicate between PaParseStrings() and yy_input()and 
+    // also across the files.(gen_glslang.cpp and scanner.c)
+    //
+    int    PaWhichStr;            // which string we're parsing
+    int*   PaStrLen;              // array of lengths of the PaArgv strings
+    int    PaArgc;                // count of strings in the array
+    char** PaArgv;                // our array of strings to parse    
+    unsigned int tokensBeforeEOF : 1;
+};
+
+#endif // !defined(__COMPILE_H)
diff --git a/Compiler/Preprocessor/cpp.c b/Compiler/Preprocessor/cpp.c
new file mode 100644
index 0000000..d852fd4
--- /dev/null
+++ b/Compiler/Preprocessor/cpp.c
@@ -0,0 +1,1009 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// cpp.c
+//
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "slglobals.h"
+
+static int CPPif(yystypepp * yylvalpp);
+
+/* Don't use memory.c's replacements, as we clean up properly here */
+#undef malloc
+#undef free
+
+static int bindAtom = 0;
+static int constAtom = 0;
+static int defaultAtom = 0;
+static int defineAtom = 0;
+static int definedAtom = 0;
+static int elseAtom = 0;
+static int elifAtom = 0;
+static int endifAtom = 0;
+static int ifAtom = 0;
+static int ifdefAtom = 0;
+static int ifndefAtom = 0;
+static int includeAtom = 0;
+static int lineAtom = 0;
+static int pragmaAtom = 0;
+static int texunitAtom = 0;
+static int undefAtom = 0;
+static int errorAtom = 0;
+static int __LINE__Atom = 0;
+static int __FILE__Atom = 0;
+static int __VERSION__Atom = 0;
+static int versionAtom = 0;
+static int extensionAtom = 0;
+
+static Scope *macros = 0;
+#define MAX_MACRO_ARGS  64
+#define MAX_IF_NESTING  64
+
+static SourceLoc ifloc; /* outermost #if */
+
+int InitCPP(void)
+{
+    char        buffer[64], *t;
+    const char  *f;
+    // Add various atoms needed by the CPP line scanner:
+    bindAtom = LookUpAddString(atable, "bind");
+    constAtom = LookUpAddString(atable, "const");
+    defaultAtom = LookUpAddString(atable, "default");
+    defineAtom = LookUpAddString(atable, "define");
+    definedAtom = LookUpAddString(atable, "defined");
+    elifAtom = LookUpAddString(atable, "elif");
+    elseAtom = LookUpAddString(atable, "else");
+    endifAtom = LookUpAddString(atable, "endif");
+    ifAtom = LookUpAddString(atable, "if");
+    ifdefAtom = LookUpAddString(atable, "ifdef");
+    ifndefAtom = LookUpAddString(atable, "ifndef");
+    includeAtom = LookUpAddString(atable, "include");
+    lineAtom = LookUpAddString(atable, "line");
+    pragmaAtom = LookUpAddString(atable, "pragma");
+    texunitAtom = LookUpAddString(atable, "texunit");
+    undefAtom = LookUpAddString(atable, "undef");
+	errorAtom = LookUpAddString(atable, "error");
+    __LINE__Atom = LookUpAddString(atable, "__LINE__");
+    __FILE__Atom = LookUpAddString(atable, "__FILE__");
+	__VERSION__Atom = LookUpAddString(atable, "__VERSION__");
+    versionAtom = LookUpAddString(atable, "version");
+    extensionAtom = LookUpAddString(atable, "extension");
+    macros = NewScopeInPool(mem_CreatePool(0, 0));
+    strcpy(buffer, "PROFILE_");
+    t = buffer + strlen(buffer);
+    f = cpp->options.profileString;
+    while ((isalnum(*f) || *f == '_') && t < buffer + sizeof(buffer) - 1)
+        *t++ = toupper(*f++);
+    *t = 0;
+	return 1;
+} // InitCPP
+
+int FreeCPP(void)
+{
+    if (macros)
+    {
+        mem_FreePool(macros->pool);
+        macros = 0;
+    }
+
+    return 1;
+}
+
+int FinalCPP(void)
+{
+	if (cpp->ifdepth)
+		CPPErrorToInfoLog("#if mismatch");
+    return 1;
+}
+
+static int CPPdefine(yystypepp * yylvalpp)
+{
+    int token, name, args[MAX_MACRO_ARGS], argc;
+    const char *message;
+    MacroSymbol mac;
+    Symbol *symb;
+    SourceLoc dummyLoc;
+    memset(&mac, 0, sizeof(mac));
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token != CPP_IDENTIFIER) {
+        CPPErrorToInfoLog("#define");
+        return token;
+    }
+    name = yylvalpp->sc_ident;
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token == '(' && !yylvalpp->sc_int) {
+        // gather arguments
+        argc = 0;
+        do {
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            if (argc == 0 && token == ')') break;
+            if (token != CPP_IDENTIFIER) {
+				CPPErrorToInfoLog("#define");
+                return token;
+            }
+            if (argc < MAX_MACRO_ARGS)
+                args[argc++] = yylvalpp->sc_ident;
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        } while (token == ',');
+        if (token != ')') {
+            CPPErrorToInfoLog("#define");
+            return token;
+        }
+        mac.argc = argc;
+        mac.args = mem_Alloc(macros->pool, argc * sizeof(int));
+        memcpy(mac.args, args, argc * sizeof(int));
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	}
+    mac.body = NewTokenStream(GetAtomString(atable, name), macros->pool);
+    while (token != '\n') {
+        while (token == '\\') {
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            if (token == '\n')
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            else
+                RecordToken(mac.body, '\\', yylvalpp);
+        }
+        RecordToken(mac.body, token, yylvalpp);
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    };
+
+    symb = LookUpSymbol(macros, name);
+    if (symb) {
+        if (!symb->details.mac.undef) {
+            // already defined -- need to make sure they are identical
+            if (symb->details.mac.argc != mac.argc) goto error;
+            for (argc=0; argc < mac.argc; argc++)
+                if (symb->details.mac.args[argc] != mac.args[argc])
+                    goto error;
+            RewindTokenStream(symb->details.mac.body);
+            RewindTokenStream(mac.body);
+            do {
+                int old_lval, old_token;
+                old_token = ReadToken(symb->details.mac.body, yylvalpp);
+                old_lval = yylvalpp->sc_int;
+                token = ReadToken(mac.body, yylvalpp);
+                if (token != old_token || yylvalpp->sc_int != old_lval) { 
+                error:
+                    StoreStr("Macro Redefined");
+                    StoreStr(GetStringOfAtom(atable,name));
+                    message=GetStrfromTStr();
+                    DecLineNumber();
+                    CPPShInfoLogMsg(message);
+                    IncLineNumber();
+                    ResetTString();
+                    break; }
+            } while (token > 0);
+        }
+        //FreeMacro(&symb->details.mac);
+    } else {
+        dummyLoc.file = 0;
+        dummyLoc.line = 0;
+        symb = AddSymbol(&dummyLoc, macros, name, MACRO_S);
+    }
+    symb->details.mac = mac;
+    return '\n';
+} // CPPdefine
+
+static int CPPundef(yystypepp * yylvalpp)
+{
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    Symbol *symb;
+	if(token == '\n'){
+		CPPErrorToInfoLog("#undef");
+	    return token;
+    }
+    if (token != CPP_IDENTIFIER)
+          goto error;
+    symb = LookUpSymbol(macros, yylvalpp->sc_ident);
+    if (symb) {
+        symb->details.mac.undef = 1;
+    }
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token != '\n') {
+    error:
+        CPPErrorToInfoLog("#undef");
+    }
+    return token;
+} // CPPundef
+
+/* CPPelse -- skip forward to appropriate spot.  This is actually used
+** to skip to and #endif after seeing an #else, AND to skip to a #else,
+** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false
+*/
+
+static int CPPelse(int matchelse, yystypepp * yylvalpp)
+{
+    int atom,depth=0;
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	
+	while (token > 0) {
+        if (token != '#') {
+		    while (token != '\n')
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            continue;
+        }
+		if ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) != CPP_IDENTIFIER)
+			continue;
+        atom = yylvalpp->sc_ident;
+        if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){
+            depth++; cpp->ifdepth++; cpp->elsetracker++;
+		}
+		else if (atom == endifAtom) {
+            if(--depth<=0){
+		        cpp->elsedepth[cpp->elsetracker]=0;
+			    --cpp->elsetracker;
+                if (cpp->ifdepth) 
+                    --cpp->ifdepth;
+                break;
+            }             
+                --cpp->elsetracker;
+                --cpp->ifdepth;
+            }
+        else if (((int)(matchelse) != 0)&& depth==0) {
+			if (atom == elseAtom ) {
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                if (token != '\n') {
+                    CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
+                    while (token != '\n')
+                        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                } 
+				break;
+			} 
+			else if (atom == elifAtom) {
+                /* we decrement cpp->ifdepth here, because CPPif will increment
+                 * it and we really want to leave it alone */
+				if (cpp->ifdepth){
+					--cpp->ifdepth;
+				    --cpp->elsetracker;
+				}
+                return CPPif(yylvalpp);
+            }
+		}
+        else if((atom==elseAtom) && (!ChkCorrectElseNesting())){
+            CPPErrorToInfoLog("#else after a #else");
+            cpp->CompileError=1;
+        }
+	};
+    return token;
+}
+
+enum eval_prec {
+    MIN_PREC,
+    COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY,
+    MAX_PREC
+};
+
+static int op_logor(int a, int b) { return a || b; }
+static int op_logand(int a, int b) { return a && b; }
+static int op_or(int a, int b) { return a | b; }
+static int op_xor(int a, int b) { return a ^ b; }
+static int op_and(int a, int b) { return a & b; }
+static int op_eq(int a, int b) { return a == b; }
+static int op_ne(int a, int b) { return a != b; }
+static int op_ge(int a, int b) { return a >= b; }
+static int op_le(int a, int b) { return a <= b; }
+static int op_gt(int a, int b) { return a > b; }
+static int op_lt(int a, int b) { return a < b; }
+static int op_shl(int a, int b) { return a << b; }
+static int op_shr(int a, int b) { return a >> b; }
+static int op_add(int a, int b) { return a + b; }
+static int op_sub(int a, int b) { return a - b; }
+static int op_mul(int a, int b) { return a * b; }
+static int op_div(int a, int b) { return a / b; }
+static int op_mod(int a, int b) { return a % b; }
+static int op_pos(int a) { return a; }
+static int op_neg(int a) { return -a; }
+static int op_cmpl(int a) { return ~a; }
+static int op_not(int a) { return !a; }
+
+struct {
+    int token, prec, (*op)(int, int);
+} binop[] = {
+    { CPP_OR_OP, LOGOR, op_logor },
+    { CPP_AND_OP, LOGAND, op_logand },
+    { '|', OR, op_or },
+    { '^', XOR, op_xor },
+    { '&', AND, op_and },
+    { CPP_EQ_OP, EQUAL, op_eq },
+    { CPP_NE_OP, EQUAL, op_ne },
+    { '>', RELATION, op_gt },
+    { CPP_GE_OP, RELATION, op_ge },
+    { '<', RELATION, op_lt },
+    { CPP_LE_OP, RELATION, op_le },
+    { CPP_LEFT_OP, SHIFT, op_shl },
+    { CPP_RIGHT_OP, SHIFT, op_shr },
+    { '+', ADD, op_add },
+    { '-', ADD, op_sub },
+    { '*', MUL, op_mul },
+    { '/', MUL, op_div },
+    { '%', MUL, op_mod },
+};
+
+struct {
+    int token, (*op)(int);
+} unop[] = {
+    { '+', op_pos },
+    { '-', op_neg },
+    { '~', op_cmpl },
+    { '!', op_not },
+};
+
+#define ALEN(A) (sizeof(A)/sizeof(A[0]))
+
+static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp)
+{
+    int         i, val;
+    Symbol      *s;
+    if (token == CPP_IDENTIFIER) {
+        if (yylvalpp->sc_ident == definedAtom) {
+            int needclose = 0;
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            if (token == '(') {
+                needclose = 1;
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            }
+            if (token != CPP_IDENTIFIER)
+                goto error;
+            *res = (s = LookUpSymbol(macros, yylvalpp->sc_ident))
+                        ? !s->details.mac.undef : 0;
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            if (needclose) {
+                if (token != ')')
+                    goto error;
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            }
+		} else if (MacroExpand(yylvalpp->sc_ident, yylvalpp)) {
+			token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            return eval(token, prec, res, err, yylvalpp);
+        } else {
+            goto error;
+        }
+	} else if (token == CPP_INTCONSTANT) {
+        *res = yylvalpp->sc_int;
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    } else if (token == '(') {
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        token = eval(token, MIN_PREC, res, err, yylvalpp);
+        if (!*err) {
+            if (token != ')')
+                goto error;
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        }
+    } else {
+        for (i = ALEN(unop) - 1; i >= 0; i--) {
+            if (unop[i].token == token)
+                break;
+        }
+        if (i >= 0) {
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            token = eval(token, UNARY, res, err, yylvalpp);
+            *res = unop[i].op(*res);
+        } else {
+            goto error;
+        }
+    }
+    while (!*err) {
+        if (token == ')' || token == '\n') break;
+        for (i = ALEN(binop) - 1; i >= 0; i--) {
+            if (binop[i].token == token)
+                break;
+        }
+        if (i < 0 || binop[i].prec <= prec)
+            break;
+        val = *res;
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        token = eval(token, binop[i].prec, res, err, yylvalpp);
+        *res = binop[i].op(val, *res);
+    }
+    return token;
+error:
+    CPPErrorToInfoLog("incorrect preprocessor directive");
+    *err = 1;
+    *res = 0;
+    return token;
+} // eval
+
+static int CPPif(yystypepp * yylvalpp) {
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    int res = 0, err = 0;
+	cpp->elsetracker++;
+    if (!cpp->ifdepth++)
+        ifloc = *cpp->tokenLoc;
+	if(cpp->ifdepth >MAX_IF_NESTING){
+        CPPErrorToInfoLog("max #if nesting depth exceeded");
+		return 0;
+	}
+	token = eval(token, MIN_PREC, &res, &err, yylvalpp);
+    if (token != '\n') {
+        CPPWarningToInfoLog("unexpected tokens following the preprocessor directive - expected a newline");
+        while (token != '\n')
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    } 
+    if (!res && !err) {
+        token = CPPelse(1, yylvalpp);
+    }
+
+    return token;
+} // CPPif
+
+static int CPPifdef(int defined, yystypepp * yylvalpp)
+{
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    int name = yylvalpp->sc_ident;
+	if(++cpp->ifdepth >MAX_IF_NESTING){
+	    CPPErrorToInfoLog("max #if nesting depth exceeded");
+		return 0;
+	}
+	cpp->elsetracker++;
+    if (token != CPP_IDENTIFIER) {
+            defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef");
+    } else {
+        Symbol *s = LookUpSymbol(macros, name);
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        if (token != '\n') {
+            CPPWarningToInfoLog("unexpected tokens following #ifdef preprocessor directive - expected a newline");
+            while (token != '\n')
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        }
+        if (((s && !s->details.mac.undef) ? 1 : 0) != defined)
+            token = CPPelse(1, yylvalpp);
+    }
+    return token;
+} // CPPifdef
+
+static int CPPline(yystypepp * yylvalpp) 
+{
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	if(token=='\n'){
+		DecLineNumber();
+        CPPErrorToInfoLog("#line");
+        IncLineNumber();
+		return token;
+	}
+	else if (token == CPP_INTCONSTANT) {
+		yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+		SetLineNumber(yylvalpp->sc_int);
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        
+		if (token == CPP_INTCONSTANT) {
+            yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+			SetStringNumber(yylvalpp->sc_int);
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+			if(token!='\n')
+				CPPErrorToInfoLog("#line");
+        }
+		else if (token == '\n'){
+			return token;
+		}
+		else{
+            CPPErrorToInfoLog("#line");
+		}
+	}
+	else{
+          CPPErrorToInfoLog("#line");
+	}
+    return token;
+}
+
+static int CPPerror(yystypepp * yylvalpp) {
+
+	int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    const char *message;
+	
+    while (token != '\n') {
+		if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
+            StoreStr(yylvalpp->symbol_name);
+		}else if(token == CPP_IDENTIFIER || token == CPP_STRCONSTANT){
+			StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
+		}else {
+		    StoreStr(GetStringOfAtom(atable,token));
+		}
+		token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	}
+	DecLineNumber();
+	//store this msg into the shader's information log..set the Compile Error flag!!!!
+	message=GetStrfromTStr();
+    CPPShInfoLogMsg(message);
+    ResetTString();
+    cpp->CompileError=1;
+    IncLineNumber();
+    return '\n';
+}//CPPerror
+
+static int CPPpragma(yystypepp * yylvalpp)
+{
+	char SrcStrName[2];
+	char** allTokens;
+	int tokenCount = 0;
+	int maxTokenCount = 10;
+	const char* SrcStr;
+	int i;
+
+	int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	
+	if (token=='\n') {
+		DecLineNumber();
+        CPPErrorToInfoLog("#pragma");
+        IncLineNumber();
+	    return token;
+	}
+	
+	allTokens = (char**)malloc(sizeof(char*) * maxTokenCount);	
+
+	while (token != '\n') {
+		if (tokenCount >= maxTokenCount) {
+			maxTokenCount *= 2;
+			allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount);
+		}
+		switch (token) {
+		case CPP_IDENTIFIER:
+			SrcStr = GetAtomString(atable, yylvalpp->sc_ident);
+			allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+			strcpy(allTokens[tokenCount++], SrcStr);
+			break;
+		case CPP_INTCONSTANT:
+			SrcStr = yylvalpp->symbol_name;
+			allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+			strcpy(allTokens[tokenCount++], SrcStr);
+			break;
+		case CPP_FLOATCONSTANT:
+			SrcStr = yylvalpp->symbol_name;
+			allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1);
+			strcpy(allTokens[tokenCount++], SrcStr);
+			break;
+		case -1:
+            // EOF
+            CPPShInfoLogMsg("#pragma directive must end with a newline");			
+			return token;
+		default:
+			SrcStrName[0] = token;
+			SrcStrName[1] = '\0';
+			allTokens[tokenCount] = (char*)malloc(2);
+			strcpy(allTokens[tokenCount++], SrcStrName);
+		}
+		token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	}
+
+	cpp->currentInput->ungetch(cpp->currentInput, token, yylvalpp);
+	HandlePragma((const char**)allTokens, tokenCount);
+	token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	
+	for (i = 0; i < tokenCount; ++i) {
+		free (allTokens[i]);
+	}
+	free (allTokens);	
+
+	return token;    
+} // CPPpragma
+
+#define GL2_VERSION_NUMBER 110
+
+static int CPPversion(yystypepp * yylvalpp)
+{
+
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+    if (cpp->notAVersionToken == 1)
+        CPPShInfoLogMsg("#version must occur before any other statement in the program");
+
+    if(token=='\n'){
+		DecLineNumber();
+        CPPErrorToInfoLog("#version");
+        IncLineNumber();
+		return token;
+	}
+    if (token != CPP_INTCONSTANT)
+        CPPErrorToInfoLog("#version");
+	
+    yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+	//SetVersionNumber(yylvalpp->sc_int);
+    
+    if (yylvalpp->sc_int != GL2_VERSION_NUMBER)
+        CPPShInfoLogMsg("Version number not supported by GL2");
+
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    
+	if (token == '\n'){
+		return token;
+	}
+	else{
+        CPPErrorToInfoLog("#version");
+	}
+    return token;
+} // CPPversion
+
+static int CPPextension(yystypepp * yylvalpp)
+{
+
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    char extensionName[80];
+
+    if(token=='\n'){
+		DecLineNumber();
+        CPPShInfoLogMsg("extension name not specified");
+        IncLineNumber();
+		return token;
+	}
+
+    if (token != CPP_IDENTIFIER)
+        CPPErrorToInfoLog("#extension");
+    
+    strcpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident));
+	    
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token != ':') {
+        CPPShInfoLogMsg("':' missing after extension name");
+        return token;
+    }
+    
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    if (token != CPP_IDENTIFIER) {
+        CPPShInfoLogMsg("behavior for extension not specified");
+        return token;
+    }
+
+    updateExtensionBehavior(extensionName, GetAtomString(atable, yylvalpp->sc_ident));
+
+    token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	if (token == '\n'){
+		return token;
+	}
+	else{
+        CPPErrorToInfoLog("#extension");
+	}
+    return token;
+} // CPPextension
+
+int readCPPline(yystypepp * yylvalpp)
+{
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+    const char *message;
+    int isVersion = 0;
+
+    if (token == CPP_IDENTIFIER) {
+        if (yylvalpp->sc_ident == defineAtom) {
+             token = CPPdefine(yylvalpp);
+        } else if (yylvalpp->sc_ident == elseAtom) {
+			 if(ChkCorrectElseNesting()){
+                 if (!cpp->ifdepth ){
+                     CPPErrorToInfoLog("#else mismatch");
+                     cpp->CompileError=1;
+                 }
+                 token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                 if (token != '\n') {
+                     CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline");
+                     while (token != '\n')
+                         token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                 }
+			     token = CPPelse(0, yylvalpp);
+             }else{
+                 CPPErrorToInfoLog("#else after a #else");
+                 cpp->ifdepth=0;
+                 cpp->notAVersionToken = 1;
+                 return 0;
+             }
+		} else if (yylvalpp->sc_ident == elifAtom) {
+            if (!cpp->ifdepth){
+                 CPPErrorToInfoLog("#elif mismatch");
+                 cpp->CompileError=1;
+            } 
+            // this token is really a dont care, but we still need to eat the tokens
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); 
+            while (token != '\n')
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+		    token = CPPelse(0, yylvalpp);
+        } else if (yylvalpp->sc_ident == endifAtom) {
+			 cpp->elsedepth[cpp->elsetracker]=0;
+		     --cpp->elsetracker;
+             if (!cpp->ifdepth){
+                 CPPErrorToInfoLog("#endif mismatch");
+                 cpp->CompileError=1;
+             }
+             else
+			  	 --cpp->ifdepth;
+	    } else if (yylvalpp->sc_ident == ifAtom) {
+             token = CPPif(yylvalpp);
+        } else if (yylvalpp->sc_ident == ifdefAtom) {
+             token = CPPifdef(1, yylvalpp);
+        } else if (yylvalpp->sc_ident == ifndefAtom) {
+             token = CPPifdef(0, yylvalpp);
+        } else if (yylvalpp->sc_ident == lineAtom) {
+             token = CPPline(yylvalpp);
+        } else if (yylvalpp->sc_ident == pragmaAtom) {
+             token = CPPpragma(yylvalpp);
+        } else if (yylvalpp->sc_ident == undefAtom) {
+             token = CPPundef(yylvalpp);
+        } else if (yylvalpp->sc_ident == errorAtom) {
+             token = CPPerror(yylvalpp);
+        } else if (yylvalpp->sc_ident == versionAtom) {
+            token = CPPversion(yylvalpp);
+            isVersion = 1;
+        } else if (yylvalpp->sc_ident == extensionAtom) {
+            token = CPPextension(yylvalpp);
+        } else {
+            StoreStr("Invalid Directive");
+            StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident));
+            message=GetStrfromTStr();
+            CPPShInfoLogMsg(message);
+            ResetTString();
+        }
+    }
+    while (token != '\n' && token != 0 && token != EOF) {
+		token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+	}
+        
+    cpp->notAVersionToken = !isVersion;
+
+    return token;
+} // readCPPline
+
+void FreeMacro(MacroSymbol *s) {
+    DeleteTokenStream(s->body);
+}
+
+static int eof_scan(InputSrc *in, yystypepp * yylvalpp) { return -1; }
+static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) { }
+
+static void PushEofSrc() {
+    InputSrc *in = malloc(sizeof(InputSrc));
+    memset(in, 0, sizeof(InputSrc));
+    in->scan = eof_scan;
+    in->getch = eof_scan;
+    in->ungetch = noop;
+    in->prev = cpp->currentInput;
+    cpp->currentInput = in;
+}
+
+static void PopEofSrc() {
+    if (cpp->currentInput->scan == eof_scan) {
+        InputSrc *in = cpp->currentInput;
+        cpp->currentInput = in->prev;
+        free(in);
+    }
+}
+
+static TokenStream *PrescanMacroArg(TokenStream *a, yystypepp * yylvalpp) {
+    int token;
+    TokenStream *n;
+    RewindTokenStream(a);
+    do {
+        token = ReadToken(a, yylvalpp);
+        if (token == CPP_IDENTIFIER && LookUpSymbol(macros, yylvalpp->sc_ident))
+            break;
+    } while (token > 0);
+    if (token <= 0) return a;
+    n = NewTokenStream("macro arg", 0);
+    PushEofSrc();
+    ReadFromTokenStream(a, 0, 0);
+    while ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) > 0) {
+        if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp->sc_ident, yylvalpp))
+            continue;
+        RecordToken(n, token, yylvalpp);
+    }
+    PopEofSrc();
+    DeleteTokenStream(a);
+    return n;
+} // PrescanMacroArg
+
+typedef struct MacroInputSrc {
+    InputSrc    base;
+    MacroSymbol *mac;
+    TokenStream **args;
+} MacroInputSrc;
+
+/* macro_scan ---
+** return the next token for a macro expanion, handling macro args 
+*/
+static int macro_scan(MacroInputSrc *in, yystypepp * yylvalpp) {
+    int i;
+    int token = ReadToken(in->mac->body, yylvalpp);
+    if (token == CPP_IDENTIFIER) {
+        for (i = in->mac->argc-1; i>=0; i--)
+            if (in->mac->args[i] == yylvalpp->sc_ident) break;
+        if (i >= 0) {
+            ReadFromTokenStream(in->args[i], yylvalpp->sc_ident, 0);
+            return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+        }
+    }
+    if (token > 0) return token;
+    in->mac->busy = 0;
+    cpp->currentInput = in->base.prev;
+    if (in->args) {
+        for (i=in->mac->argc-1; i>=0; i--)
+            DeleteTokenStream(in->args[i]);
+        free(in->args);
+    }
+    free(in);
+    return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+} // macro_scan
+
+/* MacroExpand
+** check an identifier (atom) to see if it a macro that should be expanded.
+** If it is, push an InputSrc that will produce the appropriate expansion
+** and return TRUE.  If not, return FALSE.
+*/
+
+int MacroExpand(int atom, yystypepp * yylvalpp)
+{
+    Symbol              *sym = LookUpSymbol(macros, atom);
+    MacroInputSrc       *in;
+    int i,j, token, depth=0;
+    const char *message;
+	if (atom == __LINE__Atom) {
+        yylvalpp->sc_int = GetLineNumber();
+        sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
+        UngetToken(CPP_INTCONSTANT, yylvalpp);
+        return 1;
+    }
+    if (atom == __FILE__Atom) {
+        yylvalpp->sc_int = GetStringNumber();
+        sprintf(yylvalpp->symbol_name,"%d",yylvalpp->sc_int);
+        UngetToken(CPP_INTCONSTANT, yylvalpp);
+        return 1;
+    }
+	if (atom == __VERSION__Atom) {
+        strcpy(yylvalpp->symbol_name,"100");
+        yylvalpp->sc_int = atoi(yylvalpp->symbol_name);
+        UngetToken(CPP_INTCONSTANT, yylvalpp);
+        return 1;
+    }
+    if (!sym || sym->details.mac.undef) return 0;
+    if (sym->details.mac.busy) return 0;        // no recursive expansions
+    in = malloc(sizeof(*in));
+    memset(in, 0, sizeof(*in));
+    in->base.scan = (void *)macro_scan;
+    in->base.line = cpp->currentInput->line;
+    in->base.name = cpp->currentInput->name;
+    in->mac = &sym->details.mac;
+    if (sym->details.mac.args) {
+        token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+		if (token != '(') {
+            UngetToken(token, yylvalpp);
+            yylvalpp->sc_ident = atom;
+            return 0;
+        }
+        in->args = malloc(in->mac->argc * sizeof(TokenStream *));
+        for (i=0; i<in->mac->argc; i++)
+            in->args[i] = NewTokenStream("macro arg", 0);
+		i=0;j=0;
+        do{
+            depth = 0;
+			while(1) {
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                if (token <= 0) {
+                    StoreStr("EOF in Macro ");
+                    StoreStr(GetStringOfAtom(atable,atom));
+                    message=GetStrfromTStr();
+                    CPPShInfoLogMsg(message);
+                    ResetTString();
+                    return 1;
+                }
+                if((in->mac->argc==0) && (token!=')')) break;
+                if (depth == 0 && (token == ',' || token == ')')) break;
+                if (token == '(') depth++;
+                if (token == ')') depth--;
+                RecordToken(in->args[i], token, yylvalpp);
+                j=1;
+			}
+            if (token == ')') {
+                if((in->mac->argc==1) &&j==0)
+                    break;
+                i++;
+                break;
+            }
+            i++;
+		}while(i < in->mac->argc);
+
+        if (i < in->mac->argc) {
+            StoreStr("Too few args in Macro ");
+            StoreStr(GetStringOfAtom(atable,atom));
+            message=GetStrfromTStr();
+            CPPShInfoLogMsg(message);
+            ResetTString();
+        } else if (token != ')') {
+            depth=0;
+			while (token >= 0 && (depth > 0 || token != ')')) {
+                if (token == ')') depth--;
+                token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+                if (token == '(') depth++;
+            }
+			
+            if (token <= 0) {
+                StoreStr("EOF in Macro ");
+                StoreStr(GetStringOfAtom(atable,atom));
+                message=GetStrfromTStr();
+                CPPShInfoLogMsg(message);
+                ResetTString();
+                return 1;
+            }
+            StoreStr("Too many args in Macro ");
+            StoreStr(GetStringOfAtom(atable,atom));
+            message=GetStrfromTStr();
+            CPPShInfoLogMsg(message);
+            ResetTString();
+		}
+		for (i=0; i<in->mac->argc; i++) {
+            in->args[i] = PrescanMacroArg(in->args[i], yylvalpp);
+        }
+    }
+#if 0
+    printf("  <%s:%d>found macro %s\n", GetAtomString(atable, loc.file),
+           loc.line, GetAtomString(atable, atom));
+    for (i=0; i<in->mac->argc; i++) {
+        printf("\targ %s = '", GetAtomString(atable, in->mac->args[i]));
+        DumpTokenStream(stdout, in->args[i]);
+        printf("'\n");
+    }
+#endif
+	/*retain the input source*/
+    in->base.prev = cpp->currentInput;
+    sym->details.mac.busy = 1;
+    RewindTokenStream(sym->details.mac.body);
+    cpp->currentInput = &in->base;
+    return 1;
+} // MacroExpand
+
+int ChkCorrectElseNesting(void)
+{
+    if(cpp->elsedepth[cpp->elsetracker]==0){
+	  cpp->elsedepth[cpp->elsetracker]=1;
+      return 1;          
+    }
+    return 0;
+}
+
+
diff --git a/Compiler/Preprocessor/cpp.h b/Compiler/Preprocessor/cpp.h
new file mode 100644
index 0000000..85abbb5
--- /dev/null
+++ b/Compiler/Preprocessor/cpp.h
@@ -0,0 +1,91 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// cpp.h
+//
+
+#if !defined(__CPP_H)
+#define __CPP_H 1
+
+#include "parser.h"
+#include "tokens.h"
+
+int InitCPP(void);
+int FinalCPP(void);
+int  readCPPline(yystypepp * yylvalpp);
+int MacroExpand(int atom, yystypepp * yylvalpp);
+int ChkCorrectElseNesting(void);
+
+typedef struct MacroSymbol {
+    int argc;
+    int *args;
+    TokenStream *body;
+    unsigned busy:1;
+    unsigned undef:1;
+} MacroSymbol;
+
+void FreeMacro(MacroSymbol *);
+int PredefineMacro(char *);
+
+void  CPPDebugLogMsg(const char *msg);      // Prints information into debug log
+void  CPPShInfoLogMsg(const char*);         // Store cpp Err Msg into Sh.Info.Log
+void  CPPWarningToInfoLog(const char *msg); // Prints warning messages into info log
+void  HandlePragma(const char**, int numTokens);  // #pragma directive container.
+void  ResetTString(void);                   // #error Message as TString.
+void  CPPErrorToInfoLog(char*);             // Stick all cpp errors into Sh.Info.log   .
+void  StoreStr(char*);                      // Store the TString in Parse Context.
+void  SetLineNumber(int);                   // Set line number.  
+void  SetStringNumber(int);                 // Set string number.    
+int   GetLineNumber(void);                  // Get the current String Number. 
+int   GetStringNumber(void);                // Get the current String Number. 
+const char* GetStrfromTStr(void);           // Convert TString to String.  
+void  updateExtensionBehavior(const char* extName, const char* behavior);
+int   FreeCPP(void);
+
+#endif // !(defined(__CPP_H)
diff --git a/Compiler/Preprocessor/cppstruct.c b/Compiler/Preprocessor/cppstruct.c
new file mode 100644
index 0000000..5144b6c
--- /dev/null
+++ b/Compiler/Preprocessor/cppstruct.c
@@ -0,0 +1,157 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// cppstruct.c
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "slglobals.h"
+
+CPPStruct  *cpp      = NULL;
+static int  refCount = 0;
+
+int InitPreprocessor(void);
+int ResetPreprocessor(void);
+int FreeCPPStruct(void);
+int FinalizePreprocessor(void);
+
+/*
+ * InitCPPStruct() - Initilaize the CPP structure.
+ *
+ */
+
+int InitCPPStruct(void)
+{
+    int len;
+    char *p;
+
+    cpp = (CPPStruct *) malloc(sizeof(CPPStruct));
+    if (cpp == NULL)
+        return 0;
+
+    refCount++;
+
+    // Initialize public members:
+    cpp->pLastSourceLoc = &cpp->lastSourceLoc;
+    
+	p = (char *) &cpp->options;
+    len = sizeof(cpp->options);
+    while (--len >= 0)
+        p[len] = 0;
+     
+    ResetPreprocessor();
+    return 1;
+} // InitCPPStruct
+
+int ResetPreprocessor(void)
+{
+    // Initialize private members:
+
+    cpp->lastSourceLoc.file = 0;
+    cpp->lastSourceLoc.line = 0;
+	cpp->pC=0;
+    cpp->CompileError=0; 
+	cpp->ifdepth=0;
+    for(cpp->elsetracker=0; cpp->elsetracker<64; cpp->elsetracker++)
+		cpp->elsedepth[cpp->elsetracker]=0; 
+	cpp->elsetracker=0;
+    cpp->tokensBeforeEOF = 0;
+    return 1;
+}
+
+//Intializing the Preprocessor.
+
+int InitPreprocessor(void)
+{
+   #  define CPP_STUFF true
+        #  ifdef CPP_STUFF
+            FreeCPPStruct();
+            InitCPPStruct();
+            cpp->options.Quiet = 1;
+            cpp->options.profileString = "generic";
+            if (!InitAtomTable(atable, 0))
+                return 1;
+            if (!InitScanner(cpp))
+	            return 1;
+       #  endif
+  return 0; 
+}
+
+//FreeCPPStruct() - Free the CPP structure.
+
+int FreeCPPStruct(void)
+{
+    if (refCount)
+    {
+       free(cpp);
+       refCount--;
+    }
+    
+    return 1;
+}
+
+//Finalizing the Preprocessor.
+
+int FinalizePreprocessor(void)
+{
+   #  define CPP_STUFF true
+        #  ifdef CPP_STUFF
+            FreeAtomTable(atable);
+            FreeCPPStruct();
+            FreeScanner();
+       #  endif
+  return 0; 
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////// End of cppstruct.c //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/Compiler/Preprocessor/memory.c b/Compiler/Preprocessor/memory.c
new file mode 100644
index 0000000..1a70231
--- /dev/null
+++ b/Compiler/Preprocessor/memory.c
@@ -0,0 +1,163 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __STDC99__
+#include <stdint.h>
+#elif defined (_WIN64)
+typedef unsigned __int64 uintptr_t;
+#else 
+typedef unsigned int uintptr_t;
+#endif
+
+#include "memory.h"
+
+// default alignment and chunksize, if called with 0 arguments
+#define CHUNKSIZE       (64*1024)
+#define ALIGN           8
+
+// we need to call the `real' malloc and free, not our replacements
+#undef malloc
+#undef free
+
+struct chunk {
+    struct chunk        *next;
+};
+
+struct cleanup {
+    struct cleanup      *next;
+    void                (*fn)(void *);
+    void                *arg;
+};
+
+struct MemoryPool_rec {
+    struct chunk        *next;
+    uintptr_t           free, end;
+    size_t              chunksize;
+    uintptr_t           alignmask;
+    struct cleanup      *cleanup;
+};
+
+MemoryPool *mem_CreatePool(size_t chunksize, unsigned int align)
+{
+    MemoryPool  *pool;
+
+    if (align == 0) align = ALIGN;
+    if (chunksize == 0) chunksize = CHUNKSIZE;
+    if (align & (align-1)) return 0;
+    if (chunksize < sizeof(MemoryPool)) return 0;
+    if (chunksize & (align-1)) return 0;
+    if (!(pool = malloc(chunksize))) return 0;
+    pool->next = 0;
+    pool->chunksize = chunksize;
+    pool->alignmask = (uintptr_t)(align)-1;  
+    pool->free = ((uintptr_t)(pool + 1) + pool->alignmask) & ~pool->alignmask;
+    pool->end = (uintptr_t)pool + chunksize;
+    pool->cleanup = 0;
+    return pool;
+}
+
+void mem_FreePool(MemoryPool *pool)
+{
+    struct cleanup      *cleanup;
+    struct chunk        *p, *next;
+
+    for (cleanup = pool->cleanup; cleanup; cleanup = cleanup->next) {
+        cleanup->fn(cleanup->arg);
+    }
+    for (p = (struct chunk *)pool; p; p = next) {
+        next = p->next;
+        free(p);
+    }
+}
+
+void *mem_Alloc(MemoryPool *pool, size_t size)
+{
+    struct chunk *ch;
+    void *rv = (void *)pool->free;
+    size = (size + pool->alignmask) & ~pool->alignmask;
+    if (size <= 0) size = pool->alignmask;
+    pool->free += size;
+    if (pool->free > pool->end || pool->free < (uintptr_t)rv) {
+        size_t minreq = (size + sizeof(struct chunk) + pool->alignmask)
+                      & ~pool->alignmask;
+        pool->free = (uintptr_t)rv;
+        if (minreq >= pool->chunksize) {
+            // request size is too big for the chunksize, so allocate it as
+            // a single chunk of the right size
+            ch = malloc(minreq);
+            if (!ch) return 0;
+        } else {
+            ch = malloc(pool->chunksize);
+            if (!ch) return 0;
+            pool->free = (uintptr_t)ch + minreq;
+            pool->end = (uintptr_t)ch + pool->chunksize;
+        }
+        ch->next = pool->next;
+        pool->next = ch;
+        rv = (void *)(((uintptr_t)(ch+1) + pool->alignmask) & ~pool->alignmask);
+    }
+    return rv;
+}
+
+int mem_AddCleanup(MemoryPool *pool, void (*fn)(void *), void *arg) {
+    struct cleanup *cleanup;
+
+    pool->free = (pool->free + sizeof(void *) - 1) & ~(sizeof(void *)-1);
+    cleanup = mem_Alloc(pool, sizeof(struct cleanup));
+    if (!cleanup) return -1;
+    cleanup->next = pool->cleanup;
+    cleanup->fn = fn;
+    cleanup->arg = arg;
+    pool->cleanup = cleanup;
+    return 0;
+}
diff --git a/Compiler/Preprocessor/memory.h b/Compiler/Preprocessor/memory.h
new file mode 100644
index 0000000..3da7989
--- /dev/null
+++ b/Compiler/Preprocessor/memory.h
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+#ifndef __MEMORY_H
+#define __MEMORY_H
+
+typedef struct MemoryPool_rec MemoryPool;
+
+extern MemoryPool *mem_CreatePool(size_t chunksize, unsigned align);
+extern void mem_FreePool(MemoryPool *);
+extern void *mem_Alloc(MemoryPool *p, size_t size);
+extern void *mem_Realloc(MemoryPool *p, void *old, size_t oldsize, size_t newsize);
+extern int mem_AddCleanup(MemoryPool *p, void (*fn)(void *), void *arg);
+
+#endif /* __MEMORY_H */
diff --git a/Compiler/Preprocessor/parser.h b/Compiler/Preprocessor/parser.h
new file mode 100644
index 0000000..91a6200
--- /dev/null
+++ b/Compiler/Preprocessor/parser.h
@@ -0,0 +1,98 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+#ifndef BISON_PARSER_H
+# define BISON_PARSER_H
+
+#ifndef yystypepp
+typedef struct {
+    int    sc_int;
+    float  sc_fval;
+    int    sc_ident;
+	char   symbol_name[MAX_SYMBOL_NAME_LEN+1];
+} yystypepp;
+
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+# define	CPP_AND_OP	        257
+# define	CPP_SUB_ASSIGN	    259
+# define	CPP_MOD_ASSIGN	    260
+# define	CPP_ADD_ASSIGN	261
+# define	CPP_DIV_ASSIGN	262
+# define	CPP_MUL_ASSIGN	263
+# define	CPP_EQ_OP	        264
+# define    CPP_XOR_OP         265 
+# define	ERROR_SY	    266
+# define	CPP_FLOATCONSTANT	267
+# define	CPP_GE_OP	        268
+# define	CPP_RIGHT_OP        269
+# define	CPP_IDENTIFIER	    270
+# define	CPP_INTCONSTANT	    271
+# define	CPP_LE_OP	        272
+# define	CPP_LEFT_OP	        273
+# define	CPP_DEC_OP	274
+# define	CPP_NE_OP	        275
+# define	CPP_OR_OP	        276
+# define	CPP_INC_OP	    277
+# define	CPP_STRCONSTANT	    278
+# define	CPP_TYPEIDENTIFIER	279
+
+# define	FIRST_USER_TOKEN_SY	289
+
+# define	CPP_RIGHT_ASSIGN	    280
+# define	CPP_LEFT_ASSIGN	    281
+# define	CPP_AND_ASSIGN	282
+# define	CPP_OR_ASSIGN  	283
+# define	CPP_XOR_ASSIGN	284
+# define	CPP_LEFT_BRACKET	285
+# define	CPP_RIGHT_BRACKET	286
+# define	CPP_LEFT_BRACE	287
+# define	CPP_RIGHT_BRACE	288
+
+#endif /* not BISON_PARSER_H */
diff --git a/Compiler/Preprocessor/preprocess.h b/Compiler/Preprocessor/preprocess.h
new file mode 100644
index 0000000..323cd1e
--- /dev/null
+++ b/Compiler/Preprocessor/preprocess.h
@@ -0,0 +1,56 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+
+# include "slglobals.h"
+extern CPPStruct *cpp;
+int InitCPPStruct(void);
+int InitScanner(CPPStruct *cpp);
+int InitAtomTable(AtomTable *atable, int htsize);
+int ScanFromString(char *s);
+char* GetStringOfAtom(AtomTable *atable, int atom);
diff --git a/Compiler/Preprocessor/scanner.c b/Compiler/Preprocessor/scanner.c
new file mode 100644
index 0000000..fcdf751
--- /dev/null
+++ b/Compiler/Preprocessor/scanner.c
@@ -0,0 +1,766 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// scanner.c
+//
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+    #include <ieeefp.h>
+    #else
+    #define isinff(x) (((*(int *)&(x) & 0x7f800000L)==0x7f800000L) && \
+                       ((*(int *)&(x) & 0x007fffffL)==0000000000L))
+#endif
+
+#include "slglobals.h"
+
+
+typedef struct StringInputSrc {
+    InputSrc base;
+    char *p;
+} StringInputSrc;
+
+static int eof_scan(InputSrc *is, yystypepp * yylvalpp)
+{
+    return EOF;
+} // eof_scan
+
+static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) {}
+
+static InputSrc eof_inputsrc = { 0, &eof_scan, &eof_scan, &noop };
+
+static int byte_scan(InputSrc *, yystypepp * yylvalpp);
+
+#define EOL_SY '\n'
+
+#if defined(_WIN32)
+    #define DBG_BREAKPOINT() __asm int 3
+    #elif defined(_M_AMD64)
+    #define DBG_BREAKPOINT() assert(!"Dbg_Breakpoint");
+    #else
+    #define DBG_BREAKPOINT()
+    #endif
+
+    #if defined(_WIN32) && !defined(_M_AMD64)
+    __int64 RDTSC ( void ) {
+
+        __int64 v;
+    
+        __asm __emit 0x0f
+        __asm __emit 0x31
+        __asm mov dword ptr v, eax
+        __asm mov dword ptr v+4, edx
+    
+        return v;
+    }
+#endif
+
+
+int InitScanner(CPPStruct *cpp)
+{
+    // Add various atoms needed by the CPP line scanner:
+    if (!InitCPP())
+        return 0;
+
+    cpp->mostRecentToken = 0;
+    cpp->tokenLoc = &cpp->ltokenLoc;
+
+    cpp->ltokenLoc.file = 0;
+    cpp->ltokenLoc.line = 0;
+
+    cpp->currentInput = &eof_inputsrc;
+    cpp->previous_token = '\n';
+    cpp->notAVersionToken = 0;
+
+    return 1;
+} // InitScanner
+
+int FreeScanner(void)
+{
+    return (FreeCPP());
+}
+
+/*
+ * str_getch()
+ * takes care of reading from multiple strings.
+ * returns the next-char from the input stream.
+ * returns EOF when the complete shader is parsed.
+ */
+static int str_getch(StringInputSrc *in)
+{
+	for(;;){
+	   if (*in->p){
+	      if (*in->p == '\n') {
+             in->base.line++;
+             IncLineNumber();
+          }
+          return *in->p++;
+	   }
+	   if(++(cpp->PaWhichStr) < cpp->PaArgc){
+		  free(in);
+		  SetStringNumber(cpp->PaWhichStr);
+    	  SetLineNumber(1);
+		  ScanFromString(cpp->PaArgv[cpp->PaWhichStr]);
+		  in=(StringInputSrc*)cpp->currentInput;
+	      continue;             
+	   }
+	   else{
+	      cpp->currentInput = in->base.prev;
+	      cpp->PaWhichStr=0;
+          free(in);
+          return EOF;
+       }  
+	}
+} // str_getch
+
+static void str_ungetch(StringInputSrc *in, int ch, yystypepp *type) {
+    if (in->p[-1] == ch)in->p--;
+	else {
+		*(in->p)='\0'; //this would take care of shifting to the previous string.
+	    cpp->PaWhichStr--;
+	}  
+	if (ch == '\n') {
+        in->base.line--;
+        DecLineNumber();
+    }
+} // str_ungetch
+
+int ScanFromString(char *s)
+{
+    
+	StringInputSrc *in = malloc(sizeof(StringInputSrc));
+    memset(in, 0, sizeof(StringInputSrc));
+	in->p = s;
+    in->base.line = 1;
+    in->base.scan = byte_scan;
+    in->base.getch = (int (*)(InputSrc *, yystypepp *))str_getch;
+    in->base.ungetch = (void (*)(InputSrc *, int, yystypepp *))str_ungetch;
+    in->base.prev = cpp->currentInput;
+    cpp->currentInput = &in->base;
+
+    return 1;
+} // ScanFromString;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// Floating point constants: /////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ * lBuildFloatValue() - Quick and dirty conversion to floating point.  Since all
+ *         we need is single precision this should be quite precise.
+ */
+
+static float lBuildFloatValue(const char *str, int len, int exp)
+{
+    double val, expval, ten;
+    int ii, llen, absexp;
+    float rv;
+
+    val = 0.0;
+    llen = len;
+    for (ii = 0; ii < len; ii++)
+        val = val*10.0 + (str[ii] - '0');
+    if (exp != 0) {
+        absexp = exp > 0 ? exp : -exp;
+        expval = 1.0f;
+        ten = 10.0;
+        while (absexp) {
+            if (absexp & 1)
+                expval *= ten;
+            ten *= ten;
+            absexp >>= 1;
+        }
+        if (exp >= 0) {
+            val *= expval;
+        } else {
+            val /= expval;
+        }
+    }
+    rv = (float)val;
+    if (isinff(rv)) {
+		CPPErrorToInfoLog(" ERROR___FP_CONST_OVERFLOW");
+    }
+    return rv;
+} // lBuildFloatValue
+
+
+/*
+ * lFloatConst() - Scan a floating point constant.  Assumes that the scanner
+ *         has seen at least one digit, followed by either a decimal '.' or the
+ *         letter 'e'.
+ */
+
+static int lFloatConst(char *str, int len, int ch, yystypepp * yylvalpp)
+{
+    int HasDecimal, declen, exp, ExpSign;
+    int str_len;
+    float lval;
+    
+    HasDecimal = 0;
+    declen = 0;
+    exp = 0;
+	
+    str_len=len;
+    if (ch == '.') {
+		str[len++]=ch;
+        HasDecimal = 1;
+        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        while (ch >= '0' && ch <= '9') {
+            if (len < MAX_SYMBOL_NAME_LEN) {
+                declen++;
+                if (len > 0 || ch != '0') {
+                    str[len] = ch;
+                    len++;str_len++;
+                }
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            } else {
+                CPPErrorToInfoLog("ERROR___FP_CONST_TOO_LONG");
+                len = 1,str_len=1;
+            }
+        }
+    }
+
+    // Exponent:
+
+    if (ch == 'e' || ch == 'E') {
+        ExpSign = 1;
+		str[len++]=ch;
+        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        if (ch == '+') {
+            str[len++]=ch;  
+			ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        } else if (ch == '-') {
+            ExpSign = -1;
+			str[len++]=ch;
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        }
+        if (ch >= '0' && ch <= '9') {
+            while (ch >= '0' && ch <= '9') {
+                exp = exp*10 + ch - '0';
+				str[len++]=ch;
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            }
+        } else {
+            CPPErrorToInfoLog("ERROR___ERROR_IN_EXPONENT");
+        }
+        exp *= ExpSign;
+    }
+      
+    if (len == 0) {
+        lval = 0.0f;
+		strcpy(str,"0.0");
+    } else {
+        str[len]='\0';      
+        lval = lBuildFloatValue(str, str_len, exp - declen);
+    }
+    // Suffix:
+    
+    yylvalpp->sc_fval = lval;
+    strcpy(yylvalpp->symbol_name,str);
+    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);            
+    return CPP_FLOATCONSTANT;
+} // lFloatConst
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////// Normal Scanner //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+    
+static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
+{
+    char symbol_name[MAX_SYMBOL_NAME_LEN + 1];
+    char string_val[MAX_STRING_LEN + 1];
+    int AlreadyComplained;
+    int len, ch, ii, ival = 0;
+
+    for (;;) {
+        yylvalpp->sc_int = 0;
+        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+		
+        while (ch == ' ' || ch == '\t' || ch == '\r') {
+            yylvalpp->sc_int = 1;
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        }
+		
+        cpp->ltokenLoc.file = cpp->currentInput->name;
+        cpp->ltokenLoc.line = cpp->currentInput->line;
+        len = 0;
+        switch (ch) {
+        default:
+			return ch; // Single character token
+        case EOF:
+            return -1;
+		case 'A': case 'B': case 'C': case 'D': case 'E':
+        case 'F': case 'G': case 'H': case 'I': case 'J':
+        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 'a': case 'b': case 'c': case 'd': case 'e':
+        case 'f': case 'g': case 'h': case 'i': case 'j':
+        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':            
+            do {
+                if (len < MAX_SYMBOL_NAME_LEN) {
+                    symbol_name[len] = ch;
+                    len++;
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);					
+                } else {
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                }
+            } while ((ch >= 'a' && ch <= 'z') ||
+                     (ch >= 'A' && ch <= 'Z') ||
+                     (ch >= '0' && ch <= '9') ||
+                     ch == '_');
+            if (len >= MAX_SYMBOL_NAME_LEN)
+                len = MAX_SYMBOL_NAME_LEN - 1;
+            symbol_name[len] = '\0';
+            cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+            yylvalpp->sc_ident = LookUpAddString(atable, symbol_name);
+            return CPP_IDENTIFIER;
+            break;
+        case '0':
+            yylvalpp->symbol_name[len++] = ch;
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == 'x' || ch == 'X') {
+				yylvalpp->symbol_name[len++] = ch;
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                if ((ch >= '0' && ch <= '9') ||
+                    (ch >= 'A' && ch <= 'F') ||
+                    (ch >= 'a' && ch <= 'f'))
+                {
+                    AlreadyComplained = 0;
+                    ival = 0;
+                    do {
+						yylvalpp->symbol_name[len++] = ch;
+                        if (ival <= 0x0fffffff) {
+                            if (ch >= '0' && ch <= '9') {
+                                ii = ch - '0';
+                            } else if (ch >= 'A' && ch <= 'F') {
+                                ii = ch - 'A' + 10;
+                            } else {
+                                ii = ch - 'a' + 10;
+                            }
+                            ival = (ival << 4) | ii;
+                        } else {
+                            if (!AlreadyComplained)
+                                CPPErrorToInfoLog("ERROR___HEX_CONST_OVERFLOW");
+                            AlreadyComplained = 1;
+                        }
+                        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                    } while ((ch >= '0' && ch <= '9') ||
+                             (ch >= 'A' && ch <= 'F') ||
+                             (ch >= 'a' && ch <= 'f'));
+                } else {
+                    CPPErrorToInfoLog("ERROR___ERROR_IN_HEX_CONSTANT");
+                }
+                yylvalpp->symbol_name[len] = '\0';
+				cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+				yylvalpp->sc_int = ival;
+                return CPP_INTCONSTANT;
+            } else if (ch >= '0' && ch <= '7') { // octal integer constants
+                AlreadyComplained = 0;
+                ival = 0;
+                do {
+                    yylvalpp->symbol_name[len++] = ch;
+                    if (ival <= 0x1fffffff) {
+                        ii = ch - '0';
+                        ival = (ival << 3) | ii;
+                    } else {
+                        if (!AlreadyComplained)
+                           CPPErrorToInfoLog("ERROR___OCT_CONST_OVERFLOW");
+                        AlreadyComplained = 1;
+                    }
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                } while (ch >= '0' && ch <= '7');
+                if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') 
+                     return lFloatConst(yylvalpp->symbol_name, len, ch, yylvalpp);
+                yylvalpp->symbol_name[len] = '\0';
+				cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+				yylvalpp->sc_int = ival;
+                return CPP_INTCONSTANT;
+            } else {
+				cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+				ch = '0';
+            }
+            // Fall through...
+        case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+            do {
+                if (len < MAX_SYMBOL_NAME_LEN) {
+                    if (len > 0 || ch != '0') {
+                        yylvalpp->symbol_name[len] = ch;
+                   len++;
+                    }
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                }
+            } while (ch >= '0' && ch <= '9');
+            if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') {
+                return lFloatConst(yylvalpp->symbol_name, len, ch, yylvalpp);
+            } else {
+                yylvalpp->symbol_name[len] = '\0';
+				cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                ival = 0;
+                AlreadyComplained = 0;
+                for (ii = 0; ii < len; ii++) {
+                    ch = yylvalpp->symbol_name[ii] - '0';
+                    if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) {
+                        if (!AlreadyComplained)
+                           CPPErrorToInfoLog("ERROR___INTEGER_CONST_OVERFLOW");
+                        AlreadyComplained = 1;
+                    }
+                    ival = ival*10 + ch;
+                }
+                yylvalpp->sc_int = ival;
+                if(ival==0)
+                   strcpy(yylvalpp->symbol_name,"0");
+                return CPP_INTCONSTANT;
+            }
+            break;
+        case '-':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '-') {
+                return CPP_DEC_OP;
+            } else if (ch == '=') {
+                return CPP_SUB_ASSIGN;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '-';
+            }
+        case '+':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '+') {
+                return CPP_INC_OP;
+            } else if (ch == '=') {
+                return CPP_ADD_ASSIGN;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '+';
+            }
+        case '*':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '=') {
+                return CPP_MUL_ASSIGN;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '*';
+            }
+        case '%':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '=') {
+                return CPP_MOD_ASSIGN;
+            } else if (ch == '>'){
+                return CPP_RIGHT_BRACE;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '%';
+            }
+        case ':':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '>') {
+                return CPP_RIGHT_BRACKET;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return ':';
+            }
+        case '^':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '^') {
+                return CPP_XOR_OP;
+            } else {
+                if (ch == '=')
+                    return CPP_XOR_ASSIGN;
+                else{
+                  cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                  return '^';
+                }
+            }
+        
+        case '=':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '=') {
+                return CPP_EQ_OP;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '=';
+            }
+        case '!':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '=') {
+                return CPP_NE_OP;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '!';
+            }
+        case '|':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '|') {
+                return CPP_OR_OP;
+            } else {
+                if (ch == '=')
+                    return CPP_OR_ASSIGN;
+                else{
+                  cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                  return '|';
+                }
+            }
+        case '&':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '&') {
+                return CPP_AND_OP;
+            } else {
+                if (ch == '=')
+                    return CPP_AND_ASSIGN;
+                else{
+                  cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                  return '&';
+                }
+            }
+        case '<':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '<') {
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                if(ch == '=')
+                    return CPP_LEFT_ASSIGN;
+                else{
+                    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                    return CPP_LEFT_OP;
+                }
+            } else {
+                if (ch == '=') {
+                    return CPP_LE_OP;
+                } else {
+                    if (ch == '%')
+                        return CPP_LEFT_BRACE;
+                    else if (ch == ':')
+                        return CPP_LEFT_BRACKET;
+                    else{
+                        cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                        return '<';
+                    }
+                }
+            }
+        case '>':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '>') {
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                if(ch == '=')
+                    return CPP_RIGHT_ASSIGN;
+                else{
+                    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                    return CPP_RIGHT_OP;
+                }
+            } else {
+                if (ch == '=') {
+                    return CPP_GE_OP;
+                } else {
+                    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                    return '>';
+                }
+            }
+        case '.':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch >= '0' && ch <= '9') {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return lFloatConst(yylvalpp->symbol_name, 0, '.', yylvalpp);
+            } else {
+                if (ch == '.') {
+                    return -1; // Special EOF hack
+                } else {
+                    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                    return '.';
+                }
+            }
+        case '/':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == '/') {
+                do {
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                } while (ch != '\n' && ch != EOF);
+                if (ch == EOF)
+                    return -1;
+                return '\n';
+            } else if (ch == '*') {
+                int nlcount = 0;
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                do {
+                    while (ch != '*') {
+                        if (ch == '\n') nlcount++;
+                        if (ch == EOF) {
+                            CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT");
+                            return -1;
+                        }
+                        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                    }
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                    if (ch == EOF) {
+                        CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT");
+                        return -1;
+                    }
+                } while (ch != '/');
+                if (nlcount) {
+                    return '\n';
+                }
+                // Go try it again...
+            } else if (ch == '=') {
+                return CPP_DIV_ASSIGN;
+            } else {
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                return '/';
+            }
+            break;
+        case '"':
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            while (ch != '"' && ch != '\n' && ch != EOF) {
+                if (ch == '\\') {
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                    if (ch == '\n' || ch == EOF) {
+                        break;
+                    }
+                }
+                if (len < MAX_STRING_LEN) {
+                    string_val[len] = ch;
+                    len++;
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                }
+            };
+            string_val[len] = '\0';
+            if (ch == '"') {
+                yylvalpp->sc_ident = LookUpAddString(atable, string_val);
+                return CPP_STRCONSTANT;
+            } else {
+                CPPErrorToInfoLog("ERROR___CPP_EOL_IN_STRING");
+                return ERROR_SY;
+            }
+        }
+    }
+} // byte_scan
+
+int yylex_CPP(char* buf, int maxSize)
+{    
+	yystypepp yylvalpp;
+    int token = '\n';   
+
+    for(;;) {
+
+        char* tokenString = 0;
+        token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp);
+		if(check_EOF(token))
+		    return 0;
+        if (token == '#') {
+            if (cpp->previous_token == '\n'|| cpp->previous_token == 0) {
+			    token = readCPPline(&yylvalpp);
+                if(check_EOF(token))
+                    return 0;
+			    continue;
+            } else {
+                CPPErrorToInfoLog("preprocessor command must not be preceded by any other statement in that line");
+                return 0;
+            }
+        }
+        cpp->previous_token = token;
+        // expand macros
+        if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp.sc_ident, &yylvalpp)) {
+            cpp->notAVersionToken = 1;
+            continue;
+        }
+        
+        if (token == '\n')
+            continue;
+          
+        if (token == CPP_IDENTIFIER) {                
+            cpp->notAVersionToken = 1;
+            tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident);
+        } else if (token == CPP_FLOATCONSTANT||token == CPP_INTCONSTANT){             
+            cpp->notAVersionToken = 1;            
+            tokenString = yylvalpp.symbol_name;
+		} else {            
+            cpp->notAVersionToken = 1;            
+            tokenString = GetStringOfAtom(atable,token);
+	    }
+
+        if (tokenString) {
+            if ((signed)strlen(tokenString) >= maxSize) {
+                cpp->tokensBeforeEOF = 1;
+                return maxSize;               
+            } else  if (strlen(tokenString) > 0) {
+			    strcpy(buf, tokenString);
+                cpp->tokensBeforeEOF = 1;
+                return (int)strlen(tokenString);
+            }  
+
+            return 0;
+        }
+    }
+
+    return 0;
+} // yylex
+
+//Checks if the token just read is EOF or not.
+int check_EOF(int token)
+{
+   if(token==-1){
+       if(cpp->ifdepth >0){
+		CPPErrorToInfoLog("#endif missing!! Compilation stopped");
+        cpp->CompileError=1;
+       }
+      return 1;
+   }
+   return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////// End of scanner.c //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/Compiler/Preprocessor/scanner.h b/Compiler/Preprocessor/scanner.h
new file mode 100644
index 0000000..288a090
--- /dev/null
+++ b/Compiler/Preprocessor/scanner.h
@@ -0,0 +1,90 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// scanner.h
+//
+
+#if !defined(__SCANNER_H)
+#define __SCANNER_H 1
+
+#define MAX_SYMBOL_NAME_LEN 128
+#define MAX_STRING_LEN 512
+
+#include "parser.h"
+
+// Not really atom table stuff but needed first...
+
+typedef struct SourceLoc_Rec {
+    unsigned short file, line;
+} SourceLoc;
+
+int yyparse (void);
+
+int yylex_CPP(char* buf, int maxSize);
+
+typedef struct InputSrc {
+    struct InputSrc	*prev;
+    int			(*scan)(struct InputSrc *, yystypepp *);
+    int			(*getch)(struct InputSrc *, yystypepp *);
+    void		(*ungetch)(struct InputSrc *, int, yystypepp *);
+    int			name;  /* atom */
+    int			line;
+} InputSrc;
+
+int InitScanner(CPPStruct *cpp);   // Intialise the cpp scanner. 
+int ScanFromString(char *);      // Start scanning the input from the string mentioned.
+int check_EOF(int);              // check if we hit a EOF abruptly 
+void CPPErrorToInfoLog(char *);   // sticking the msg,line into the Shader's.Info.log
+void SetLineNumber(int);
+void SetStringNumber(int);
+void IncLineNumber(void);
+void DecLineNumber(void);
+int FreeScanner(void);                 // Free the cpp scanner
+#endif // !(defined(__SCANNER_H)
+
diff --git a/Compiler/Preprocessor/slglobals.h b/Compiler/Preprocessor/slglobals.h
new file mode 100644
index 0000000..852502f
--- /dev/null
+++ b/Compiler/Preprocessor/slglobals.h
@@ -0,0 +1,87 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// slglobals.h
+//
+
+#if !defined(__SLGLOBALS_H)
+#define __SLGLOBALS_H 1
+
+typedef struct CPPStruct_Rec CPPStruct;
+
+extern CPPStruct *cpp;
+
+#undef  CPPC_DEBUG_THE_COMPILER
+#if defined(_DEBUG)
+#define CPPC_DEBUG_THE_COMPILER 1
+#endif
+
+#undef  CPPC_ENABLE_TOOLS
+#define CPPC_ENABLE_TOOLS 1
+
+#include "memory.h"
+#include "atom.h"
+#include "scanner.h"
+#include "cpp.h"
+#include "tokens.h"
+#include "symbols.h"
+#include "compile.h"
+#if !defined(NO_PARSER)
+#include "parser.h"
+#endif
+
+#if !defined(NULL)
+#define NULL 0
+#endif
+
+#endif // !(defined(__SLGLOBALS_H)
+
+
+    
+
diff --git a/Compiler/Preprocessor/symbols.c b/Compiler/Preprocessor/symbols.c
new file mode 100644
index 0000000..d97bae0
--- /dev/null
+++ b/Compiler/Preprocessor/symbols.c
@@ -0,0 +1,290 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// symbols.c
+//
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "slglobals.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// Symbol Table Variables: ///////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+Scope *ScopeList = NULL;
+Scope *CurrentScope = NULL;
+Scope *GlobalScope = NULL;
+
+static void unlinkScope(void *_scope) {
+    Scope *scope = _scope;
+
+    if (scope->next)
+        scope->next->prev = scope->prev;
+    if (scope->prev)
+        scope->prev->next = scope->next;
+    else
+        ScopeList = scope->next;
+}
+
+/*
+ * NewScope()
+ *
+ */
+Scope *NewScopeInPool(MemoryPool *pool)
+{
+    Scope *lScope;
+
+    lScope = mem_Alloc(pool, sizeof(Scope));
+    lScope->pool = pool;
+    lScope->parent = NULL;
+    lScope->funScope = NULL;
+    lScope->symbols = NULL;
+    
+    lScope->level = 0;
+
+    lScope->programs = NULL;
+    if ((lScope->next = ScopeList))
+        ScopeList->prev = lScope;
+    lScope->prev = 0;
+    ScopeList = lScope;
+    mem_AddCleanup(pool, unlinkScope, lScope);
+    return lScope;
+} // NewScope
+
+/*
+ * PushScope()
+ *
+ */
+
+void PushScope(Scope *fScope)
+{
+    Scope *lScope;
+
+    if (CurrentScope) {
+        fScope->level = CurrentScope->level + 1;
+        if (fScope->level == 1) {
+            if (!GlobalScope) {
+                /* HACK - CTD -- if GlobalScope==NULL and level==1, we're
+                 * defining a function in the superglobal scope.  Things
+                 * will break if we leave the level as 1, so we arbitrarily
+                 * set it to 2 */
+                fScope->level = 2;
+            }
+        }
+        if (fScope->level >= 2) {
+            lScope = fScope;
+            while (lScope->level > 2)
+                lScope = lScope->next;
+            fScope->funScope = lScope;
+        }
+    } else {
+        fScope->level = 0;
+    }
+    fScope->parent = CurrentScope;
+    CurrentScope = fScope;
+} // PushScope
+
+/*
+ * PopScope()
+ *
+ */
+
+Scope *PopScope(void)
+{
+    Scope *lScope;
+
+    lScope = CurrentScope;
+    if (CurrentScope)
+        CurrentScope = CurrentScope->parent;
+    return lScope;
+} // PopScope
+
+/*
+ * NewSymbol() - Allocate a new symbol node;
+ *
+ */
+
+Symbol *NewSymbol(SourceLoc *loc, Scope *fScope, int name, symbolkind kind)
+{
+    Symbol *lSymb;
+    char *pch;
+    int ii;
+
+    lSymb = (Symbol *) mem_Alloc(fScope->pool, sizeof(Symbol));
+    lSymb->left = NULL;
+    lSymb->right = NULL;
+    lSymb->next = NULL;
+    lSymb->name = name;
+    lSymb->loc = *loc;
+    lSymb->kind = kind;
+    
+    // Clear union area:
+
+    pch = (char *) &lSymb->details;
+    for (ii = 0; ii < sizeof(lSymb->details); ii++)
+        *pch++ = 0;
+    return lSymb;
+} // NewSymbol
+
+/*
+ * lAddToTree() - Using a binary tree is not a good idea for basic atom values because they
+ *         are generated in order.  We'll fix this later (by reversing the bit pattern).
+ */
+
+static void lAddToTree(Symbol **fSymbols, Symbol *fSymb)
+{
+    Symbol *lSymb;
+    int lrev, frev;
+
+    lSymb = *fSymbols;
+    if (lSymb) {
+        frev = GetReversedAtom(atable, fSymb->name);
+        while (lSymb) {
+            lrev = GetReversedAtom(atable, lSymb->name);
+            if (lrev == frev) {
+                CPPErrorToInfoLog("GetAtomString(atable, fSymb->name)");
+                break;
+            } else {
+                if (lrev > frev) {
+                    if (lSymb->left) {
+                        lSymb = lSymb->left;
+                    } else {
+                        lSymb->left = fSymb;
+                        break;
+                    }
+                } else {
+                    if (lSymb->right) {
+                        lSymb = lSymb->right;
+                    } else {
+                        lSymb->right = fSymb;
+                        break;
+                    }
+                }
+            }
+        }
+    } else {
+        *fSymbols = fSymb;
+    }
+} // lAddToTree
+
+
+/*
+ * AddSymbol() - Add a variable, type, or function name to a scope.
+ *
+ */
+
+Symbol *AddSymbol(SourceLoc *loc, Scope *fScope, int atom, symbolkind kind)
+{
+    Symbol *lSymb;
+
+    if (!fScope)
+        fScope = CurrentScope;
+    lSymb = NewSymbol(loc, fScope, atom, kind);
+    lAddToTree(&fScope->symbols, lSymb);
+    return lSymb;
+} // AddSymbol
+
+
+/*********************************************************************************************/
+/************************************ Symbol Semantic Functions ******************************/
+/*********************************************************************************************/
+
+/*
+ * LookUpLocalSymbol()
+ *
+ */
+
+Symbol *LookUpLocalSymbol(Scope *fScope, int atom)
+{
+    Symbol *lSymb;
+    int rname, ratom;
+
+    ratom = GetReversedAtom(atable, atom);
+    if (!fScope)
+        fScope = CurrentScope;
+    lSymb = fScope->symbols;
+    while (lSymb) {
+        rname = GetReversedAtom(atable, lSymb->name);
+        if (rname == ratom) {
+            return lSymb;
+        } else {
+            if (rname > ratom) {
+                lSymb = lSymb->left;
+            } else {
+                lSymb = lSymb->right;
+            }
+        }
+    }
+    return NULL;
+} // LookUpLocalSymbol
+
+/*
+ * LookUpSymbol()
+ *
+ */
+
+Symbol *LookUpSymbol(Scope *fScope, int atom)
+{
+    Symbol *lSymb;
+
+    if (!fScope)
+        fScope = CurrentScope;
+    while (fScope) {
+        lSymb = LookUpLocalSymbol(fScope, atom);
+        if (lSymb)
+            return lSymb;
+        fScope = fScope->parent;
+    }
+    return NULL;
+} // LookUpSymbol
+
diff --git a/Compiler/Preprocessor/symbols.h b/Compiler/Preprocessor/symbols.h
new file mode 100644
index 0000000..a94adbf
--- /dev/null
+++ b/Compiler/Preprocessor/symbols.h
@@ -0,0 +1,117 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// symbols.h
+//
+
+#if !defined(__SYMBOLS_H)
+#define __SYMBOLS_H 1
+
+#include "memory.h"
+
+typedef enum symbolkind {
+   MACRO_S
+} symbolkind;
+
+// Typedefs for things defined here in "symbols.h":
+
+typedef struct Scope_Rec Scope;
+typedef struct Symbol_Rec Symbol;
+
+typedef struct SymbolList_Rec {
+    struct SymbolList_Rec *next;
+    Symbol *symb;
+} SymbolList;
+
+struct Scope_Rec {
+    Scope *next, *prev;     // doubly-linked list of all scopes
+    Scope *parent;
+    Scope *funScope;        // Points to base scope of enclosing function
+    MemoryPool *pool;       // pool used for allocation in this scope
+    Symbol *symbols;
+    
+	int level;              // 0 = super globals, 1 = globals, etc.
+
+    // Only used at global scope (level 1):
+    SymbolList *programs;   // List of programs for this compilation.
+};
+
+
+// Symbol table is a simple binary tree.
+
+#include "cpp.h"        // to get MacroSymbol def
+
+struct Symbol_Rec {
+    Symbol *left, *right;
+    Symbol *next;
+    int name;       // Name atom
+    SourceLoc loc;
+    symbolkind kind;
+    union {
+        MacroSymbol mac;
+    } details;
+};
+
+extern Scope *CurrentScope;
+extern Scope *GlobalScope;
+extern Scope *ScopeList;
+
+Scope *NewScopeInPool(MemoryPool *);
+#define NewScope()      NewScopeInPool(CurrentScope->pool)
+void PushScope(Scope *fScope);
+Scope *PopScope(void);
+Symbol *NewSymbol(SourceLoc *loc, Scope *fScope, int name, symbolkind kind);
+Symbol *AddSymbol(SourceLoc *loc, Scope *fScope, int atom, symbolkind kind);
+Symbol *LookUpLocalSymbol(Scope *fScope, int atom);
+Symbol *LookUpSymbol(Scope *fScope, int atom);
+void CPPErrorToInfoLog(char *);
+
+
+#endif // !defined(__SYMBOLS_H)
+
diff --git a/Compiler/Preprocessor/tokens.c b/Compiler/Preprocessor/tokens.c
new file mode 100644
index 0000000..b508f03
--- /dev/null
+++ b/Compiler/Preprocessor/tokens.c
@@ -0,0 +1,444 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// tokens.c
+//
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "slglobals.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////// Preprocessor and Token Recorder and Playback: ////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * idstr()
+ * Copy a string to a malloc'ed block and convert it into something suitable
+ * for an ID
+ *
+ */
+
+static char *idstr(const char *fstr, MemoryPool *pool)
+{
+    size_t len;
+    char *str, *t;
+    const char *f;
+
+    len = strlen(fstr);
+    if (!pool)
+        str = (char *) malloc(len + 1);
+    else
+        str = (char *) mem_Alloc(pool, len + 1);
+    
+    for (f=fstr, t=str; *f; f++) {
+        if (isalnum(*f)) *t++ = *f;
+        else if (*f == '.' || *f == '/') *t++ = '_';
+    }
+    *t = 0;
+    return str;
+} // idstr
+
+
+/*
+ * lNewBlock()
+ *
+ */
+
+static TokenBlock *lNewBlock(TokenStream *fTok, MemoryPool *pool)
+{
+    TokenBlock *lBlock;
+
+    if (!pool)
+        lBlock = (TokenBlock *) malloc(sizeof(TokenBlock) + 256);
+    else
+        lBlock = (TokenBlock *) mem_Alloc(pool, sizeof(TokenBlock) + 256);
+    lBlock->count = 0;
+    lBlock->current = 0;
+    lBlock->data = (unsigned char *) lBlock + sizeof(TokenBlock);
+    lBlock->max = 256;
+    lBlock->next = NULL;
+    if (fTok->head) {
+        fTok->current->next = lBlock;
+    } else {
+        fTok->head = lBlock;
+    }
+    fTok->current = lBlock;
+    return lBlock;
+} // lNewBlock
+
+/*
+ * lAddByte()
+ *
+ */
+
+static void lAddByte(TokenStream *fTok, unsigned char fVal)
+{
+    TokenBlock *lBlock;
+    lBlock = fTok->current;
+    if (lBlock->count >= lBlock->max)
+        lBlock = lNewBlock(fTok, 0);
+    lBlock->data[lBlock->count++] = fVal;
+} // lAddByte
+
+
+
+/*
+ * lReadByte() - Get the next byte from a stream.
+ *
+ */
+
+static int lReadByte(TokenStream *pTok)
+{
+    TokenBlock *lBlock;
+    int lval = -1;
+
+    lBlock = pTok->current;
+    if (lBlock) {
+        if (lBlock->current >= lBlock->count) {
+            lBlock = lBlock->next;
+            if (lBlock)
+                lBlock->current = 0;
+            pTok->current = lBlock;
+        }
+        if (lBlock)
+            lval = lBlock->data[lBlock->current++];
+    }
+    return lval;
+} // lReadByte
+
+/////////////////////////////////////// Global Functions://////////////////////////////////////
+
+/*
+ * NewTokenStream()
+ *
+ */
+
+TokenStream *NewTokenStream(const char *name, MemoryPool *pool)
+{
+    TokenStream *pTok;
+
+    if (!pool)
+        pTok = (TokenStream *) malloc(sizeof(TokenStream));
+    else
+        pTok = (TokenStream*)mem_Alloc(pool, sizeof(TokenStream));
+    pTok->next = NULL;
+    pTok->name = idstr(name, pool);
+    pTok->head = NULL;
+    pTok->current = NULL;
+    lNewBlock(pTok, pool);
+    return pTok;
+} // NewTokenStream
+
+/*
+ * DeleteTokenStream()
+ *
+ */
+
+void DeleteTokenStream(TokenStream *pTok)
+{
+    TokenBlock *pBlock, *nBlock;
+
+    if (pTok) {
+        pBlock = pTok->head;
+        while (pBlock) {
+            nBlock = pBlock->next;
+            free(pBlock);
+            pBlock = nBlock;
+        }
+        if (pTok->name)
+            free(pTok->name);
+        free(pTok);
+    }
+} // DeleteTokenStream
+
+/*
+ * RecordToken() - Add a token to the end of a list for later playback or printout.
+ *
+ */
+
+void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp)
+{
+    const char *s;
+    unsigned char *str=NULL;
+
+    if (token > 256)
+        lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80));
+    else
+        lAddByte(pTok, (unsigned char)(token & 0x7f));
+    switch (token) {
+    case CPP_IDENTIFIER:
+    case CPP_TYPEIDENTIFIER:
+    case CPP_STRCONSTANT:
+        s = GetAtomString(atable, yylvalpp->sc_ident);
+        while (*s)
+            lAddByte(pTok, (unsigned char) *s++);
+        lAddByte(pTok, 0);
+        break;
+    case CPP_FLOATCONSTANT:
+    case CPP_INTCONSTANT:
+         str=yylvalpp->symbol_name;
+         while (*str){
+            lAddByte(pTok,(unsigned char) *str);
+            *str++;
+         }
+         lAddByte(pTok, 0);
+         break;
+    case '(':
+        lAddByte(pTok, (unsigned char)(yylvalpp->sc_int ? 1 : 0));
+    default:
+        break;
+    }
+} // RecordToken
+
+/*
+ * RewindTokenStream() - Reset a token stream in preperation for reading.
+ *
+ */
+
+void RewindTokenStream(TokenStream *pTok)
+{
+    if (pTok->head) {
+        pTok->current = pTok->head;
+        pTok->current->current = 0;
+    }
+} // RewindTokenStream
+
+/*
+ * ReadToken() - Read the next token from a stream.
+ *
+ */
+
+int ReadToken(TokenStream *pTok, yystypepp * yylvalpp)
+{
+    char symbol_name[MAX_SYMBOL_NAME_LEN + 1];
+    char string_val[MAX_STRING_LEN + 1];
+    int ltoken, len;
+    char ch;
+
+    ltoken = lReadByte(pTok);
+    if (ltoken >= 0) {
+        if (ltoken > 127)
+            ltoken += 128;
+        switch (ltoken) {
+        case CPP_IDENTIFIER:
+        case CPP_TYPEIDENTIFIER:
+            len = 0;
+            ch = lReadByte(pTok);
+            while ((ch >= 'a' && ch <= 'z') ||
+                     (ch >= 'A' && ch <= 'Z') ||
+                     (ch >= '0' && ch <= '9') ||
+                     ch == '_')
+            {
+                if (len < MAX_SYMBOL_NAME_LEN) {
+                    symbol_name[len] = ch;
+                    len++;
+                    ch = lReadByte(pTok);
+                }
+            }
+            symbol_name[len] = '\0';
+            assert(ch == '\0');
+            yylvalpp->sc_ident = LookUpAddString(atable, symbol_name);
+            return CPP_IDENTIFIER;
+            break;
+        case CPP_STRCONSTANT:
+            len = 0;
+            while ((ch = lReadByte(pTok)) != 0)
+                if (len < MAX_STRING_LEN)
+                    string_val[len++] = ch;
+            string_val[len] = 0;
+            yylvalpp->sc_ident = LookUpAddString(atable, string_val);
+            break;
+        case CPP_FLOATCONSTANT:
+            len = 0;
+            ch = lReadByte(pTok);
+            while ((ch >= '0' && ch <= '9')||(ch=='e'||ch=='E'||ch=='.')||(ch=='+'||ch=='-'))
+            {
+                if (len < MAX_SYMBOL_NAME_LEN) {
+                    symbol_name[len] = ch;
+                    len++;
+                    ch = lReadByte(pTok);
+                }
+            }
+            symbol_name[len] = '\0';
+            assert(ch == '\0');
+            strcpy(yylvalpp->symbol_name,symbol_name);
+            yylvalpp->sc_fval=(float)atof(yylvalpp->symbol_name);
+            break;
+        case CPP_INTCONSTANT:
+            len = 0;
+            ch = lReadByte(pTok);
+            while ((ch >= '0' && ch <= '9'))
+            {
+                if (len < MAX_SYMBOL_NAME_LEN) {
+                    symbol_name[len] = ch;
+                    len++;
+                    ch = lReadByte(pTok);
+                }
+            }
+            symbol_name[len] = '\0';
+            assert(ch == '\0');
+            strcpy(yylvalpp->symbol_name,symbol_name);
+            yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
+            break;
+        case '(':
+            yylvalpp->sc_int = lReadByte(pTok);
+            break;
+        }
+        return ltoken;
+    }
+    return EOF_SY;
+} // ReadToken
+
+typedef struct TokenInputSrc {
+    InputSrc            base;
+    TokenStream         *tokens;
+    int                 (*final)(CPPStruct *);
+} TokenInputSrc;
+
+static int scan_token(TokenInputSrc *in, yystypepp * yylvalpp)
+{
+    int token = ReadToken(in->tokens, yylvalpp);
+    int (*final)(CPPStruct *);
+    cpp->tokenLoc->file = cpp->currentInput->name;
+    cpp->tokenLoc->line = cpp->currentInput->line;
+    if (token == '\n') {
+        in->base.line++;
+        return token;
+    }
+    if (token > 0) return token;
+    cpp->currentInput = in->base.prev;
+    final = in->final;
+    free(in);
+    if (final && !final(cpp)) return -1;
+    return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+}
+
+int ReadFromTokenStream(TokenStream *ts, int name, int (*final)(CPPStruct *))
+{
+    TokenInputSrc *in = malloc(sizeof(TokenInputSrc));
+    memset(in, 0, sizeof(TokenInputSrc));
+    in->base.name = name;
+    in->base.prev = cpp->currentInput;
+    in->base.scan = (int (*)(InputSrc *, yystypepp *))scan_token;
+    in->base.line = 1;
+    in->tokens = ts;
+    in->final = final;
+    RewindTokenStream(ts);
+    cpp->currentInput = &in->base;
+    return 1;
+}
+
+typedef struct UngotToken {
+    InputSrc    base;
+    int         token;
+    yystypepp     lval;
+} UngotToken;
+
+static int reget_token(UngotToken *t, yystypepp * yylvalpp)
+{
+    int token = t->token;
+    *yylvalpp = t->lval;
+    cpp->currentInput = t->base.prev;
+    free(t);
+    return token;
+}
+
+void UngetToken(int token, yystypepp * yylvalpp) {
+    UngotToken *t = malloc(sizeof(UngotToken));
+    memset(t, 0, sizeof(UngotToken));
+    t->token = token;
+    t->lval = *yylvalpp;
+    t->base.scan = (void *)reget_token;
+    t->base.prev = cpp->currentInput;
+    t->base.name = cpp->currentInput->name;
+    t->base.line = cpp->currentInput->line;
+    cpp->currentInput = &t->base;
+}
+
+
+void DumpTokenStream(FILE *fp, TokenStream *s, yystypepp * yylvalpp) {
+    int token;
+    char str[100];
+
+    if (fp == 0) fp = stdout;
+    RewindTokenStream(s);
+    while ((token = ReadToken(s, yylvalpp)) > 0) {
+        switch (token) {
+        case CPP_IDENTIFIER:
+        case CPP_TYPEIDENTIFIER:
+            sprintf(str, "%s ", GetAtomString(atable, yylvalpp->sc_ident));
+            break;
+        case CPP_STRCONSTANT:
+            sprintf(str, "\"%s\"", GetAtomString(atable, yylvalpp->sc_ident));
+            break;
+        case CPP_FLOATCONSTANT:
+            //printf("%g9.6 ", yylvalpp->sc_fval);
+            break;
+        case CPP_INTCONSTANT:
+            //printf("%d ", yylvalpp->sc_int);
+            break;
+        default:
+            if (token >= 127)
+                sprintf(str, "%s ", GetAtomString(atable, token));
+            else
+                sprintf(str, "%c", token);
+            break;
+        }
+        CPPDebugLogMsg(str);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////// End of tokens.c ///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/Compiler/Preprocessor/tokens.h b/Compiler/Preprocessor/tokens.h
new file mode 100644
index 0000000..19938d7
--- /dev/null
+++ b/Compiler/Preprocessor/tokens.h
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+/****************************************************************************\
+Copyright (c) 2002, NVIDIA Corporation.
+
+NVIDIA Corporation("NVIDIA") supplies this software to you in
+consideration of your agreement to the following terms, and your use,
+installation, modification or redistribution of this NVIDIA software
+constitutes acceptance of these terms.  If you do not agree with these
+terms, please do not use, install, modify or redistribute this NVIDIA
+software.
+
+In consideration of your agreement to abide by the following terms, and
+subject to these terms, NVIDIA grants you a personal, non-exclusive
+license, under NVIDIA's copyrights in this original NVIDIA software (the
+"NVIDIA Software"), to use, reproduce, modify and redistribute the
+NVIDIA Software, with or without modifications, in source and/or binary
+forms; provided that if you redistribute the NVIDIA Software, you must
+retain the copyright notice of NVIDIA, this notice and the following
+text and disclaimers in all such redistributions of the NVIDIA Software.
+Neither the name, trademarks, service marks nor logos of NVIDIA
+Corporation may be used to endorse or promote products derived from the
+NVIDIA Software without specific prior written permission from NVIDIA.
+Except as expressly stated in this notice, no other rights or licenses
+express or implied, are granted by NVIDIA herein, including but not
+limited to any patent rights that may be infringed by your derivative
+works or by other works in which the NVIDIA Software may be
+incorporated. No hardware is licensed hereunder. 
+
+THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
+INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
+PRODUCTS.
+
+IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
+INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
+OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
+NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
+TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
+NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\****************************************************************************/
+//
+// tokens.h
+//
+
+#if !defined(__TOKENS_H)
+#define __TOKENS_H 1
+
+#include "parser.h"
+
+#define EOF_SY (-1)
+
+typedef struct TokenBlock_Rec TokenBlock;
+
+typedef struct TokenStream_Rec {
+    struct TokenStream_Rec *next;
+    char *name;
+    TokenBlock *head;
+    TokenBlock *current;
+} TokenStream;
+
+struct TokenBlock_Rec {
+    TokenBlock *next;
+    int current;
+    int count;
+    int max;
+    unsigned char *data;
+};
+
+extern TokenStream stdlib_cpp_stream;
+
+
+TokenStream *NewTokenStream(const char *name, MemoryPool *pool);
+void DeleteTokenStream(TokenStream *pTok); 
+void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp);
+void RewindTokenStream(TokenStream *pTok);
+int ReadToken(TokenStream *pTok, yystypepp * yylvalpp);
+int ReadFromTokenStream(TokenStream *pTok, int name, int (*final)(CPPStruct *));
+void UngetToken(int, yystypepp * yylvalpp);
+
+#if defined(CPPC_ENABLE_TOOLS)
+
+void DumpTokenStream(FILE *, TokenStream *, yystypepp * yylvalpp);
+
+#endif // defined(CPPC_ENABLE_TOOLS)
+
+#endif // !defined(__TOKENS_H)
diff --git a/Compiler/QualifierAlive.cpp b/Compiler/QualifierAlive.cpp
new file mode 100644
index 0000000..e47fd6f
--- /dev/null
+++ b/Compiler/QualifierAlive.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "intermediate.h"
+
+class TAliveTraverser : public TIntermTraverser {
+public:
+    TAliveTraverser(TQualifier q) : TIntermTraverser(true, false, false, true), found(false), qualifier(q)
+    {
+    }
+
+	bool wasFound() { return found; }
+
+protected:
+    bool found;
+    TQualifier qualifier;
+
+    void visitSymbol(TIntermSymbol*);
+    bool visitSelection(Visit, TIntermSelection*);
+};
+
+//
+// Report whether or not a variable of the given qualifier type
+// is guaranteed written.  Not always possible to determine if
+// it is written conditionally.
+//
+// ?? It does not do this well yet, this is just a place holder
+// that simply determines if it was reference at all, anywhere.
+//
+bool QualifierWritten(TIntermNode* node, TQualifier qualifier)
+{
+    TAliveTraverser it(qualifier);
+
+    if (node)
+        node->traverse(&it);
+
+    return it.wasFound();
+}
+
+void TAliveTraverser::visitSymbol(TIntermSymbol* node)
+{
+    //
+    // If it's what we're looking for, record it.
+    //
+    if (node->getQualifier() == qualifier)
+        found = true;
+}
+
+bool TAliveTraverser::visitSelection(Visit preVisit, TIntermSelection* node)
+{
+    if (wasFound())
+        return false;
+
+    return true;
+}
diff --git a/Compiler/QualifierAlive.h b/Compiler/QualifierAlive.h
new file mode 100644
index 0000000..872a06f
--- /dev/null
+++ b/Compiler/QualifierAlive.h
@@ -0,0 +1,7 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+bool QualifierWritten(TIntermNode* root, TQualifier);
diff --git a/Compiler/RemoveTree.cpp b/Compiler/RemoveTree.cpp
new file mode 100644
index 0000000..9c4162e
--- /dev/null
+++ b/Compiler/RemoveTree.cpp
@@ -0,0 +1,76 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "intermediate.h"
+#include "RemoveTree.h"
+//
+// Code to recursively delete the intermediate tree.
+//
+
+class RemoveTree : public TIntermTraverser
+{
+public:
+	RemoveTree() : TIntermTraverser(false, false, true)
+	{
+	}
+
+protected:
+	void visitSymbol(TIntermSymbol*);
+	void visitConstantUnion(TIntermConstantUnion*);
+	bool visitBinary(Visit visit, TIntermBinary*);
+	bool visitUnary(Visit visit, TIntermUnary*);
+	bool visitSelection(Visit visit, TIntermSelection*);
+	bool visitAggregate(Visit visit, TIntermAggregate*);
+};
+
+void RemoveTree::visitSymbol(TIntermSymbol* node)
+{
+	delete node;
+}
+
+bool RemoveTree::visitBinary(Visit visit, TIntermBinary* node)
+{
+	delete node;
+
+	return true;
+}
+
+bool RemoveTree::visitUnary(Visit visit, TIntermUnary* node)
+{
+    delete node;
+
+	return true;
+}
+
+bool RemoveTree::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+	delete node;
+
+	return true;
+}
+
+bool RemoveTree::visitSelection(Visit visit, TIntermSelection* node)
+{
+	delete node;
+
+	return true;
+}
+
+void RemoveTree::visitConstantUnion(TIntermConstantUnion* node)
+{
+	delete node;
+}
+
+//
+// Entry point.
+//
+void RemoveAllTreeNodes(TIntermNode* root)
+{
+    RemoveTree it;
+
+    root->traverse(&it);
+}
+
diff --git a/Compiler/RemoveTree.h b/Compiler/RemoveTree.h
new file mode 100644
index 0000000..97a8216
--- /dev/null
+++ b/Compiler/RemoveTree.h
@@ -0,0 +1,7 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+void RemoveAllTreeNodes(TIntermNode*);
diff --git a/Compiler/ResourceLimits.h b/Compiler/ResourceLimits.h
new file mode 100644
index 0000000..7b7a4b7
--- /dev/null
+++ b/Compiler/ResourceLimits.h
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _RESOURCE_LIMITS_INCLUDED_
+#define _RESOURCE_LIMITS_INCLUDED_
+
+struct TBuiltInResource
+{
+	int maxVertexAttribs;
+	int maxVertexUniformVectors;
+	int maxVaryingVectors;
+	int maxVertexTextureImageUnits;
+	int maxCombinedTextureImageUnits;
+	int maxTextureImageUnits;
+	int maxFragmentUniformVectors;
+	int maxDrawBuffers;
+};
+#endif // _RESOURCE_LIMITS_INCLUDED_
diff --git a/Compiler/ShHandle.h b/Compiler/ShHandle.h
new file mode 100644
index 0000000..cd6353e
--- /dev/null
+++ b/Compiler/ShHandle.h
@@ -0,0 +1,139 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _SHHANDLE_INCLUDED_
+#define _SHHANDLE_INCLUDED_
+
+//
+// Machine independent part of the compiler private objects
+// sent as ShHandle to the driver.
+//
+// This should not be included by driver code.
+//
+
+#include "ShaderLang.h"
+
+#include "InfoSink.h"
+
+class TCompiler;
+class TLinker;
+class TUniformMap;
+
+
+//
+// The base class used to back handles returned to the driver.
+//
+class TShHandleBase {
+public:
+    TShHandleBase() { }
+    virtual ~TShHandleBase() { }
+    virtual TCompiler* getAsCompiler() { return 0; }
+    virtual TLinker* getAsLinker() { return 0; }
+    virtual TUniformMap* getAsUniformMap() { return 0; }
+};
+
+//
+// The base class for the machine dependent linker to derive from
+// for managing where uniforms live.
+//
+class TUniformMap : public TShHandleBase {
+public:
+    TUniformMap() { }
+    virtual ~TUniformMap() { }
+    virtual TUniformMap* getAsUniformMap() { return this; }
+    virtual int getLocation(const char* name) = 0;    
+    virtual TInfoSink& getInfoSink() { return infoSink; }
+    TInfoSink infoSink;
+};
+class TIntermNode;
+
+//
+// The base class for the machine dependent compiler to derive from
+// for managing object code from the compile.
+//
+class TCompiler : public TShHandleBase {
+public:
+    TCompiler(EShLanguage l, TInfoSink& sink) : infoSink(sink) , language(l), haveValidObjectCode(false) { }
+    virtual ~TCompiler() { }
+    EShLanguage getLanguage() { return language; }
+    virtual TInfoSink& getInfoSink() { return infoSink; }
+
+    virtual bool compile(TIntermNode* root) = 0;
+
+    virtual TCompiler* getAsCompiler() { return this; }
+    virtual bool linkable() { return haveValidObjectCode; }
+    
+    TInfoSink& infoSink;
+protected:
+    EShLanguage language;
+    bool haveValidObjectCode;
+};
+
+//
+// Link operations are base on a list of compile results...
+//
+typedef TVector<TCompiler*> TCompilerList;
+typedef TVector<TShHandleBase*> THandleList;
+
+//
+// The base class for the machine dependent linker to derive from
+// to manage the resulting executable.
+//
+
+class TLinker : public TShHandleBase {
+public:
+    TLinker(EShExecutable e, TInfoSink& iSink) : 
+        infoSink(iSink),
+        executable(e), 
+        haveReturnableObjectCode(false),
+        appAttributeBindings(0),
+        fixedAttributeBindings(0),
+		excludedAttributes(0),
+		excludedCount(0),
+        uniformBindings(0) { }
+    virtual TLinker* getAsLinker() { return this; }
+    virtual ~TLinker() { }
+    virtual bool link(TCompilerList&, TUniformMap*) = 0;
+    virtual bool link(THandleList&) { return false; }
+    virtual void setAppAttributeBindings(const ShBindingTable* t)   { appAttributeBindings = t; }
+    virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; }
+	virtual void getAttributeBindings(ShBindingTable const **t) const = 0;
+	virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; }
+    virtual ShBindingTable* getUniformBindings() const  { return uniformBindings; }
+    virtual const void* getObjectCode() const { return 0; } // a real compiler would be returning object code here
+    virtual TInfoSink& getInfoSink() { return infoSink; }
+    TInfoSink& infoSink;
+protected:
+    EShExecutable executable;
+    bool haveReturnableObjectCode;  // true when objectCode is acceptable to send to driver
+
+    const ShBindingTable* appAttributeBindings;
+    const ShBindingTable* fixedAttributeBindings;
+	const int* excludedAttributes;
+	int excludedCount;
+    ShBindingTable* uniformBindings;                // created by the linker    
+};
+
+//
+// This is the interface between the machine independent code
+// and the machine dependent code.
+//
+// The machine dependent code should derive from the classes
+// above. Then Construct*() and Delete*() will create and 
+// destroy the machine dependent objects, which contain the
+// above machine independent information.
+//
+TCompiler* ConstructCompiler(EShLanguage, int);
+
+TShHandleBase* ConstructLinker(EShExecutable, int);
+void DeleteLinker(TShHandleBase*);
+    
+TUniformMap* ConstructUniformMap();
+void DeleteCompiler(TCompiler*);
+
+void DeleteUniformMap(TUniformMap*);
+
+#endif // _SHHANDLE_INCLUDED_
diff --git a/Compiler/ShaderLang.cpp b/Compiler/ShaderLang.cpp
new file mode 100644
index 0000000..461604a
--- /dev/null
+++ b/Compiler/ShaderLang.cpp
@@ -0,0 +1,587 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Implement the top-level of interface to the compiler/linker,
+// as defined in ShaderLang.h
+//
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+
+#include "ShHandle.h"
+#include "InitializeDll.h"
+
+#include "ShaderLang.h"
+#include "Initialize.h"
+
+#include "OutputHLSL.h"
+
+//
+// A symbol table for each language.  Each has a different
+// set of built-ins, and we want to preserve that from
+// compile to compile.
+//
+TSymbolTable SymbolTables[EShLangCount];
+
+
+TPoolAllocator* PerProcessGPA = 0;
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler/linker.
+//
+
+//
+// Driver must call this first, once, before doing any other
+// compiler/linker operations.
+//
+int ShInitialize()
+{
+    TInfoSink infoSink;
+    bool ret = true;
+
+    if (!InitProcess())
+        return 0;
+
+    // This method should be called once per process. If its called by multiple threads, then 
+    // we need to have thread synchronization code around the initialization of per process
+    // global pool allocator
+    if (!PerProcessGPA) { 
+        TPoolAllocator *builtInPoolAllocator = new TPoolAllocator(true);
+        builtInPoolAllocator->push();
+        TPoolAllocator* gPoolAllocator = &GlobalPoolAllocator;
+        SetGlobalPoolAllocatorPtr(builtInPoolAllocator);
+
+        TSymbolTable symTables[EShLangCount];
+        GenerateBuiltInSymbolTable(0, infoSink, symTables);
+
+        PerProcessGPA = new TPoolAllocator(true);
+        PerProcessGPA->push();
+        SetGlobalPoolAllocatorPtr(PerProcessGPA);
+
+        SymbolTables[EShLangVertex].copyTable(symTables[EShLangVertex]);
+        SymbolTables[EShLangFragment].copyTable(symTables[EShLangFragment]);
+
+        SetGlobalPoolAllocatorPtr(gPoolAllocator);
+
+        symTables[EShLangVertex].pop();
+        symTables[EShLangFragment].pop();
+
+        builtInPoolAllocator->popAll();
+        delete builtInPoolAllocator;        
+
+    }
+
+    return ret ? 1 : 0;
+}
+
+//
+// Driver calls these to create and destroy compiler/linker
+// objects.
+//
+
+ShHandle ShConstructCompiler(const EShLanguage language, int debugOptions)
+{
+    if (!InitThread())
+        return 0;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(language, debugOptions));
+    
+    return reinterpret_cast<void*>(base);
+}
+
+ShHandle ShConstructLinker(const EShExecutable executable, int debugOptions)
+{
+    if (!InitThread())
+        return 0;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(ConstructLinker(executable, debugOptions));
+
+    return reinterpret_cast<void*>(base);
+}
+
+ShHandle ShConstructUniformMap()
+{
+    if (!InitThread())
+        return 0;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(ConstructUniformMap());
+
+    return reinterpret_cast<void*>(base);
+}
+
+void ShDestruct(ShHandle handle)
+{
+    if (handle == 0)
+        return;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+
+    if (base->getAsCompiler())
+        DeleteCompiler(base->getAsCompiler());
+    else if (base->getAsLinker())
+        DeleteLinker(base->getAsLinker());
+    else if (base->getAsUniformMap())
+        DeleteUniformMap(base->getAsUniformMap());
+}
+
+//
+// Cleanup symbol tables
+//
+int __fastcall ShFinalize()
+{  
+  if (PerProcessGPA) {
+    PerProcessGPA->popAll();
+    delete PerProcessGPA;
+  }
+  return 1;
+}
+
+bool GenerateBuiltInSymbolTable(const TBuiltInResource* resources, TInfoSink& infoSink, TSymbolTable* symbolTables, EShLanguage language)
+{
+    TBuiltIns builtIns;
+    
+	if (resources) {
+		builtIns.initialize(*resources);
+		InitializeSymbolTable(builtIns.getBuiltInStrings(), language, infoSink, resources, symbolTables);
+	} else {
+		builtIns.initialize();
+		InitializeSymbolTable(builtIns.getBuiltInStrings(), EShLangVertex, infoSink, resources, symbolTables);
+		InitializeSymbolTable(builtIns.getBuiltInStrings(), EShLangFragment, infoSink, resources, symbolTables);
+	}
+
+    return true;
+}
+
+bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language, TInfoSink& infoSink, const TBuiltInResource* resources, TSymbolTable* symbolTables)
+{
+    TIntermediate intermediate(infoSink);	
+    TSymbolTable* symbolTable;
+	
+	if (resources)
+		symbolTable = symbolTables;
+	else
+		symbolTable = &symbolTables[language];
+
+    TParseContext parseContext(*symbolTable, intermediate, language, infoSink);
+
+    GlobalParseContext = &parseContext;
+    
+    setInitialState();
+
+    assert(symbolTable->isEmpty() || symbolTable->atSharedBuiltInLevel());
+       
+    //
+    // Parse the built-ins.  This should only happen once per
+    // language symbol table.
+    //
+    // Push the symbol table to give it an initial scope.  This
+    // push should not have a corresponding pop, so that built-ins
+    // are preserved, and the test for an empty table fails.
+    //
+
+    symbolTable->push();
+    
+    //Initialize the Preprocessor
+    int ret = InitPreprocessor();
+    if (ret) {
+        infoSink.info.message(EPrefixInternalError,  "Unable to intialize the Preprocessor");
+        return false;
+    }
+    
+    for (TBuiltInStrings::iterator i  = BuiltInStrings[parseContext.language].begin();
+                                    i != BuiltInStrings[parseContext.language].end();
+                                    ++i) {
+        const char* builtInShaders[1];
+        int builtInLengths[1];
+
+        builtInShaders[0] = (*i).c_str();
+        builtInLengths[0] = (int) (*i).size();
+
+        if (PaParseStrings(const_cast<char**>(builtInShaders), builtInLengths, 1, parseContext) != 0) {
+            infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
+            return false;
+        }
+    }
+
+	if (resources) {
+		IdentifyBuiltIns(parseContext.language, *symbolTable, *resources);
+	} else {									   
+		IdentifyBuiltIns(parseContext.language, *symbolTable);
+	}
+
+    FinalizePreprocessor();
+
+    return true;
+}
+
+//
+// Do an actual compile on the given strings.  The result is left 
+// in the given compile object.
+//
+// Return:  The return value of ShCompile is really boolean, indicating
+// success or failure.
+//
+int ShCompile(
+    const ShHandle handle,
+    const char* const shaderStrings[],
+    const int numStrings,
+    const EShOptimizationLevel optLevel,
+    const TBuiltInResource* resources,
+    int debugOptions
+    )
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (compiler == 0)
+        return 0;
+    
+    GlobalPoolAllocator.push();
+    compiler->infoSink.info.erase();
+    compiler->infoSink.debug.erase();
+    compiler->infoSink.obj.erase();
+
+    if (numStrings == 0)
+        return 1;
+
+    TIntermediate intermediate(compiler->infoSink);
+    TSymbolTable symbolTable(SymbolTables[compiler->getLanguage()]);
+    
+    GenerateBuiltInSymbolTable(resources, compiler->infoSink, &symbolTable, compiler->getLanguage());
+
+    TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->infoSink);
+    parseContext.initializeExtensionBehavior();
+
+    GlobalParseContext = &parseContext;
+    
+    setInitialState();
+
+    InitPreprocessor();    
+    //
+    // Parse the application's shaders.  All the following symbol table
+    // work will be throw-away, so push a new allocation scope that can
+    // be thrown away, then push a scope for the current shader's globals.
+    //
+    bool success = true;
+    
+    symbolTable.push();
+    if (!symbolTable.atGlobalLevel())
+        parseContext.infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
+
+    int ret = PaParseStrings(const_cast<char**>(shaderStrings), 0, numStrings, parseContext);
+    if (ret)
+        success = false;
+
+    if (success && parseContext.treeRoot) {
+        if (optLevel == EShOptNoGeneration)
+            parseContext.infoSink.info.message(EPrefixNone, "No errors.  No code generation or linking was requested.");
+        else {
+            success = intermediate.postProcess(parseContext.treeRoot, parseContext.language);
+
+            if (success) {
+
+                if (debugOptions & EDebugOpIntermediate)
+                    intermediate.outputTree(parseContext.treeRoot);
+
+				if(debugOptions & EDebugOpObjectCode)
+				{
+					sh::OutputHLSL outputHLSL(parseContext);
+
+					outputHLSL.header();
+					parseContext.treeRoot->traverse(&outputHLSL);
+				}
+
+                //
+                // Call the machine dependent compiler
+                //
+                if (! compiler->compile(parseContext.treeRoot))
+                    success = false;
+            }
+        }
+    } else if (!success) {
+        parseContext.infoSink.info.prefix(EPrefixError);
+        parseContext.infoSink.info << parseContext.numErrors << " compilation errors.  No code generated.\n\n";
+        success = false;
+        if (debugOptions & EDebugOpIntermediate)
+            intermediate.outputTree(parseContext.treeRoot);
+    }
+
+    intermediate.remove(parseContext.treeRoot);
+
+    //
+    // Ensure symbol table is returned to the built-in level,
+    // throwing away all but the built-ins.
+    //
+    while (! symbolTable.atSharedBuiltInLevel())
+        symbolTable.pop();
+
+    FinalizePreprocessor();
+    //
+    // Throw away all the temporary memory used by the compilation process.
+    //
+    GlobalPoolAllocator.pop();
+
+    return success ? 1 : 0;
+}
+
+//
+// Do an actual link on the given compile objects.
+//
+// Return:  The return value of is really boolean, indicating
+// success or failure.
+//
+int ShLink(
+    const ShHandle linkHandle,
+    const ShHandle compHandles[],
+    const int numHandles,
+    ShHandle uniformMapHandle,
+    short int** uniformsAccessed,
+    int* numUniformsAccessed)
+
+{
+    if (!InitThread())
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(linkHandle);
+    TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+    if (linker == 0)
+        return 0;
+
+    int returnValue;
+    GlobalPoolAllocator.push();
+    returnValue = ShLinkExt(linkHandle, compHandles, numHandles);
+    GlobalPoolAllocator.pop();
+
+    if (returnValue)
+        return 1;
+
+    return 0;
+}
+//
+// This link method will be eventually used once the ICD supports the new linker interface
+//
+int ShLinkExt(
+    const ShHandle linkHandle,
+    const ShHandle compHandles[],
+    const int numHandles)
+{
+    if (linkHandle == 0 || numHandles == 0)
+        return 0;
+
+    THandleList cObjects;
+
+    {// support MSVC++6.0
+        for (int i = 0; i < numHandles; ++i) {
+            if (compHandles[i] == 0)
+                return 0;
+            TShHandleBase* base = reinterpret_cast<TShHandleBase*>(compHandles[i]);
+            if (base->getAsLinker()) {
+                cObjects.push_back(base->getAsLinker());
+            }
+            if (base->getAsCompiler())
+                cObjects.push_back(base->getAsCompiler());
+    
+    
+            if (cObjects[i] == 0)
+                return 0;
+        }
+    }
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(linkHandle);
+    TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+    if (linker == 0)
+        return 0;
+
+    linker->infoSink.info.erase();
+    linker->infoSink.obj.erase();
+
+    {// support MSVC++6.0
+        for (int i = 0; i < numHandles; ++i) {
+            if (cObjects[i]->getAsCompiler()) {
+                if (! cObjects[i]->getAsCompiler()->linkable()) {
+                    linker->infoSink.info.message(EPrefixError, "Not all shaders have valid object code.");                
+                    return 0;
+                }
+            }
+        }
+    }
+
+    bool ret = linker->link(cObjects);
+
+    return ret ? 1 : 0;
+}
+
+//
+// ShSetEncrpytionMethod is a place-holder for specifying
+// how source code is encrypted.
+//
+void ShSetEncryptionMethod(ShHandle handle)
+{
+    if (handle == 0)
+        return;
+}
+
+//
+// Return any compiler/linker/uniformmap log of messages for the application.
+//
+const char* ShGetInfoLog(const ShHandle handle)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+    TInfoSink* infoSink;
+
+    if (base->getAsCompiler())
+        infoSink = &(base->getAsCompiler()->getInfoSink());
+    else if (base->getAsLinker())
+        infoSink = &(base->getAsLinker()->getInfoSink());
+
+    infoSink->info << infoSink->debug.c_str();
+    return infoSink->info.c_str();
+}
+
+//
+// Return any unlinked object code.
+//
+const char* ShGetObjectCode(const ShHandle handle)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+    TInfoSink* infoSink;
+
+    if (base->getAsCompiler())
+        infoSink = &(base->getAsCompiler()->getInfoSink());
+
+    return infoSink->obj.c_str();
+}
+
+//
+// Return the resulting binary code from the link process.  Structure
+// is machine dependent.
+//
+const void* ShGetExecutable(const ShHandle handle)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    
+    TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+    if (linker == 0)
+        return 0;
+
+    return linker->getObjectCode();
+}
+
+//
+// Let the linker know where the application said it's attributes are bound.
+// The linker does not use these values, they are remapped by the ICD or
+// hardware.  It just needs them to know what's aliased.
+//
+// Return:  The return value of is really boolean, indicating
+// success or failure.
+//
+int ShSetVirtualAttributeBindings(const ShHandle handle, const ShBindingTable* table)
+{    
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+    if (linker == 0)
+        return 0;
+   
+    linker->setAppAttributeBindings(table);
+
+    return 1;
+}
+
+//
+// Let the linker know where the predefined attributes have to live.
+//
+int ShSetFixedAttributeBindings(const ShHandle handle, const ShBindingTable* table)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+
+    if (linker == 0)
+        return 0;
+
+    linker->setFixedAttributeBindings(table);
+    return 1;
+}
+
+//
+// Some attribute locations are off-limits to the linker...
+//
+int ShExcludeAttributes(const ShHandle handle, int *attributes, int count)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TLinker* linker = static_cast<TLinker*>(base->getAsLinker());
+    if (linker == 0)
+        return 0;
+
+    linker->setExcludedAttributes(attributes, count);
+
+    return 1;
+}
+
+//
+// Return the index for OpenGL to use for knowing where a uniform lives.
+//
+// Return:  The return value of is really boolean, indicating
+// success or failure.
+//
+int ShGetUniformLocation(const ShHandle handle, const char* name)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return -1;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TUniformMap* uniformMap= base->getAsUniformMap();
+    if (uniformMap == 0)
+        return -1;
+
+    return uniformMap->getLocation(name);
+}
+
diff --git a/Compiler/ShaderLang.h b/Compiler/ShaderLang.h
new file mode 100644
index 0000000..4e695eb
--- /dev/null
+++ b/Compiler/ShaderLang.h
@@ -0,0 +1,179 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef _COMPILER_INTERFACE_INCLUDED_
+#define _COMPILER_INTERFACE_INCLUDED_
+
+#include "ResourceLimits.h"
+
+#ifdef _WIN32
+#define C_DECL __cdecl
+#else
+#define __fastcall
+#define C_DECL
+#endif
+
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler/linker.
+//
+
+#ifdef __cplusplus
+	extern "C" {
+#endif
+//
+// Driver must call this first, once, before doing any other
+// compiler/linker operations.
+//
+int ShInitialize();
+//
+// Driver should call this at shutdown.
+//
+int __fastcall ShFinalize();
+//
+// Types of languages the compiler can consume.
+//
+typedef enum {
+	EShLangVertex,
+	EShLangFragment,
+	EShLangPack,
+	EShLangUnpack,
+	EShLangCount,
+} EShLanguage;
+
+//
+// Types of output the linker will create.
+//
+typedef enum {
+	EShExVertexFragment,
+	EShExPackFragment,
+	EShExUnpackFragment,
+	EShExFragment
+} EShExecutable;
+
+//
+// Optimization level for the compiler.
+//
+typedef enum {
+	EShOptNoGeneration,
+	EShOptNone,
+	EShOptSimple,       // Optimizations that can be done quickly
+	EShOptFull,         // Optimizations that will take more time
+} EShOptimizationLevel;
+
+//
+// Build a table for bindings.  This can be used for locating
+// attributes, uniforms, globals, etc., as needed.
+//
+typedef struct {
+	const char* name;
+	int binding;
+} ShBinding;
+
+typedef struct {
+	int numBindings;
+	ShBinding* bindings;  // array of bindings
+} ShBindingTable;
+
+//
+// ShHandle held by but opaque to the driver.  It is allocated,
+// managed, and de-allocated by the compiler/linker. It's contents 
+// are defined by and used by the compiler and linker.  For example,
+// symbol table information and object code passed from the compiler 
+// to the linker can be stored where ShHandle points.
+//
+// If handle creation fails, 0 will be returned.
+//
+typedef void* ShHandle;
+
+//
+// Driver calls these to create and destroy compiler/linker
+// objects.
+//
+ShHandle ShConstructCompiler(const EShLanguage, int debugOptions);  // one per shader
+ShHandle ShConstructLinker(const EShExecutable, int debugOptions);  // one per shader pair
+ShHandle ShConstructUniformMap();                 // one per uniform namespace (currently entire program object)
+void ShDestruct(ShHandle);
+
+//
+// The return value of ShCompile is boolean, indicating
+// success or failure.
+//
+// The info-log should be written by ShCompile into 
+// ShHandle, so it can answer future queries.
+//
+int ShCompile(
+	const ShHandle,
+	const char* const shaderStrings[],
+	const int numStrings,
+	const EShOptimizationLevel,
+	const TBuiltInResource *resources,
+	int debugOptions
+	);
+
+
+//
+// Similar to ShCompile, but accepts an opaque handle to an
+// intermediate language structure.
+//
+int ShCompileIntermediate(
+	ShHandle compiler,
+	ShHandle intermediate,
+	const EShOptimizationLevel,
+	int debuggable           // boolean
+	);
+
+int ShLink(
+	const ShHandle,               // linker object
+	const ShHandle h[],           // compiler objects to link together
+	const int numHandles,
+	ShHandle uniformMap,          // updated with new uniforms
+	short int** uniformsAccessed,  // returned with indexes of uniforms accessed
+	int* numUniformsAccessed); 	
+
+int ShLinkExt(
+	const ShHandle,               // linker object
+	const ShHandle h[],           // compiler objects to link together
+	const int numHandles);
+
+//
+// ShSetEncrpytionMethod is a place-holder for specifying
+// how source code is encrypted.
+//
+void ShSetEncryptionMethod(ShHandle);
+
+//
+// All the following return 0 if the information is not
+// available in the object passed down, or the object is bad.
+//
+const char* ShGetInfoLog(const ShHandle);
+const char* ShGetObjectCode(const ShHandle);
+const void* ShGetExecutable(const ShHandle);
+int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*);   // to detect user aliasing
+int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*);     // to force any physical mappings
+int ShGetPhysicalAttributeBindings(const ShHandle, const ShBindingTable**); // for all attributes
+//
+// Tell the linker to never assign a vertex attribute to this list of physical attributes
+//
+int ShExcludeAttributes(const ShHandle, int *attributes, int count);
+
+//
+// Returns the location ID of the named uniform.
+// Returns -1 if error.
+//
+int ShGetUniformLocation(const ShHandle uniformMap, const char* name);
+
+enum TDebugOptions {
+	EDebugOpNone               = 0x000,
+	EDebugOpIntermediate       = 0x001,
+	EDebugOpAssembly           = 0x002,
+	EDebugOpObjectCode         = 0x004,
+	EDebugOpLinkMaps           = 0x008
+};
+#ifdef __cplusplus
+	}
+#endif
+
+#endif // _COMPILER_INTERFACE_INCLUDED_
diff --git a/Compiler/SymbolTable.cpp b/Compiler/SymbolTable.cpp
new file mode 100644
index 0000000..fa54a9a
--- /dev/null
+++ b/Compiler/SymbolTable.cpp
@@ -0,0 +1,211 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Symbol table for parsing.  Most functionaliy and main ideas
+// are documented in the header file.
+//
+
+#include "SymbolTable.h"
+
+//
+// TType helper function needs a place to live.
+//
+
+//
+// Recursively generate mangled names.
+//
+void TType::buildMangledName(TString& mangledName)
+{
+	if (isMatrix())
+		mangledName += 'm';
+	else if (isVector())
+		mangledName += 'v';
+
+	switch (type) {
+	case EbtFloat:              mangledName += 'f';      break;
+	case EbtInt:                mangledName += 'i';      break;
+	case EbtBool:               mangledName += 'b';      break;
+	case EbtSampler2D:          mangledName += "s2";     break;
+	case EbtSamplerCube:        mangledName += "sC";     break;
+	case EbtStruct:
+		mangledName += "struct-";
+		if (typeName)
+			mangledName += *typeName;
+		{// support MSVC++6.0
+			for (unsigned int i = 0; i < structure->size(); ++i) {
+				mangledName += '-';
+				(*structure)[i].type->buildMangledName(mangledName);
+			}
+		}
+	default:
+		break;
+	}
+
+	mangledName += static_cast<char>('0' + getNominalSize());
+	if (isArray()) {
+		char buf[10];
+		sprintf(buf, "%d", arraySize);
+		mangledName += '[';
+		mangledName += buf;
+		mangledName += ']';
+	}
+}
+
+int TType::getStructSize() const
+{
+	if (!getStruct()) {
+		assert(false && "Not a struct");
+		return 0;
+	}
+
+	if (structureSize == 0)
+		for (TTypeList::iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
+			structureSize += ((*tl).type)->getObjectSize();
+
+	return structureSize;
+}
+
+//
+// Dump functions.
+//
+
+void TVariable::dump(TInfoSink& infoSink) const
+{
+	infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getBasicString();
+	if (type.isArray()) {
+		infoSink.debug << "[0]";
+	}
+	infoSink.debug << "\n";
+}
+
+void TFunction::dump(TInfoSink &infoSink) const
+{
+	infoSink.debug << getName().c_str() << ": " <<  returnType.getBasicString() << " " << getMangledName().c_str() << "\n";
+}
+
+void TSymbolTableLevel::dump(TInfoSink &infoSink) const
+{
+	tLevel::const_iterator it;
+	for (it = level.begin(); it != level.end(); ++it)
+		(*it).second->dump(infoSink);
+}
+
+void TSymbolTable::dump(TInfoSink &infoSink) const
+{
+	for (int level = currentLevel(); level >= 0; --level) {
+		infoSink.debug << "LEVEL " << level << "\n";
+		table[level]->dump(infoSink);
+	}
+}
+
+//
+// Functions have buried pointers to delete.
+//
+TFunction::~TFunction()
+{
+	for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
+		delete (*i).type;
+}
+
+//
+// Symbol table levels are a map of pointers to symbols that have to be deleted.
+//
+TSymbolTableLevel::~TSymbolTableLevel()
+{
+	for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
+		delete (*it).second;
+}
+
+//
+// Change all function entries in the table with the non-mangled name
+// to be related to the provided built-in operation.  This is a low
+// performance operation, and only intended for symbol tables that
+// live across a large number of compiles.
+//
+void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
+{
+	tLevel::iterator it;
+	for (it = level.begin(); it != level.end(); ++it) {
+		if ((*it).second->isFunction()) {
+			TFunction* function = static_cast<TFunction*>((*it).second);
+			if (function->getName() == name)
+				function->relateToOperator(op);
+		}
+	}
+}
+
+
+TSymbol::TSymbol(const TSymbol& copyOf)
+{
+	name = NewPoolTString(copyOf.name->c_str());
+	uniqueId = copyOf.uniqueId;
+}
+
+TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
+{
+	type.copyType(copyOf.type, remapper);
+	userType = copyOf.userType;
+	// for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL
+	assert(copyOf.arrayInformationType == 0);
+	arrayInformationType = 0;
+
+	if (copyOf.unionArray) {
+		assert(!copyOf.type.getStruct());
+		assert(copyOf.type.getObjectSize() == 1);
+		unionArray = new constUnion[1];
+		unionArray[0] = copyOf.unionArray[0];
+	} else
+		unionArray = 0;
+}
+
+TVariable* TVariable::clone(TStructureMap& remapper)
+{
+	TVariable *variable = new TVariable(*this, remapper);
+
+	return variable;
+}
+
+TFunction::TFunction(const TFunction& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
+{
+	for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
+		TParameter param;
+		parameters.push_back(param);
+		parameters.back().copyParam(copyOf.parameters[i], remapper);
+	}
+
+	returnType.copyType(copyOf.returnType, remapper);
+	mangledName = copyOf.mangledName;
+	op = copyOf.op;
+	defined = copyOf.defined;
+}
+
+TFunction* TFunction::clone(TStructureMap& remapper)
+{
+	TFunction *function = new TFunction(*this, remapper);
+
+	return function;
+}
+
+TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper)
+{
+	TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
+	tLevel::iterator iter;
+	for (iter = level.begin(); iter != level.end(); ++iter) {
+		symTableLevel->insert(*iter->second->clone(remapper));
+	}
+
+	return symTableLevel;
+}
+
+void TSymbolTable::copyTable(const TSymbolTable& copyOf)
+{
+	TStructureMap remapper;
+	uniqueId = copyOf.uniqueId;
+	for (unsigned int i = 0; i < copyOf.table.size(); ++i) {
+		table.push_back(copyOf.table[i]->clone(remapper));
+	}
+}
diff --git a/Compiler/SymbolTable.h b/Compiler/SymbolTable.h
new file mode 100644
index 0000000..3af31ad
--- /dev/null
+++ b/Compiler/SymbolTable.h
@@ -0,0 +1,300 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _SYMBOL_TABLE_INCLUDED_
+#define _SYMBOL_TABLE_INCLUDED_
+
+//
+// Symbol table for parsing.  Has these design characteristics:
+//
+// * Same symbol table can be used to compile many shaders, to preserve
+//   effort of creating and loading with the large numbers of built-in
+//   symbols.
+//
+// * Name mangling will be used to give each function a unique name
+//   so that symbol table lookups are never ambiguous.  This allows
+//   a simpler symbol table structure.
+//
+// * Pushing and popping of scope, so symbol table will really be a stack 
+//   of symbol tables.  Searched from the top, with new inserts going into
+//   the top.
+//
+// * Constants:  Compile time constant symbols will keep their values
+//   in the symbol table.  The parser can substitute constants at parse
+//   time, including doing constant folding and constant propagation.
+//
+// * No temporaries:  Temporaries made from operations (+, --, .xy, etc.)
+//   are tracked in the intermediate representation, not the symbol table.
+//
+
+#include "Common.h"
+#include "intermediate.h"
+#include "InfoSink.h"
+ 
+//
+// Symbol base class.  (Can build functions or variables out of these...)
+//
+class TSymbol {    
+public:
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+    TSymbol(const TString *n) :  name(n) { }
+    virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
+    const TString& getName() const { return *name; }
+    virtual const TString& getMangledName() const { return getName(); }
+    virtual bool isFunction() const { return false; }
+    virtual bool isVariable() const { return false; }
+    void setUniqueId(int id) { uniqueId = id; }
+    int getUniqueId() const { return uniqueId; }
+    virtual void dump(TInfoSink &infoSink) const = 0;	
+	TSymbol(const TSymbol&);
+	virtual TSymbol* clone(TStructureMap& remapper) = 0;
+
+protected:
+    const TString *name;
+    unsigned int uniqueId;      // For real comparing during code generation
+};
+
+//
+// Variable class, meaning a symbol that's not a function.
+// 
+// There could be a separate class heirarchy for Constant variables;
+// Only one of int, bool, or float, (or none) is correct for
+// any particular use, but it's easy to do this way, and doesn't
+// seem worth having separate classes, and "getConst" can't simply return
+// different values for different types polymorphically, so this is 
+// just simple and pragmatic.
+//
+class TVariable : public TSymbol {
+public:
+    TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { }
+    virtual ~TVariable() { }
+    virtual bool isVariable() const { return true; }    
+    TType& getType() { return type; }    
+    const TType& getType() const { return type; }
+    bool isUserType() const { return userType; }
+    void changeQualifier(TQualifier qualifier) { type.changeQualifier(qualifier); }
+    void updateArrayInformationType(TType *t) { arrayInformationType = t; }
+    TType* getArrayInformationType() { return arrayInformationType; }
+
+    virtual void dump(TInfoSink &infoSink) const;
+
+    constUnion* getConstPointer() { 
+        if (!unionArray)
+            unionArray = new constUnion[type.getObjectSize()];
+
+        return unionArray;
+    }
+
+    constUnion* getConstPointer() const { return unionArray; }
+
+    void shareConstPointer( constUnion *constArray)
+    {
+        delete unionArray;
+        unionArray = constArray;  
+    }
+	TVariable(const TVariable&, TStructureMap& remapper); // copy constructor
+	virtual TVariable* clone(TStructureMap& remapper);
+      
+protected:
+    TType type;
+    bool userType;
+    // we are assuming that Pool Allocator will free the memory allocated to unionArray
+    // when this object is destroyed
+    constUnion *unionArray;
+    TType *arrayInformationType;  // this is used for updating maxArraySize in all the references to a given symbol
+};
+
+//
+// The function sub-class of symbols and the parser will need to
+// share this definition of a function parameter.
+//
+struct TParameter {
+    TString *name;
+    TType* type;
+	void copyParam(const TParameter& param, TStructureMap& remapper) {
+		name = NewPoolTString(param.name->c_str());
+		type = param.type->clone(remapper);
+	}
+};
+
+//
+// The function sub-class of a symbol.  
+//
+class TFunction : public TSymbol {
+public:
+    TFunction(TOperator o) :
+        TSymbol(0),
+        returnType(TType(EbtVoid)),
+        op(o),
+        defined(false) { }
+    TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : 
+        TSymbol(name), 
+        returnType(retType),
+        mangledName(*name + '('),
+        op(tOp),
+        defined(false) { }
+	virtual ~TFunction();
+    virtual bool isFunction() const { return true; }    
+    
+    void addParameter(TParameter& p) 
+    { 
+        parameters.push_back(p);
+        mangledName = mangledName + p.type->getMangledName();
+    }
+    
+    const TString& getMangledName() const { return mangledName; }
+    const TType& getReturnType() const { return returnType; }
+    void relateToOperator(TOperator o) { op = o; }
+    TOperator getBuiltInOp() const { return op; }
+    void setDefined() { defined = true; }
+    bool isDefined() { return defined; }
+
+    int getParamCount() const { return static_cast<int>(parameters.size()); }    
+          TParameter& operator [](int i)       { return parameters[i]; }
+    const TParameter& operator [](int i) const { return parameters[i]; }
+    
+    virtual void dump(TInfoSink &infoSink) const;
+	TFunction(const TFunction&, TStructureMap& remapper);
+	virtual TFunction* clone(TStructureMap& remapper);
+    
+protected:
+    typedef TVector<TParameter> TParamList;
+	TParamList parameters;
+    TType returnType;
+    TString mangledName;
+    TOperator op;
+    bool defined;
+};
+
+
+class TSymbolTableLevel {
+public:
+	typedef std::map<TString, TSymbol*, std::less<TString>, pool_allocator<std::pair<const TString, TSymbol*> > > tLevel;
+	typedef tLevel::const_iterator const_iterator;
+    typedef const tLevel::value_type tLevelPair;
+    typedef std::pair<tLevel::iterator, bool> tInsertResult;
+
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+    TSymbolTableLevel() { }
+	~TSymbolTableLevel();
+    
+    bool insert(TSymbol& symbol) 
+    {
+        //
+        // returning true means symbol was added to the table
+        //
+        tInsertResult result;
+        result = level.insert(tLevelPair(symbol.getMangledName(), &symbol));
+        
+        return result.second;
+    }
+
+    TSymbol* find(const TString& name) const
+    {
+        tLevel::const_iterator it = level.find(name);
+        if (it == level.end())
+            return 0;
+        else
+            return (*it).second;
+    }
+
+	const_iterator begin() const
+	{
+		return level.begin();
+	}
+
+	const_iterator end() const
+	{
+		return level.end();
+	}
+
+    void relateToOperator(const char* name, TOperator op);
+    void dump(TInfoSink &infoSink) const;
+	TSymbolTableLevel* clone(TStructureMap& remapper);
+    
+protected:
+    tLevel level;
+};
+
+class TSymbolTable {
+public:
+    TSymbolTable() : uniqueId(0)
+    {
+        //
+        // The symbol table cannot be used until push() is called, but
+        // the lack of an initial call to push() can be used to detect
+        // that the symbol table has not been preloaded with built-ins.
+        //
+    }
+
+    TSymbolTable(TSymbolTable& symTable)
+    {
+        table.push_back(symTable.table[0]);
+        uniqueId = symTable.uniqueId;
+    }
+
+    ~TSymbolTable()
+    {
+        // level 0 is always built In symbols, so we never pop that out
+        while (table.size() > 1)
+            pop();
+    }
+
+    //
+    // When the symbol table is initialized with the built-ins, there should
+    // 'push' calls, so that built-ins are at level 0 and the shader
+    // globals are at level 1.
+    //
+    bool isEmpty() { return table.size() == 0; }
+    bool atBuiltInLevel() { return atSharedBuiltInLevel() || atDynamicBuiltInLevel(); }
+    bool atSharedBuiltInLevel() { return table.size() == 1; }	
+    bool atGlobalLevel() { return table.size() <= 3; }
+    void push() { 
+        table.push_back(new TSymbolTableLevel);
+    }
+
+    void pop() { 
+        delete table[currentLevel()]; 
+        table.pop_back(); 
+    }
+
+    bool insert(TSymbol& symbol)
+    {
+        symbol.setUniqueId(++uniqueId);
+        return table[currentLevel()]->insert(symbol);
+    }
+    
+    TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0) 
+    {
+        int level = currentLevel();
+        TSymbol* symbol;
+        do {
+            symbol = table[level]->find(name);
+            --level;
+        } while (symbol == 0 && level >= 0);
+        level++;
+        if (builtIn)
+            *builtIn = level == 0;
+        if (sameScope)
+            *sameScope = level == currentLevel();
+        return symbol;
+    }
+
+    TSymbolTableLevel* getGlobalLevel() { assert(table.size() >= 3); return table[2]; }
+    void relateToOperator(const char* name, TOperator op) { table[0]->relateToOperator(name, op); }
+    int getMaxSymbolId() { return uniqueId; }
+    void dump(TInfoSink &infoSink) const;
+	void copyTable(const TSymbolTable& copyOf);
+
+protected:    
+    int currentLevel() const { return static_cast<int>(table.size()) - 1; }
+    bool atDynamicBuiltInLevel() { return table.size() == 2; }
+
+    std::vector<TSymbolTableLevel*> table;
+    int uniqueId;     // for unique identification in code generation
+};
+
+#endif // _SYMBOL_TABLE_INCLUDED_
diff --git a/Compiler/Tools/bison.exe b/Compiler/Tools/bison.exe
new file mode 100644
index 0000000..4881bf6
--- /dev/null
+++ b/Compiler/Tools/bison.exe
Binary files differ
diff --git a/Compiler/Tools/bison.hairy b/Compiler/Tools/bison.hairy
new file mode 100644
index 0000000..999b555
--- /dev/null
+++ b/Compiler/Tools/bison.hairy
@@ -0,0 +1,334 @@
+
+extern int timeclock;
+
+
+int yyerror;		/*  Yyerror and yycost are set by guards.	*/
+int yycost;		/*  If yyerror is set to a nonzero value by a	*/
+			/*  guard, the reduction with which the guard	*/
+			/*  is associated is not performed, and the	*/
+			/*  error recovery mechanism is invoked.	*/
+			/*  Yycost indicates the cost of performing	*/
+			/*  the reduction given the attributes of the	*/
+			/*  symbols.					*/
+
+
+/*  YYMAXDEPTH indicates the size of the parser's state and value	*/
+/*  stacks.								*/
+
+#ifndef	YYMAXDEPTH
+#define	YYMAXDEPTH	500
+#endif
+
+/*  YYMAXRULES must be at least as large as the number of rules that	*/
+/*  could be placed in the rule queue.  That number could be determined	*/
+/*  from the grammar and the size of the stack, but, as yet, it is not.	*/
+
+#ifndef	YYMAXRULES
+#define	YYMAXRULES	100
+#endif
+
+#ifndef	YYMAXBACKUP
+#define YYMAXBACKUP	100
+#endif
+
+
+short	yyss[YYMAXDEPTH];	/*  the state stack			*/
+YYSTYPE	yyvs[YYMAXDEPTH];	/*  the semantic value stack		*/
+YYLTYPE yyls[YYMAXDEPTH];	/*  the location stack			*/
+short	yyrq[YYMAXRULES];	/*  the rule queue			*/
+int	yychar;			/*  the lookahead symbol		*/
+
+YYSTYPE	yylval;			/*  the semantic value of the		*/
+				/*  lookahead symbol			*/
+
+YYSTYPE yytval;			/*  the semantic value for the state	*/
+				/*  at the top of the state stack.	*/
+
+YYSTYPE yyval;			/*  the variable used to return		*/
+				/*  semantic values from the action	*/
+				/*  routines				*/
+
+YYLTYPE yylloc;		/*  location data for the lookahead	*/
+				/*  symbol				*/
+
+YYLTYPE yytloc;		/*  location data for the state at the	*/
+				/*  top of the state stack		*/
+
+
+int	yynunlexed;
+short	yyunchar[YYMAXBACKUP];
+YYSTYPE	yyunval[YYMAXBACKUP];
+YYLTYPE yyunloc[YYMAXBACKUP];
+
+short *yygssp;			/*  a pointer to the top of the state	*/
+				/*  stack; only set during error	*/
+				/*  recovery.				*/
+
+YYSTYPE *yygvsp;		/*  a pointer to the top of the value	*/
+				/*  stack; only set during error	*/
+				/*  recovery.				*/
+
+YYLTYPE *yyglsp;		/*  a pointer to the top of the		*/
+				/*  location stack; only set during	*/
+				/*  error recovery.			*/
+
+
+/*  Yyget is an interface between the parser and the lexical analyzer.	*/
+/*  It is costly to provide such an interface, but it avoids requiring	*/
+/*  the lexical analyzer to be able to back up the scan.		*/
+
+yyget()
+{
+  if (yynunlexed > 0)
+    {
+      yynunlexed--;
+      yychar = yyunchar[yynunlexed];
+      yylval = yyunval[yynunlexed];
+      yylloc = yyunloc[yynunlexed];
+    }
+  else if (yychar <= 0)
+    yychar = 0;
+  else
+    {
+      yychar = yylex();
+      if (yychar < 0)
+	yychar = 0;
+      else yychar = YYTRANSLATE(yychar);
+    }
+}
+
+
+
+yyunlex(chr, val, loc)
+int chr;
+YYSTYPE val;
+YYLTYPE loc;
+{
+  yyunchar[yynunlexed] = chr;
+  yyunval[yynunlexed] = val;
+  yyunloc[yynunlexed] = loc;
+  yynunlexed++;
+}
+
+
+
+yyrestore(first, last)
+register short *first;
+register short *last;
+{
+  register short *ssp;
+  register short *rp;
+  register int symbol;
+  register int state;
+  register int tvalsaved;
+
+  ssp = yygssp;
+  yyunlex(yychar, yylval, yylloc);
+
+  tvalsaved = 0;
+  while (first != last)
+    {
+      symbol = yystos[*ssp];
+      if (symbol < YYNTBASE)
+	{
+	  yyunlex(symbol, yytval, yytloc);
+	  tvalsaved = 1;
+	  ssp--;
+	}
+
+      ssp--;
+
+      if (first == yyrq)
+	first = yyrq + YYMAXRULES;
+
+      first--;
+
+      for (rp = yyrhs + yyprhs[*first]; symbol = *rp; rp++)
+	{
+	  if (symbol < YYNTBASE)
+	    state = yytable[yypact[*ssp] + symbol];
+	  else
+	    {
+	      state = yypgoto[symbol - YYNTBASE] + *ssp;
+
+	      if (state >= 0 && state <= YYLAST && yycheck[state] == *ssp)
+		state = yytable[state];
+	      else
+		state = yydefgoto[symbol - YYNTBASE];
+	    }
+
+	  *++ssp = state;
+	}
+    }
+
+  if ( ! tvalsaved && ssp > yyss)
+    {
+      yyunlex(yystos[*ssp], yytval, yytloc);
+      ssp--;
+    }
+
+  yygssp = ssp;
+}
+
+
+
+int
+yyparse()
+{
+  register int yystate;
+  register int yyn;
+  register short *yyssp;
+  register short *yyrq0;
+  register short *yyptr;
+  register YYSTYPE *yyvsp;
+
+  int yylen;
+  YYLTYPE *yylsp;
+  short *yyrq1;
+  short *yyrq2;
+
+  yystate = 0;
+  yyssp = yyss - 1;
+  yyvsp = yyvs - 1;
+  yylsp = yyls - 1;
+  yyrq0 = yyrq;
+  yyrq1 = yyrq0;
+  yyrq2 = yyrq0;
+
+  yychar = yylex();
+  if (yychar < 0)
+    yychar = 0;
+  else yychar = YYTRANSLATE(yychar);
+
+yynewstate:
+
+  if (yyssp >= yyss + YYMAXDEPTH - 1)
+    {
+      yyabort("Parser Stack Overflow");
+      YYABORT;
+    }
+
+  *++yyssp = yystate;
+
+yyresume:
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  yyn += yychar;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  yystate = yyn;
+
+  yyptr = yyrq2;
+  while (yyptr != yyrq1)
+    {
+      yyn = *yyptr++;
+      yylen = yyr2[yyn];
+      yyvsp -= yylen;
+      yylsp -= yylen;
+
+      yyguard(yyn, yyvsp, yylsp);
+      if (yyerror)
+	goto yysemerr;
+
+      yyaction(yyn, yyvsp, yylsp);
+      *++yyvsp = yyval;
+
+      yylsp++;
+      if (yylen == 0)
+	{
+	  yylsp->timestamp = timeclock;
+	  yylsp->first_line = yytloc.first_line;
+	  yylsp->first_column = yytloc.first_column;
+	  yylsp->last_line = (yylsp-1)->last_line;
+	  yylsp->last_column = (yylsp-1)->last_column;
+	  yylsp->text = 0;
+	}
+      else
+	{
+	  yylsp->last_line = (yylsp+yylen-1)->last_line;
+	  yylsp->last_column = (yylsp+yylen-1)->last_column;
+	}
+	  
+      if (yyptr == yyrq + YYMAXRULES)
+        yyptr = yyrq;
+    }
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  yyrq2 = yyptr;
+  yyrq1 = yyrq0;
+
+  *++yyvsp = yytval;
+  *++yylsp = yytloc;
+  yytval = yylval;
+  yytloc = yylloc;
+  yyget();
+
+  goto yynewstate;
+
+yydefault:
+
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+
+yyreduce:
+
+  *yyrq0++ = yyn;
+
+  if (yyrq0 == yyrq + YYMAXRULES)
+    yyrq0 = yyrq;
+
+  if (yyrq0 == yyrq2)
+    {
+      yyabort("Parser Rule Queue Overflow");
+      YYABORT;
+    }
+
+  yyssp -= yyr2[yyn];
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+yysemerr:
+  *--yyptr = yyn;
+  yyrq2 = yyptr;
+  yyvsp += yyr2[yyn];
+
+yyerrlab:
+
+  yygssp = yyssp;
+  yygvsp = yyvsp;
+  yyglsp = yylsp;
+  yyrestore(yyrq0, yyrq2);
+  yyrecover();
+  yystate = *yygssp;
+  yyssp = yygssp;
+  yyvsp = yygvsp;
+  yyrq0 = yyrq;
+  yyrq1 = yyrq0;
+  yyrq2 = yyrq0;
+  goto yyresume;
+}
+
+$
diff --git a/Compiler/Tools/bison.simple b/Compiler/Tools/bison.simple
new file mode 100644
index 0000000..08acea8
--- /dev/null
+++ b/Compiler/Tools/bison.simple
@@ -0,0 +1,699 @@
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+
+/* Skeleton output parser for bison,
+   Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not __GNUC__ */
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#else /* not HAVE_ALLOCA_H */
+#ifdef _AIX
+ #pragma alloca
+#else /* not _AIX */
+char *alloca ();
+#endif /* not _AIX */
+#endif /* not HAVE_ALLOCA_H */
+#endif /* not __GNUC__ */
+
+extern void yyerror(char* s);
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not GNU C.  */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#include <alloca.h>
+#else /* not sparc */
+#if (defined (MSDOS) && !defined (__TURBOC__)) || defined (WIN32)
+#include <malloc.h>
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+#include <malloc.h>
+ #pragma alloca
+#else /* not MSDOS, __TURBOC__, or _AIX */
+#ifdef __hpux
+#ifdef __cplusplus
+extern "C" {
+void *alloca (unsigned int);
+};
+#else /* not __cplusplus */
+void *alloca ();
+#endif /* not __cplusplus */
+#endif /* __hpux */
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc.  */
+#endif /* not GNU C.  */
+#endif /* alloca not defined.  */
+
+/* This is the parser code that is written into each bison parser
+  when the %semantic_parser declaration is not specified in the grammar.
+  It was written by Richard Stallman by simplifying the hairy parser
+  used when %semantic_parser is specified.  */
+
+/* Note: there must be only one dollar sign in this file.
+   It is replaced by the list of actions, each action
+   as one case of the switch.  */
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		-2
+#define YYEOF		0
+#define YYACCEPT	return(0)
+#define YYABORT 	return(1)
+#define YYERROR		goto yyerrlab1
+/* Like YYERROR except do call yyerror.
+   This remains here temporarily to ease the
+   transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+#define YYFAIL		goto yyerrlab
+#define YYRECOVERING()  (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    { yychar = (token), yylval = (value);			\
+      yychar1 = YYTRANSLATE (yychar);				\
+      YYPOPSTACK;						\
+      goto yybackup;						\
+    }								\
+  else								\
+    { yyerror ("syntax error: cannot back up"); YYERROR; }	\
+while (0)
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+#ifndef YYPURE
+#define YYLEX		yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#ifdef YYLEX_PARAM
+#define YYLEX		yylex(&yylval, &yylloc, YYLEX_PARAM)
+#else
+#define YYLEX		yylex(&yylval, &yylloc)
+#endif
+#else /* not YYLSP_NEEDED */
+#ifdef YYLEX_PARAM
+#define YYLEX		yylex(&yylval, YYLEX_PARAM)
+#else
+#define YYLEX		yylex(&yylval)
+#endif
+#endif /* not YYLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int	yychar;			/*  the lookahead symbol		*/
+YYSTYPE	yylval;			/*  the semantic value of the		*/
+				/*  lookahead symbol			*/
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc;			/*  location data for the lookahead	*/
+				/*  symbol				*/
+#endif
+
+int yynerrs;			/*  number of parse errors so far       */
+#endif  /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug;			/*  nonzero means print parse trace	*/
+/* Since this is uninitialized, it does not stop multiple parsers
+   from coexisting.  */
+#endif
+
+/*  YYINITDEPTH indicates the initial size of the parser's stacks	*/
+
+#ifndef	YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/*  YYMAXDEPTH is the maximum size the stacks can grow to
+    (effective only if the built-in stack extension method is used).  */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+int yyparse (void);
+#endif
+
+#if __GNUC__ > 1		/* GNU C and GNU C++ define this.  */
+#define __yy_memcpy(FROM,TO,COUNT)	__builtin_memcpy(TO,FROM,COUNT)
+#else				/* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+   in available built-in functions on various systems.  */
+static void
+__yy_memcpy (from, to, count)
+     char *from;
+     char *to;
+     size_t count;
+{
+  register char *f = from;
+  register char *t = to;
+  register size_t i = count;
+
+  while (i-- > 0)
+    *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+   in available built-in functions on various systems.  */
+static void
+__yy_memcpy (char *from, char *to, size_t count)
+{
+  register char *f = from;
+  register char *t = to;
+  register size_t i = count;
+
+  while (i-- > 0)
+    *t++ = *f++;
+}
+
+#endif
+#endif
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+   into yyparse.  The argument should have type void *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   to the proper pointer type.  */
+
+#ifdef YYPARSE_PARAM
+#ifndef YYPARSE_PARAM_DECL
+#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+#endif 
+#else
+#define YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#endif
+
+extern YY_DECL;
+
+int
+yyparse(YYPARSE_PARAM_DECL YYPARSE_PARAM) {
+  register int yystate;
+  register int yyn;
+  register short *yyssp;
+  register YYSTYPE *yyvsp;
+  int yyerrstatus;	/*  number of tokens to shift before error messages enabled */
+  int yychar1 = 0;		/*  lookahead token as an internal (translated) token number */
+
+  short	yyssa[YYINITDEPTH];	/*  the state stack			*/
+  YYSTYPE yyvsa[YYINITDEPTH];	/*  the semantic value stack		*/
+
+  short *yyss = yyssa;		/*  refer to the stacks thru separate pointers */
+  YYSTYPE *yyvs = yyvsa;	/*  to allow yyoverflow to reallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+  YYLTYPE yylsa[YYINITDEPTH];	/*  the location stack			*/
+  YYLTYPE *yyls = yylsa;
+  YYLTYPE *yylsp;
+
+#define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK   (yyvsp--, yyssp--)
+#endif
+
+  size_t yystacksize = YYINITDEPTH;
+
+#ifdef YYPURE
+  int yychar;
+  YYSTYPE yylval;
+  int yynerrs;
+#ifdef YYLSP_NEEDED
+  YYLTYPE yylloc;
+#endif
+#endif
+
+  YYSTYPE yyval;		/*  the variable used to return		*/
+				/*  semantic values from the action	*/
+				/*  routines				*/
+
+  int yylen;
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Starting parse\n");
+#endif
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss - 1;
+  yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+  yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in  yystate  .  */
+/* In all cases, when you get here, the value and location stacks
+   have just been pushed. so pushing a state here evens the stacks.  */
+yynewstate:
+
+  *++yyssp = yystate;
+
+  if (yyssp >= yyss + yystacksize - 1)
+    {
+      /* Give user a chance to reallocate the stack */
+      /* Use copies of these so that the &'s don't force the real ones into memory. */
+      YYSTYPE *yyvs1 = yyvs;
+      short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+      YYLTYPE *yyls1 = yyls;
+#endif
+
+      /* Get the current used size of the three stacks, in elements.  */
+      size_t size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      /* Each stack pointer address is followed by the size of
+	 the data in use in that stack, in bytes.  */
+#ifdef YYLSP_NEEDED
+      /* This used to be a conditional around just the two extra args,
+	 but that might be undefined if yyoverflow is a macro.  */
+      yyoverflow("parser stack overflow",
+		 &yyss1, size * sizeof (*yyssp),
+		 &yyvs1, size * sizeof (*yyvsp),
+		 &yyls1, size * sizeof (*yylsp),
+		 &yystacksize);
+#else
+      yyoverflow("parser stack overflow",
+		 &yyss1, size * sizeof (*yyssp),
+		 &yyvs1, size * sizeof (*yyvsp),
+		 &yystacksize);
+#endif
+
+      yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+      yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+      /* Extend the stack our own way.  */
+      if (yystacksize >= YYMAXDEPTH)
+	{
+	  yyerror("parser stack overflow");
+	  return 2;
+	}
+      yystacksize *= 2;
+      if (yystacksize > YYMAXDEPTH)
+	yystacksize = YYMAXDEPTH;
+      yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
+      __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
+      yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
+      __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+      yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
+      __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + size - 1;
+      yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+      yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+      if (yyssp >= yyss + yystacksize - 1)
+	YYABORT;
+    }
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+  goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Reading a token: ");
+#endif
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with */
+
+  if (yychar <= 0)		/* This means end of input. */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;		/* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Now at end of input.\n");
+#endif
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+      if (yydebug)
+	{
+	  fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+	  /* Give the individual parser a way to print the precise meaning
+	     of a token, for further debugging info.  */
+#ifdef YYPRINT
+	  YYPRINT (stderr, yychar, yylval);
+#endif
+	  fprintf (stderr, ")\n");
+	}
+#endif
+    }
+
+  yyn += yychar1;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+
+  /* yyn is what to do for this token type in this state.
+     Negative => reduce, -yyn is rule number.
+     Positive => shift, yyn is new state.
+       New state is final state => don't bother to shift,
+       just return success.
+     0, or most negative number => error.  */
+
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  /* count tokens shifted since error; after three, turn off error status.  */
+  if (yyerrstatus) yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+/* Do the default action for the current state.  */
+yydefault:
+
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+
+/* Do a reduction.  yyn is the number of a rule to reduce with.  */
+yyreduce:
+  yylen = yyr2[yyn];
+  if (yylen > 0)
+    yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      int i;
+
+      fprintf (stderr, "Reducing via rule %d (line %d), ",
+	       yyn, yyrline[yyn]);
+
+      /* Print the symbols being reduced, and their result.  */
+      for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+	fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+      fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+    }
+#endif
+
+$   /* the action file gets copied in in place of this dollarsign */
+  yyvsp -= yylen;
+  yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+  yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      short *ssp1 = yyss - 1;
+      fprintf (stderr, "state stack now");
+      while (ssp1 != yyssp)
+	fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+  yylsp++;
+  if (yylen == 0)
+    {
+      yylsp->first_line = yylloc.first_line;
+      yylsp->first_column = yylloc.first_column;
+      yylsp->last_line = (yylsp-1)->last_line;
+      yylsp->last_column = (yylsp-1)->last_column;
+      yylsp->text = 0;
+    }
+  else
+    {
+      yylsp->last_line = (yylsp+yylen-1)->last_line;
+      yylsp->last_column = (yylsp+yylen-1)->last_column;
+    }
+#endif
+
+  /* Now "shift" the result of the reduction.
+     Determine what state that goes to,
+     based on the state we popped back to
+     and the rule number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+yyerrlab:   /* here on detecting error */
+
+  if (! yyerrstatus)
+    /* If not already recovering from an error, report this error.  */
+    {
+      ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (yyn > YYFLAG && yyn < YYLAST)
+	{
+	  int size = 0;
+	  char *msg;
+	  int x, count;
+
+	  count = 0;
+	  /* Start X at -yyn if nec to avoid negative indexes in yycheck.  */
+	  for (x = (yyn < 0 ? -yyn : 0);
+	       x < (sizeof(yytname) / sizeof(char *)); x++)
+	    if (yycheck[x + yyn] == x)
+	      size += strlen(yytname[x]) + 15, count++;
+	  msg = (char *) malloc(size + 15);
+	  if (msg != 0)
+	    {
+	      strcpy(msg, "parse error");
+
+	      if (count < 5)
+		{
+		  count = 0;
+		  for (x = (yyn < 0 ? -yyn : 0);
+		       x < (sizeof(yytname) / sizeof(char *)); x++)
+		    if (yycheck[x + yyn] == x)
+		      {
+			strcat(msg, count == 0 ? ", expecting `" : " or `");
+			strcat(msg, yytname[x]);
+			strcat(msg, "'");
+			count++;
+		      }
+		}
+	      yyerror(msg);
+	      free(msg);
+	    }
+	  else
+	    yyerror ("parse error; also virtual memory exceeded");
+	}
+      else
+#endif /* YYERROR_VERBOSE */
+	yyerror("parse error");
+    }
+
+  goto yyerrlab1;
+yyerrlab1:   /* here on error raised explicitly by an action */
+
+  if (yyerrstatus == 3)
+    {
+      /* if just tried and failed to reuse lookahead token after an error, discard it.  */
+
+      /* return failure if at end of input */
+      if (yychar == YYEOF)
+	YYABORT;
+
+#if YYDEBUG != 0
+      if (yydebug)
+	fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token
+     after shifting the error token.  */
+
+  yyerrstatus = 3;		/* Each real token shifted decrements this */
+
+  goto yyerrhandle;
+
+yyerrdefault:  /* current state does not do anything special for the error token. */
+
+#if 0
+  /* This is wrong; only states that explicitly want error tokens
+     should shift them.  */
+  yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
+  if (yyn) goto yydefault;
+#endif
+
+yyerrpop:   /* pop the current state because it cannot handle the error token */
+
+  if (yyssp == yyss) YYABORT;
+  yyvsp--;
+  yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+  yylsp--;
+#endif
+
+#if YYDEBUG != 0
+  if (yydebug)
+    {
+      short *ssp1 = yyss - 1;
+      fprintf (stderr, "Error: state stack now");
+      while (ssp1 != yyssp)
+	fprintf (stderr, " %d", *++ssp1);
+      fprintf (stderr, "\n");
+    }
+#endif
+
+yyerrhandle:
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yyerrdefault;
+
+  yyn += YYTERROR;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+    goto yyerrdefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+	goto yyerrpop;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrpop;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+#if YYDEBUG != 0
+  if (yydebug)
+    fprintf(stderr, "Shifting error token, ");
+#endif
+
+  *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  yystate = yyn;
+  goto yynewstate;
+}
diff --git a/Compiler/Tools/flex.exe b/Compiler/Tools/flex.exe
new file mode 100644
index 0000000..58f10ce
--- /dev/null
+++ b/Compiler/Tools/flex.exe
Binary files differ
diff --git a/Compiler/Types.h b/Compiler/Types.h
new file mode 100644
index 0000000..eba792c
--- /dev/null
+++ b/Compiler/Types.h
@@ -0,0 +1,300 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _TYPES_INCLUDED
+#define _TYPES_INCLUDED
+
+#include "Common.h"
+#include "BaseTypes.h"
+
+//
+// Need to have association of line numbers to types in a list for building structs.
+//
+class TType;
+struct TTypeLine {
+	TType* type;
+	int line;
+};
+typedef TVector<TTypeLine> TTypeList;
+
+inline TTypeList* NewPoolTTypeList()
+{
+	void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList));
+	return new(memory) TTypeList;
+}
+
+//
+// This is a workaround for a problem with the yacc stack,  It can't have
+// types that it thinks have non-trivial constructors.  It should
+// just be used while recognizing the grammar, not anything else.  Pointers
+// could be used, but also trying to avoid lots of memory management overhead.
+//
+// Not as bad as it looks, there is no actual assumption that the fields
+// match up or are name the same or anything like that.
+//
+class TPublicType {
+public:
+	TBasicType type;
+	TQualifier qualifier;
+	TPrecision precision;
+	int size;          // size of vector or matrix, not size of array
+	bool matrix;
+	bool array;
+	int arraySize;
+	TType* userDef;
+	int line;
+
+	void setBasic(TBasicType bt, TQualifier q, int ln = 0)
+	{
+		type = bt;
+		qualifier = q;
+		precision = EbpHigh;
+		size = 1;
+		matrix = false;
+		array = false;
+		arraySize = 0;
+		userDef = 0;
+		line = ln;
+	}
+
+	void setPrecision(TPrecision pcs)
+	{
+		precision = pcs;
+	}
+
+	void setAggregate(int s, bool m = false)
+	{
+		size = s;
+		matrix = m;
+	}
+
+	void setArray(bool a, int s = 0)
+	{
+		array = a;
+		arraySize = s;
+	}
+};
+
+typedef std::map<TTypeList*, TTypeList*> TStructureMap;
+typedef std::map<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
+//
+// Base class for things that have a type.
+//
+class TType {
+public:
+	POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+	explicit TType(TBasicType t, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false, TPrecision p = EbpHigh) :
+							type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
+							structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
+							{ }
+	explicit TType(const TPublicType &p) :
+							type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
+							structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
+							{
+							  if (p.userDef) {
+								  structure = p.userDef->getStruct();
+								  typeName = NewPoolTString(p.userDef->getTypeName().c_str());
+							  }
+							}
+	explicit TType(TTypeList* userDef, const TString& n, TPrecision p = EbpHigh) :
+							type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
+							structure(userDef), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0) {
+								typeName = NewPoolTString(n.c_str());
+							}
+	explicit TType() {}
+	virtual ~TType() {}
+
+	TType(const TType& type) { *this = type; }
+
+	void copyType(const TType& copyOf, TStructureMap& remapper)
+	{
+		type = copyOf.type;
+		precision = copyOf.precision;
+		qualifier = copyOf.qualifier;
+		size = copyOf.size;
+		matrix = copyOf.matrix;
+		array = copyOf.array;
+		arraySize = copyOf.arraySize;
+
+		TStructureMapIterator iter;
+		if (copyOf.structure) {
+			if ((iter = remapper.find(structure)) == remapper.end()) {
+				// create the new structure here
+				structure = NewPoolTTypeList();
+				for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
+					TTypeLine typeLine;
+					typeLine.line = (*copyOf.structure)[i].line;
+					typeLine.type = (*copyOf.structure)[i].type->clone(remapper);
+					structure->push_back(typeLine);
+				}
+			} else {
+				structure = iter->second;
+			}
+		} else
+			structure = 0;
+
+		fieldName = 0;
+		if (copyOf.fieldName)
+			fieldName = NewPoolTString(copyOf.fieldName->c_str());
+		typeName = 0;
+		if (copyOf.typeName)
+			typeName = NewPoolTString(copyOf.typeName->c_str());
+
+		mangled = 0;
+		if (copyOf.mangled)
+			mangled = NewPoolTString(copyOf.mangled->c_str());
+
+		structureSize = copyOf.structureSize;
+		maxArraySize = copyOf.maxArraySize;
+		assert(copyOf.arrayInformationType == 0);
+		arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level
+	}
+
+	TType* clone(TStructureMap& remapper)
+	{
+		TType *newType = new TType();
+		newType->copyType(*this, remapper);
+
+		return newType;
+	}
+
+	virtual void setType(TBasicType t, int s, bool m, bool a, int aS = 0)
+							{ type = t; size = s; matrix = m; array = a; arraySize = aS; }
+	virtual void setType(TBasicType t, int s, bool m, TType* userDef = 0)
+							{ type = t;
+							  size = s;
+							  matrix = m;
+							  if (userDef)
+								  structure = userDef->getStruct();
+							  // leave array information intact.
+							}
+	virtual void setTypeName(const TString& n) { typeName = NewPoolTString(n.c_str()); }
+	virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
+	virtual const TString& getTypeName() const
+	{
+		assert(typeName);
+		return *typeName;
+	}
+
+	virtual const TString& getFieldName() const
+	{
+		assert(fieldName);
+		return *fieldName;
+	}
+
+	virtual TBasicType getBasicType() const { return type; }
+	virtual TPrecision getPrecision() const { return precision; }
+	virtual TQualifier getQualifier() const { return qualifier; }
+	virtual void changePrecision(TPrecision p) { precision = p; }
+	virtual void changeQualifier(TQualifier q) { qualifier = q; }
+
+	// One-dimensional size of single instance type
+	virtual int getNominalSize() const { return size; }
+
+	// Full-dimensional size of single instance of type
+	virtual int getInstanceSize() const
+	{
+		if (matrix)
+			return size * size;
+		else
+			return size;
+	}
+
+	virtual bool isMatrix() const { return matrix ? true : false; }
+	virtual bool isArray() const  { return array ? true : false; }
+	int getArraySize() const { return arraySize; }
+	void setArraySize(int s) { array = true; arraySize = s; }
+	void setMaxArraySize (int s) { maxArraySize = s; }
+	int getMaxArraySize () const { return maxArraySize; }
+	void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; }
+	void setArrayInformationType(TType* t) { arrayInformationType = t; }
+	TType* getArrayInformationType() const { return arrayInformationType; }
+	virtual bool isVector() const { return size > 1 && !matrix; }
+	static const char* getBasicString(TBasicType t) {
+		switch (t) {
+		case EbtVoid:              return "void";              break;
+		case EbtFloat:             return "float";             break;
+		case EbtInt:               return "int";               break;
+		case EbtBool:              return "bool";              break;
+		case EbtSampler2D:         return "sampler2D";         break;
+		case EbtSamplerCube:       return "samplerCube";       break;
+		case EbtStruct:            return "structure";         break;
+		default:                   return "unknown type";
+		}
+	}
+	const char* getBasicString() const { return TType::getBasicString(type); }
+	const char* getPrecisionString() const { return ::getPrecisionString(precision); }
+	const char* getQualifierString() const { return ::getQualifierString(qualifier); }
+	TTypeList* getStruct() { return structure; }
+
+	int getObjectSize() const
+	{
+		int totalSize;
+
+		if (getBasicType() == EbtStruct)
+			totalSize = getStructSize();
+		else if (matrix)
+			totalSize = size * size;
+		else
+			totalSize = size;
+
+		if (isArray())
+			totalSize *= Max(getArraySize(), getMaxArraySize());
+
+		return totalSize;
+	}
+
+	TTypeList* getStruct() const { return structure; }
+	TString& getMangledName() {
+		if (!mangled) {
+			mangled = NewPoolTString("");
+			buildMangledName(*mangled);
+			*mangled += ';' ;
+		}
+
+		return *mangled;
+	}
+	bool sameElementType(const TType& right) const {
+		return      type == right.type   &&
+					size == right.size   &&
+				  matrix == right.matrix &&
+			   structure == right.structure;
+	}
+	bool operator==(const TType& right) const {
+		return      type == right.type   &&
+					size == right.size   &&
+				  matrix == right.matrix &&
+				   array == right.array  && (!array || arraySize == right.arraySize) &&
+			   structure == right.structure;
+		// don't check the qualifier, it's not ever what's being sought after
+	}
+	bool operator!=(const TType& right) const {
+		return !operator==(right);
+	}
+	TString getCompleteString() const;
+
+protected:
+	void buildMangledName(TString&);
+	int getStructSize() const;
+
+	TBasicType type      : 6;
+	TPrecision precision;
+	TQualifier qualifier : 7;
+	int size             : 8; // size of vector or matrix, not size of array
+	unsigned int matrix  : 1;
+	unsigned int array   : 1;
+	int arraySize;
+
+	TTypeList* structure;      // 0 unless this is a struct
+	mutable int structureSize;
+	int maxArraySize;
+	TType* arrayInformationType;
+	TString *fieldName;         // for structure field names
+	TString *mangled;
+	TString *typeName;          // for structure field type name
+};
+
+#endif // _TYPES_INCLUDED_
diff --git a/Compiler/glslang.l b/Compiler/glslang.l
new file mode 100644
index 0000000..6a76234
--- /dev/null
+++ b/Compiler/glslang.l
@@ -0,0 +1,605 @@
+/*
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+*/
+/* Based on
+ANSI C grammar, Lex specification
+
+In 1985, Jeff Lee published this Lex specification together with a Yacc 
+grammar for the April 30, 1985 ANSI C draft.  Tom Stockfisch reposted 
+both to net.sources in 1987; that original, as mentioned in the answer 
+to question 17.25 of the comp.lang.c FAQ, can be ftp'ed from ftp.uu.net, 
+file usenet/net.sources/ansi.c.grammar.Z. 
+
+I intend to keep this version as close to the current C Standard grammar 
+as possible; please let me know if you discover discrepancies. 
+
+Jutta Degener, 1995 
+*/
+
+D           [0-9]
+L           [a-zA-Z_]
+H           [a-fA-F0-9]
+E           [Ee][+-]?{D}+
+O           [0-7]
+
+%option nounput 
+%{
+#include <stdio.h>
+#include <stdlib.h>
+#include "ParseHelper.h"
+#include "glslang_tab.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+#pragma warning(disable : 4102)
+#endif
+
+int yy_input(char* buf, int max_size);
+TSourceLoc yylineno;
+
+#ifdef _WIN32
+    extern int yyparse(TParseContext&);
+    #define YY_DECL int yylex(YYSTYPE* pyylval, TParseContext& parseContext)    
+#else
+    extern int yyparse(void*);
+    #define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal)
+    #define parseContext (*((TParseContext*)(parseContextLocal)))		
+#endif
+ 
+#define YY_INPUT(buf,result,max_size) (result = yy_input(buf, max_size))
+
+%}
+
+%option noyywrap
+%option never-interactive
+%option outfile="Gen_glslang.cpp"
+%x FIELDS
+
+
+%%
+<*>"//"[^\n]*"\n"     { /* ?? carriage and/or line-feed? */ };
+
+"invariant"    {  pyylval->lex.line = yylineno; return(INVARIANT); }
+"highp"        {  pyylval->lex.line = yylineno; return(HIGH_PRECISION); }
+"mediump"      {  pyylval->lex.line = yylineno; return(MEDIUM_PRECISION); }
+"lowp"         {  pyylval->lex.line = yylineno; return(LOW_PRECISION); }
+"precision"    {  pyylval->lex.line = yylineno; return(PRECISION); }
+
+"attribute"    {  pyylval->lex.line = yylineno; return(ATTRIBUTE); }
+"const"        {  pyylval->lex.line = yylineno; return(CONST_QUAL); }
+"uniform"      {  pyylval->lex.line = yylineno; return(UNIFORM); }
+"varying"      {  pyylval->lex.line = yylineno; return(VARYING); }
+
+"break"        {  pyylval->lex.line = yylineno; return(BREAK); }
+"continue"     {  pyylval->lex.line = yylineno; return(CONTINUE); }
+"do"           {  pyylval->lex.line = yylineno; return(DO); }
+"for"          {  pyylval->lex.line = yylineno; return(FOR); }
+"while"        {  pyylval->lex.line = yylineno; return(WHILE); }
+
+"if"           {  pyylval->lex.line = yylineno; return(IF); }
+"else"         {  pyylval->lex.line = yylineno; return(ELSE); }
+
+"in"           {  pyylval->lex.line = yylineno; return(IN_QUAL); }
+"out"          {  pyylval->lex.line = yylineno; return(OUT_QUAL); }
+"inout"        {  pyylval->lex.line = yylineno; return(INOUT_QUAL); }
+
+"float"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(FLOAT_TYPE); }
+"int"          {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(INT_TYPE); }
+"void"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(VOID_TYPE); }
+"bool"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(BOOL_TYPE); }
+"true"         {  pyylval->lex.line = yylineno; pyylval->lex.b = true;  return(BOOLCONSTANT); }
+"false"        {  pyylval->lex.line = yylineno; pyylval->lex.b = false; return(BOOLCONSTANT); }
+
+"discard"      {  pyylval->lex.line = yylineno; return(DISCARD); }
+"return"       {  pyylval->lex.line = yylineno; return(RETURN); }
+
+"mat2"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX2); }
+"mat3"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX3); }
+"mat4"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX4); }
+
+"vec2"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC2); }
+"vec3"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC3); }
+"vec4"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC4); }
+"ivec2"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC2); }
+"ivec3"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC3); }
+"ivec4"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC4); }
+"bvec2"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC2); }
+"bvec3"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC3); }
+"bvec4"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC4); }
+
+"sampler2D"       {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER2D; }
+"samplerCube"     {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLERCUBE; }
+
+"struct"       {  pyylval->lex.line = yylineno; return(STRUCT); }
+
+"asm"          {  PaReservedWord(); return 0; }
+
+"class"        {  PaReservedWord(); return 0; }
+"union"        {  PaReservedWord(); return 0; }
+"enum"         {  PaReservedWord(); return 0; }
+"typedef"      {  PaReservedWord(); return 0; }
+"template"     {  PaReservedWord(); return 0; }
+"this"         {  PaReservedWord(); return 0; }
+"packed"       {  PaReservedWord(); return 0; }
+
+"goto"         {  PaReservedWord(); return 0; }
+"switch"       {  PaReservedWord(); return 0; }
+"default"      {  PaReservedWord(); return 0; }
+
+"inline"       {  PaReservedWord(); return 0; }
+"noinline"     {  PaReservedWord(); return 0; }
+"volatile"     {  PaReservedWord(); return 0; }
+"public"       {  PaReservedWord(); return 0; }
+"static"       {  PaReservedWord(); return 0; }
+"extern"       {  PaReservedWord(); return 0; }
+"external"     {  PaReservedWord(); return 0; }
+"interface"    {  PaReservedWord(); return 0; }
+
+"long"         {  PaReservedWord(); return 0; }
+"short"        {  PaReservedWord(); return 0; }
+"double"       {  PaReservedWord(); return 0; }
+"half"         {  PaReservedWord(); return 0; }
+"fixed"        {  PaReservedWord(); return 0; }
+"unsigned"     {  PaReservedWord(); return 0; }
+
+"input"        {  PaReservedWord(); return 0; }
+"output"       {  PaReservedWord(); return 0; }
+
+"hvec2"        {  PaReservedWord(); return 0; }
+"hvec3"        {  PaReservedWord(); return 0; }
+"hvec4"        {  PaReservedWord(); return 0; }
+"fvec2"        {  PaReservedWord(); return 0; }
+"fvec3"        {  PaReservedWord(); return 0; }
+"fvec4"        {  PaReservedWord(); return 0; }
+"dvec2"        {  PaReservedWord(); return 0; }
+"dvec3"        {  PaReservedWord(); return 0; }
+"dvec4"        {  PaReservedWord(); return 0; }
+
+"sizeof"       {  PaReservedWord(); return 0; }
+"cast"         {  PaReservedWord(); return 0; }
+
+"namespace"    {  PaReservedWord(); return 0; }
+"using"        {  PaReservedWord(); return 0; }
+
+{L}({L}|{D})*       {  
+   pyylval->lex.line = yylineno; 
+   pyylval->lex.string = NewPoolTString(yytext); 
+   return PaIdentOrType(*pyylval->lex.string, parseContext, pyylval->lex.symbol); 
+}
+
+0[xX]{H}+         { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+0{O}+             { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+0{D}+             { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); parseContext.recover(); return 0;}
+{D}+              { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+
+{D}+{E}           { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+{D}+"."{D}*({E})? { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+"."{D}+({E})?     { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
+
+"/*"            {  int ret = PaParseComment(pyylval->lex.line, parseContext); if (!ret) return ret; }   
+
+"+="            {  pyylval->lex.line = yylineno; return(ADD_ASSIGN); }
+"-="            {  pyylval->lex.line = yylineno; return(SUB_ASSIGN); }
+"*="            {  pyylval->lex.line = yylineno; return(MUL_ASSIGN); }
+"/="            {  pyylval->lex.line = yylineno; return(DIV_ASSIGN); }
+"%="            {  pyylval->lex.line = yylineno; return(MOD_ASSIGN); }
+"<<="           {  pyylval->lex.line = yylineno; return(LEFT_ASSIGN); }
+">>="           {  pyylval->lex.line = yylineno; return(RIGHT_ASSIGN); }
+"&="            {  pyylval->lex.line = yylineno; return(AND_ASSIGN); }
+"^="            {  pyylval->lex.line = yylineno; return(XOR_ASSIGN); }
+"|="            {  pyylval->lex.line = yylineno; return(OR_ASSIGN); }
+
+"++"            {  pyylval->lex.line = yylineno; return(INC_OP); }
+"--"            {  pyylval->lex.line = yylineno; return(DEC_OP); }
+"&&"            {  pyylval->lex.line = yylineno; return(AND_OP); }
+"||"            {  pyylval->lex.line = yylineno; return(OR_OP); }
+"^^"            {  pyylval->lex.line = yylineno; return(XOR_OP); }
+"<="            {  pyylval->lex.line = yylineno; return(LE_OP); }
+">="            {  pyylval->lex.line = yylineno; return(GE_OP); }
+"=="            {  pyylval->lex.line = yylineno; return(EQ_OP); }
+"!="            {  pyylval->lex.line = yylineno; return(NE_OP); }
+"<<"            {  pyylval->lex.line = yylineno; return(LEFT_OP); }
+">>"            {  pyylval->lex.line = yylineno; return(RIGHT_OP); }
+";"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(SEMICOLON); }
+("{"|"<%")      {  pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(LEFT_BRACE); }
+("}"|"%>")      {  pyylval->lex.line = yylineno; return(RIGHT_BRACE); }
+","         {  pyylval->lex.line = yylineno; if (parseContext.inTypeParen) parseContext.lexAfterType = false; return(COMMA); }
+":"         {  pyylval->lex.line = yylineno; return(COLON); }
+"="         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(EQUAL); }
+"("         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = false; parseContext.inTypeParen = true; return(LEFT_PAREN); }
+")"         {  pyylval->lex.line = yylineno; parseContext.inTypeParen = false; return(RIGHT_PAREN); }
+("["|"<:")      {  pyylval->lex.line = yylineno; return(LEFT_BRACKET); }
+("]"|":>")      {  pyylval->lex.line = yylineno; return(RIGHT_BRACKET); }
+"."         { BEGIN(FIELDS);  return(DOT); }
+"!"         {  pyylval->lex.line = yylineno; return(BANG); }
+"-"         {  pyylval->lex.line = yylineno; return(DASH); }
+"~"         {  pyylval->lex.line = yylineno; return(TILDE); }
+"+"         {  pyylval->lex.line = yylineno; return(PLUS); }
+"*"         {  pyylval->lex.line = yylineno; return(STAR); }
+"/"         {  pyylval->lex.line = yylineno; return(SLASH); }
+"%"         {  pyylval->lex.line = yylineno; return(PERCENT); }
+"<"         {  pyylval->lex.line = yylineno; return(LEFT_ANGLE); }
+">"         {  pyylval->lex.line = yylineno; return(RIGHT_ANGLE); }
+"|"         {  pyylval->lex.line = yylineno; return(VERTICAL_BAR); }
+"^"         {  pyylval->lex.line = yylineno; return(CARET); }
+"&"         {  pyylval->lex.line = yylineno; return(AMPERSAND); }
+"?"         {  pyylval->lex.line = yylineno; return(QUESTION); }
+
+<FIELDS>{L}({L}|{D})* { 
+BEGIN(INITIAL);      
+    pyylval->lex.line = yylineno;     
+    pyylval->lex.string = NewPoolTString(yytext); 
+    return FIELD_SELECTION; }
+<FIELDS>[ \t\v\f\r] {}
+
+[ \t\v\n\f\r]   {  }
+<*><<EOF>> { (&parseContext)->AfterEOF = true; yy_delete_buffer(YY_CURRENT_BUFFER); yyterminate();}
+<*>.    { parseContext.infoSink.info << "FLEX: Unknown char " << yytext << "\n";
+          return 0; }
+
+%%
+
+
+//Including Pre-processor.
+extern "C" {
+  #include "./preprocessor/preprocess.h"
+} 
+
+//
+// The YY_INPUT macro just calls this.  Maybe this could be just put into
+// the macro directly.
+//
+
+int yy_input(char* buf, int max_size)
+{
+    int len;
+
+    if ((len = yylex_CPP(buf, max_size)) == 0)
+        return 0;
+    if (len >= max_size) 
+        YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+
+    buf[len] = ' ';
+	return len+1;
+}
+
+
+//
+// Parse an array of strings using yyparse.  We set up globals used by
+// yywrap.
+//
+// Returns 0 for success, as per yyparse().
+//
+int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseContextLocal)
+{
+    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;
+    
+    for (int i = 0; i < argc; ++i) {
+        if (!argv[i]) {
+            parseContextLocal.error(0, "Null shader source string", "", "");
+            parseContextLocal.recover();
+            return 1;
+        }
+    }
+    
+    if (!strLen) {
+        argv0len = (int) strlen(argv[0]);
+        strLen   = &argv0len;
+    }
+    yyrestart(0);
+    (&parseContextLocal)->AfterEOF = false;
+    cpp->PaWhichStr = 0;
+    cpp->PaArgv     = argv;
+    cpp->PaArgc     = argc;
+    cpp->PaStrLen   = strLen;
+    cpp->notAVersionToken = 0;
+    yylineno   = 1;
+   
+    if (*cpp->PaStrLen >= 0) {    
+        int ret;
+        #ifdef _WIN32
+            ret = yyparse(parseContextLocal);            
+        #else
+            ret = yyparse((void*)(&parseContextLocal));
+        #endif
+        if (cpp->CompileError == 1 || parseContextLocal.recoveredFromError || parseContextLocal.numErrors > 0)
+             return 1;
+        else
+             return 0;
+    }
+    else
+        return 0;
+}
+
+void yyerror(char *s) 
+{
+    if (((TParseContext *)cpp->pC)->AfterEOF) {
+        if (cpp->tokensBeforeEOF == 1) {
+            GlobalParseContext->error(yylineno, "syntax error", "pre-mature EOF", s, "");
+            GlobalParseContext->recover();
+        }
+    } else {
+        GlobalParseContext->error(yylineno, "syntax error", yytext, s, "");
+        GlobalParseContext->recover();
+    }            
+}
+
+void PaReservedWord()
+{
+    GlobalParseContext->error(yylineno, "Reserved word.", yytext, "", "");
+    GlobalParseContext->recover();
+}
+
+int PaIdentOrType(TString& id, TParseContext& parseContextLocal, TSymbol*& symbol)
+{
+    symbol = parseContextLocal.symbolTable.find(id);
+    if (parseContextLocal.lexAfterType == false && symbol && symbol->isVariable()) {
+        TVariable* variable = static_cast<TVariable*>(symbol);
+        if (variable->isUserType()) {
+            parseContextLocal.lexAfterType = true;
+            return TYPE_NAME;
+        }
+    }
+    
+    return IDENTIFIER;
+}
+
+int PaParseComment(int &lineno, TParseContext& parseContextLocal)
+{
+    int transitionFlag = 0;
+    int nextChar;
+    
+    while (transitionFlag != 2) {
+        nextChar = yyinput();
+        if (nextChar == '\n')
+             lineno++;
+        switch (nextChar) {
+        case '*' :
+            transitionFlag = 1;
+            break;
+        case '/' :  /* if star is the previous character, then it is the end of comment */
+            if (transitionFlag == 1) {
+                return 1 ;
+            }
+            break;
+        case EOF :
+            /* Raise error message here */
+            parseContextLocal.error(yylineno, "End of shader found before end of comment.", "", "", "");
+            GlobalParseContext->recover();
+            return YY_NULL; 
+        default :  /* Any other character will be a part of the comment */
+            transitionFlag = 0;
+        }
+    }
+    return 1;
+}
+
+extern "C" {
+
+void CPPDebugLogMsg(const char *msg)
+{
+    ((TParseContext *)cpp->pC)->infoSink.debug.message(EPrefixNone, msg);
+}
+
+void CPPWarningToInfoLog(const char *msg)
+{
+    ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg, yylineno); 
+}
+
+void CPPShInfoLogMsg(const char *msg)
+{
+    ((TParseContext *)cpp->pC)->error(yylineno,"", "",msg,"");
+    GlobalParseContext->recover();
+}
+
+void CPPErrorToInfoLog(char *msg)
+{
+    ((TParseContext *)cpp->pC)->error(yylineno,"syntax error", "",msg,"");
+    GlobalParseContext->recover();
+}
+
+void SetLineNumber(int line)
+{
+    yylineno &= ~SourceLocLineMask;
+    yylineno |= line;
+}
+
+void SetStringNumber(int string)
+{
+    yylineno = (string << SourceLocStringShift) | (yylineno & SourceLocLineMask);
+}
+
+int GetStringNumber(void)
+{
+    return yylineno >> 16;
+}
+
+int GetLineNumber(void)
+{
+    return yylineno & SourceLocLineMask;
+}
+
+void IncLineNumber(void)
+{
+    if ((yylineno & SourceLocLineMask) <= SourceLocLineMask)
+        ++yylineno;
+}
+
+void DecLineNumber(void)
+{
+    if ((yylineno & SourceLocLineMask) > 0)
+        --yylineno;
+}
+
+void HandlePragma(const char **tokens, int numTokens)
+{    
+    if (!strcmp(tokens[0], "optimize")) {
+        if (numTokens != 4) {
+            CPPShInfoLogMsg("optimize pragma syntax is incorrect");
+            return;
+        }
+        
+        if (strcmp(tokens[1], "(")) {
+            CPPShInfoLogMsg("\"(\" expected after 'optimize' keyword");
+            return;
+        }
+            
+        if (!strcmp(tokens[2], "on"))
+            ((TParseContext *)cpp->pC)->contextPragma.optimize = true;
+        else if (!strcmp(tokens[2], "off"))
+            ((TParseContext *)cpp->pC)->contextPragma.optimize = false;
+        else {
+            CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'optimize' pragma");
+            return;
+        }
+        
+        if (strcmp(tokens[3], ")")) {
+            CPPShInfoLogMsg("\")\" expected to end 'optimize' pragma");
+            return;
+        }
+    } else if (!strcmp(tokens[0], "debug")) {
+        if (numTokens != 4) {
+            CPPShInfoLogMsg("debug pragma syntax is incorrect");
+            return;
+        }
+        
+        if (strcmp(tokens[1], "(")) {
+            CPPShInfoLogMsg("\"(\" expected after 'debug' keyword");
+            return;
+        }
+            
+        if (!strcmp(tokens[2], "on"))
+            ((TParseContext *)cpp->pC)->contextPragma.debug = true;
+        else if (!strcmp(tokens[2], "off"))
+            ((TParseContext *)cpp->pC)->contextPragma.debug = false;
+        else {
+            CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'debug' pragma");
+            return;
+        }
+        
+        if (strcmp(tokens[3], ")")) {
+            CPPShInfoLogMsg("\")\" expected to end 'debug' pragma");
+            return;
+        }
+    } else {
+
+#ifdef PRAGMA_TABLE
+        //
+        // implementation specific pragma
+        // use ((TParseContext *)cpp->pC)->contextPragma.pragmaTable to store the information about pragma
+        // For now, just ignore the pragma that the implementation cannot recognize
+        // An Example of one such implementation for a pragma that has a syntax like
+        // #pragma pragmaname(pragmavalue)
+        // This implementation stores the current pragmavalue against the pragma name in pragmaTable.
+        //        
+        if (numTokens == 4 && !strcmp(tokens[1], "(") && !strcmp(tokens[3], ")")) {              
+            TPragmaTable& pragmaTable = ((TParseContext *)cpp->pC)->contextPragma.pragmaTable;
+            TPragmaTable::iterator iter;
+            iter = pragmaTable.find(TString(tokens[0]));
+            if (iter != pragmaTable.end()) {
+                iter->second = tokens[2];
+            } else {
+                pragmaTable[tokens[0]] = tokens[2];
+            }        
+        } else if (numTokens >= 2) {
+            TPragmaTable& pragmaTable = ((TParseContext *)cpp->pC)->contextPragma.pragmaTable;
+            TPragmaTable::iterator iter;
+            iter = pragmaTable.find(TString(tokens[0]));
+            if (iter != pragmaTable.end()) {
+                iter->second = tokens[1];
+            } else {
+                pragmaTable[tokens[0]] = tokens[1];
+            }
+        }
+#endif // PRAGMA_TABLE
+    }
+}
+
+void StoreStr(char *string)
+{
+    TString strSrc;
+    strSrc = TString(string);
+
+    ((TParseContext *)cpp->pC)->HashErrMsg = ((TParseContext *)cpp->pC)->HashErrMsg + " " + strSrc;
+}
+
+const char* GetStrfromTStr(void)
+{
+    cpp->ErrMsg = (((TParseContext *)cpp->pC)->HashErrMsg).c_str();
+    return cpp->ErrMsg;
+}
+
+void ResetTString(void)
+{
+    ((TParseContext *)cpp->pC)->HashErrMsg = "";
+}
+
+TBehavior GetBehavior(const char* behavior)
+{
+    if (!strcmp("require", behavior))
+        return EBhRequire;
+    else if (!strcmp("enable", behavior))
+        return EBhEnable;
+    else if (!strcmp("disable", behavior))
+        return EBhDisable;
+    else if (!strcmp("warn", behavior))
+        return EBhWarn;
+    else {
+        CPPShInfoLogMsg((TString("behavior '") + behavior + "' is not supported").c_str());
+        return EBhDisable;
+    }        
+}
+
+void  updateExtensionBehavior(const char* extName, const char* behavior)
+{
+    TBehavior behaviorVal = GetBehavior(behavior);
+    TMap<TString, TBehavior>:: iterator iter;
+    TString msg;
+    
+    // special cased for all extension
+    if (!strcmp(extName, "all")) {
+        if (behaviorVal == EBhRequire || behaviorVal == EBhEnable) {
+            CPPShInfoLogMsg("extension 'all' cannot have 'require' or 'enable' behavior");  
+            return;
+        } else {
+            for (iter =  ((TParseContext *)cpp->pC)->extensionBehavior.begin(); iter != ((TParseContext *)cpp->pC)->extensionBehavior.end(); ++iter)
+                iter->second = behaviorVal;
+        }        
+    } else {
+        iter = ((TParseContext *)cpp->pC)->extensionBehavior.find(TString(extName));
+        if (iter == ((TParseContext *)cpp->pC)->extensionBehavior.end()) {
+            switch (behaviorVal) {
+            case EBhRequire:
+                CPPShInfoLogMsg((TString("extension '") + extName + "' is not supported").c_str());  
+                break;
+            case EBhEnable:
+            case EBhWarn:
+            case EBhDisable:
+                msg = TString("extension '") + extName + "' is not supported";
+                ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg.c_str(), yylineno); 
+                break;
+            }
+            return;
+        } else
+            iter->second = behaviorVal;
+    }
+}
+        
+}  // extern "C"
+
+void setInitialState()
+{
+    yy_start = 1;
+}
diff --git a/Compiler/glslang.y b/Compiler/glslang.y
new file mode 100644
index 0000000..ec2603e
--- /dev/null
+++ b/Compiler/glslang.y
@@ -0,0 +1,2204 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+/**
+ * This is bison grammar and production code for parsing the OpenGL 2.0 shading
+ * languages.
+ */
+%{
+
+/* Based on:
+ANSI C Yacc grammar
+
+In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a
+matching Lex specification) for the April 30, 1985 draft version of the
+ANSI C standard.  Tom Stockfisch reposted it to net.sources in 1987; that
+original, as mentioned in the answer to question 17.25 of the comp.lang.c
+FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z.
+
+I intend to keep this version as close to the current C Standard grammar as
+possible; please let me know if you discover discrepancies.
+
+Jutta Degener, 1995
+*/
+
+#include "SymbolTable.h"
+#include "ParseHelper.h"
+#include "ShaderLang.h"
+
+#ifdef _WIN32
+    #define YYPARSE_PARAM parseContext
+    #define YYPARSE_PARAM_DECL TParseContext&
+    #define YY_DECL int yylex(YYSTYPE* pyylval, TParseContext& parseContext)
+    #define YYLEX_PARAM parseContext
+#else
+    #define YYPARSE_PARAM parseContextLocal
+    #define parseContext (*((TParseContext*)(parseContextLocal)))
+    #define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal)
+    #define YYLEX_PARAM (void*)(parseContextLocal)
+    extern void yyerror(char*);
+#endif
+
+#define FRAG_VERT_ONLY(S, L) {                                                  \
+    if (parseContext.language != EShLangFragment &&                             \
+        parseContext.language != EShLangVertex) {                               \
+        parseContext.error(L, " supported in vertex/fragment shaders only ", S, "", "");   \
+        parseContext.recover();                                                            \
+    }                                                                           \
+}
+
+#define VERTEX_ONLY(S, L) {                                                     \
+    if (parseContext.language != EShLangVertex) {                               \
+        parseContext.error(L, " supported in vertex shaders only ", S, "", "");            \
+        parseContext.recover();                                                            \
+    }                                                                           \
+}
+
+#define FRAG_ONLY(S, L) {                                                       \
+    if (parseContext.language != EShLangFragment) {                             \
+        parseContext.error(L, " supported in fragment shaders only ", S, "", "");          \
+        parseContext.recover();                                                            \
+    }                                                                           \
+}
+
+#define PACK_ONLY(S, L) {                                                       \
+    if (parseContext.language != EShLangPack) {                                 \
+        parseContext.error(L, " supported in pack shaders only ", S, "", "");              \
+        parseContext.recover();                                                            \
+    }                                                                           \
+}
+
+#define UNPACK_ONLY(S, L) {                                                     \
+    if (parseContext.language != EShLangUnpack) {                               \
+        parseContext.error(L, " supported in unpack shaders only ", S, "", "");            \
+        parseContext.recover();                                                            \
+    }                                                                           \
+}
+
+#define PACK_UNPACK_ONLY(S, L) {                                                \
+    if (parseContext.language != EShLangUnpack &&                               \
+        parseContext.language != EShLangPack) {                                 \
+        parseContext.error(L, " supported in pack/unpack shaders only ", S, "", "");       \
+        parseContext.recover();                                                            \
+    }                                                                           \
+}
+%}
+%union {
+    struct {
+        TSourceLoc line;
+        union {
+            TString *string;
+            float f;
+            int i;
+            bool b;
+        };
+        TSymbol* symbol;
+    } lex;
+    struct {
+        TSourceLoc line;
+        TOperator op;
+        union {
+            TIntermNode* intermNode;
+            TIntermNodePair nodePair;
+            TIntermTyped* intermTypedNode;
+            TIntermAggregate* intermAggregate;
+        };
+        union {
+            TPublicType type;
+            TPrecision precision;
+            TQualifier qualifier;
+            TFunction* function;
+            TParameter param;
+            TTypeLine typeLine;
+            TTypeList* typeList;
+        };
+    } interm;
+}
+
+%{
+#ifndef _WIN32
+    extern int yylex(YYSTYPE*, void*);
+#endif
+%}
+
+%pure_parser /* Just in case is called from multiple threads */
+%expect 1 /* One shift reduce conflict because of if | else */
+%token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
+%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE
+%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN
+%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4
+%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING
+%token <lex> STRUCT VOID_TYPE WHILE
+%token <lex> SAMPLER2D SAMPLERCUBE
+
+%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT
+%token <lex> FIELD_SELECTION
+%token <lex> LEFT_OP RIGHT_OP
+%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
+%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
+%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
+%token <lex> SUB_ASSIGN
+
+%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
+%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
+%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
+
+%type <interm> assignment_operator unary_operator
+%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
+%type <interm.intermTypedNode> expression integer_expression assignment_expression
+%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
+%type <interm.intermTypedNode> relational_expression equality_expression
+%type <interm.intermTypedNode> conditional_expression constant_expression
+%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
+%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
+%type <interm.intermTypedNode> function_call initializer condition conditionopt
+
+%type <interm.intermNode> translation_unit function_definition
+%type <interm.intermNode> statement simple_statement
+%type <interm.intermAggregate>  statement_list compound_statement
+%type <interm.intermNode> declaration_statement selection_statement expression_statement
+%type <interm.intermNode> declaration external_declaration
+%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
+%type <interm.nodePair> selection_rest_statement for_rest_statement
+%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope
+%type <interm> single_declaration init_declarator_list
+
+%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
+%type <interm.qualifier> parameter_qualifier
+
+%type <interm.precision> precision_qualifier
+%type <interm.type> type_qualifier fully_specified_type type_specifier
+%type <interm.type> type_specifier_no_prec type_specifier_nonarray
+%type <interm.type> struct_specifier
+%type <interm.typeLine> struct_declarator
+%type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list
+%type <interm.function> function_header function_declarator function_identifier
+%type <interm.function> function_header_with_parameters function_call_header
+%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
+%type <interm> function_call_or_method
+
+%start translation_unit
+%%
+
+variable_identifier
+    : IDENTIFIER {
+        // The symbol table search was done in the lexical phase
+        const TSymbol* symbol = $1.symbol;
+        const TVariable* variable;
+        if (symbol == 0) {
+            parseContext.error($1.line, "undeclared identifier", $1.string->c_str(), "");
+            parseContext.recover();
+            TType type(EbtFloat);
+            TVariable* fakeVariable = new TVariable($1.string, type);
+            parseContext.symbolTable.insert(*fakeVariable);
+            variable = fakeVariable;
+        } else {
+            // This identifier can only be a variable type symbol
+            if (! symbol->isVariable()) {
+                parseContext.error($1.line, "variable expected", $1.string->c_str(), "");
+                parseContext.recover();
+            }
+            variable = static_cast<const TVariable*>(symbol);
+        }
+
+        // don't delete $1.string, it's used by error recovery, and the pool
+        // pop will reclaim the memory
+
+        if (variable->getType().getQualifier() == EvqConst ) {
+            constUnion* constArray = variable->getConstPointer();
+            TType t(variable->getType());
+            $$ = parseContext.intermediate.addConstantUnion(constArray, t, $1.line);
+        } else
+            $$ = parseContext.intermediate.addSymbol(variable->getUniqueId(),
+                                                     variable->getName(),
+                                                     variable->getType(), $1.line);
+    }
+    ;
+
+primary_expression
+    : variable_identifier {
+        $$ = $1;
+    }
+    | INTCONSTANT {
+        //
+        // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders,
+        // check for overflow for constants
+        //
+        if (abs($1.i) >= (1 << 16)) {
+            parseContext.error($1.line, " integer constant overflow", "", "");
+            parseContext.recover();
+        }
+        constUnion *unionArray = new constUnion[1];
+        unionArray->setIConst($1.i);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.line);
+    }
+    | FLOATCONSTANT {
+        constUnion *unionArray = new constUnion[1];
+        unionArray->setFConst($1.f);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.line);
+    }
+    | BOOLCONSTANT {
+        constUnion *unionArray = new constUnion[1];
+        unionArray->setBConst($1.b);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $1.line);
+    }
+    | LEFT_PAREN expression RIGHT_PAREN {
+        $$ = $2;
+    }
+    ;
+
+postfix_expression
+    : primary_expression {
+        $$ = $1;
+    }
+    | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
+        if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) {
+            if ($1->getAsSymbolNode())
+                parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str(), "");
+            else
+                parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", "");
+            parseContext.recover();
+        }
+        if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) {
+            if ($1->isArray()) { // constant folding for arrays
+                $$ = parseContext.addConstArrayNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line);
+            } else if ($1->isVector()) {  // constant folding for vectors
+                TVectorFields fields;
+                fields.num = 1;
+                fields.offsets[0] = $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); // need to do it this way because v.xy sends fields integer array
+                $$ = parseContext.addConstVectorNode(fields, $1, $2.line);
+            } else if ($1->isMatrix()) { // constant folding for matrices
+                $$ = parseContext.addConstMatrixNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line);
+            }
+        } else {
+            if ($3->getQualifier() == EvqConst) {
+                if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() && !$1->isArray() ) {
+                    parseContext.error($2.line, "", "[", "field selection out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
+                    parseContext.recover();
+                } else {
+                    if ($1->isArray()) {
+                        if ($1->getType().getArraySize() == 0) {
+                            if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) {
+                                if (parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line))
+                                    parseContext.recover();
+                            } else {
+                                if (parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line))
+                                    parseContext.recover();
+                            }
+                        } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize()) {
+                            parseContext.error($2.line, "", "[", "array index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
+                            parseContext.recover();
+                        }
+                    }
+                    $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line);
+                }
+            } else {
+                if ($1->isArray() && $1->getType().getArraySize() == 0) {
+                    parseContext.error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable");
+                    parseContext.recover();
+                }
+
+                $$ = parseContext.intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line);
+            }
+        }
+        if ($$ == 0) {
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setFConst(0.0f);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $2.line);
+        } else if ($1->isArray()) {
+            if ($1->getType().getStruct())
+                $$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName()));
+            else
+                $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize(), $1->isMatrix()));
+
+            if ($1->getType().getQualifier() == EvqConst)
+                $$->getTypePointer()->changeQualifier(EvqConst);
+        } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst)
+            $$->setType(TType($1->getBasicType(), EvqConst, $1->getNominalSize()));
+        else if ($1->isMatrix())
+            $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize()));
+        else if ($1->isVector() && $1->getType().getQualifier() == EvqConst)
+            $$->setType(TType($1->getBasicType(), EvqConst));
+        else if ($1->isVector())
+            $$->setType(TType($1->getBasicType(), EvqTemporary));
+        else
+            $$->setType($1->getType());
+    }
+    | function_call {
+        $$ = $1;
+    }
+    | postfix_expression DOT FIELD_SELECTION {
+        if ($1->isArray()) {
+            parseContext.error($3.line, "cannot apply dot operator to an array", ".", "");
+            parseContext.recover();
+        }
+
+        if ($1->isVector()) {
+            TVectorFields fields;
+            if (! parseContext.parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+                fields.num = 1;
+                fields.offsets[0] = 0;
+                parseContext.recover();
+            }
+
+            if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields
+                $$ = parseContext.addConstVectorNode(fields, $1, $3.line);
+                if ($$ == 0) {
+                    parseContext.recover();
+                    $$ = $1;
+                }
+                else
+                    $$->setType(TType($1->getBasicType(), EvqConst, (int) (*$3.string).size()));
+            } else {
+                if (fields.num == 1) {
+                    constUnion *unionArray = new constUnion[1];
+                    unionArray->setIConst(fields.offsets[0]);
+                    TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+                    $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+                    $$->setType(TType($1->getBasicType()));
+                } else {
+                    TString vectorString = *$3.string;
+                    TIntermTyped* index = parseContext.intermediate.addSwizzle(fields, $3.line);
+                    $$ = parseContext.intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);
+                    $$->setType(TType($1->getBasicType(),EvqTemporary, (int) vectorString.size()));
+                }
+            }
+        } else if ($1->isMatrix()) {
+            TMatrixFields fields;
+            if (! parseContext.parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+                fields.wholeRow = false;
+                fields.wholeCol = false;
+                fields.row = 0;
+                fields.col = 0;
+                parseContext.recover();
+            }
+
+            if (fields.wholeRow || fields.wholeCol) {
+                parseContext.error($2.line, " non-scalar fields not implemented yet", ".", "");
+                parseContext.recover();
+                constUnion *unionArray = new constUnion[1];
+                unionArray->setIConst(0);
+                TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+                $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+                $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize()));
+            } else {
+                constUnion *unionArray = new constUnion[1];
+                unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row);
+                TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+                $$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+                $$->setType(TType($1->getBasicType()));
+            }
+        } else if ($1->getBasicType() == EbtStruct) {
+            bool fieldFound = false;
+            TTypeList* fields = $1->getType().getStruct();
+            if (fields == 0) {
+                parseContext.error($2.line, "structure has no fields", "Internal Error", "");
+                parseContext.recover();
+                $$ = $1;
+            } else {
+                unsigned int i;
+                for (i = 0; i < fields->size(); ++i) {
+                    if ((*fields)[i].type->getFieldName() == *$3.string) {
+                        fieldFound = true;
+                        break;
+                    }
+                }
+                if (fieldFound) {
+                    if ($1->getType().getQualifier() == EvqConst) {
+                        $$ = parseContext.addConstStruct(*$3.string, $1, $2.line);
+                        if ($$ == 0) {
+                            parseContext.recover();
+                            $$ = $1;
+                        }
+                        else {
+                            $$->setType(*(*fields)[i].type);
+                            // change the qualifier of the return type, not of the structure field
+                            // as the structure definition is shared between various structures.
+                            $$->getTypePointer()->changeQualifier(EvqConst);
+                        }
+                    } else {
+                        constUnion *unionArray = new constUnion[1];
+                        unionArray->setIConst(i);
+                        TIntermTyped* index = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+                        $$ = parseContext.intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line);
+                        $$->setType(*(*fields)[i].type);
+                    }
+                } else {
+                    parseContext.error($2.line, " no such field in structure", $3.string->c_str(), "");
+                    parseContext.recover();
+                    $$ = $1;
+                }
+            }
+        } else {
+            parseContext.error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str(), "");
+            parseContext.recover();
+            $$ = $1;
+        }
+        // don't delete $3.string, it's from the pool
+    }
+    | postfix_expression INC_OP {
+        if (parseContext.lValueErrorCheck($2.line, "++", $1))
+            parseContext.recover();
+        $$ = parseContext.intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.unaryOpError($2.line, "++", $1->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    | postfix_expression DEC_OP {
+        if (parseContext.lValueErrorCheck($2.line, "--", $1))
+            parseContext.recover();
+        $$ = parseContext.intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.unaryOpError($2.line, "--", $1->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+integer_expression
+    : expression {
+        if (parseContext.integerErrorCheck($1, "[]"))
+            parseContext.recover();
+        $$ = $1;
+    }
+    ;
+
+function_call
+    : function_call_or_method {
+        TFunction* fnCall = $1.function;
+        TOperator op = fnCall->getBuiltInOp();
+
+        if (op == EOpArrayLength) {
+            if ($1.intermNode->getAsTyped() == 0 || $1.intermNode->getAsTyped()->getType().getArraySize() == 0) {
+                parseContext.error($1.line, "", fnCall->getName().c_str(), "array must be declared with a size before using this method");
+                parseContext.recover();
+            }
+
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setIConst($1.intermNode->getAsTyped()->getType().getArraySize());
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.line);
+        } else if (op != EOpNull) {
+            //
+            // Then this should be a constructor.
+            // Don't go through the symbol table for constructors.
+            // Their parameters will be verified algorithmically.
+            //
+            TType type(EbtVoid);  // use this to get the type back
+            if (parseContext.constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) {
+                $$ = 0;
+            } else {
+                //
+                // It's a constructor, of type 'type'.
+                //
+                $$ = parseContext.addConstructor($1.intermNode, &type, op, fnCall, $1.line);
+            }
+
+            if ($$ == 0) {
+                parseContext.recover();
+                $$ = parseContext.intermediate.setAggregateOperator(0, op, $1.line);
+            }
+            $$->setType(type);
+        } else {
+            //
+            // Not a constructor.  Find it in the symbol table.
+            //
+            const TFunction* fnCandidate;
+            bool builtIn;
+            fnCandidate = parseContext.findFunction($1.line, fnCall, &builtIn);
+            if (fnCandidate) {
+                //
+                // A declared function.  But, it might still map to a built-in
+                // operation.
+                //
+                op = fnCandidate->getBuiltInOp();
+                if (builtIn && op != EOpNull) {
+                    //
+                    // A function call mapped to a built-in operation.
+                    //
+                    if (fnCandidate->getParamCount() == 1) {
+                        //
+                        // Treat it like a built-in unary operator.
+                        //
+                        $$ = parseContext.intermediate.addUnaryMath(op, $1.intermNode, 0, parseContext.symbolTable);
+                        if ($$ == 0)  {
+                            parseContext.error($1.intermNode->getLine(), " wrong operand type", "Internal Error",
+                                "built in unary operator function.  Type: %s",
+                                static_cast<TIntermTyped*>($1.intermNode)->getCompleteString().c_str());
+                            YYERROR;
+                        }
+                    } else {
+                        $$ = parseContext.intermediate.setAggregateOperator($1.intermAggregate, op, $1.line);
+                    }
+                } else {
+                    // This is a real function call
+
+                    $$ = parseContext.intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, $1.line);
+                    $$->setType(fnCandidate->getReturnType());
+
+                    // this is how we know whether the given function is a builtIn function or a user defined function
+                    // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
+                    // if builtIn == true, it's definitely a builtIn function with EOpNull
+                    if (!builtIn)
+                        $$->getAsAggregate()->setUserDefined();
+                    $$->getAsAggregate()->setName(fnCandidate->getMangledName());
+
+                    TQualifier qual;
+                    TQualifierList& qualifierList = $$->getAsAggregate()->getQualifier();
+                    for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
+                        qual = (*fnCandidate)[i].type->getQualifier();
+                        if (qual == EvqOut || qual == EvqInOut) {
+                            if (parseContext.lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {
+                                parseContext.error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", "");
+                                parseContext.recover();
+                            }
+                        }
+                        qualifierList.push_back(qual);
+                    }
+                }
+                $$->setType(fnCandidate->getReturnType());
+            } else {
+                // error message was put out by PaFindFunction()
+                // Put on a dummy node for error recovery
+                constUnion *unionArray = new constUnion[1];
+                unionArray->setFConst(0.0f);
+                $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.line);
+                parseContext.recover();
+            }
+        }
+        delete fnCall;
+    }
+    ;
+
+function_call_or_method
+    : function_call_generic {
+        $$ = $1;
+    }
+    | postfix_expression DOT function_call_generic {
+        parseContext.error($3.line, "methods are not supported", "", "");
+        parseContext.recover();
+        $$ = $3;
+    }
+    ;
+
+function_call_generic
+    : function_call_header_with_parameters RIGHT_PAREN {
+        $$ = $1;
+        $$.line = $2.line;
+    }
+    | function_call_header_no_parameters RIGHT_PAREN {
+        $$ = $1;
+        $$.line = $2.line;
+    }
+    ;
+
+function_call_header_no_parameters
+    : function_call_header VOID_TYPE {
+        $$.function = $1;
+        $$.intermNode = 0;
+    }
+    | function_call_header {
+        $$.function = $1;
+        $$.intermNode = 0;
+    }
+    ;
+
+function_call_header_with_parameters
+    : function_call_header assignment_expression {
+        TParameter param = { 0, new TType($2->getType()) };
+        $1->addParameter(param);
+        $$.function = $1;
+        $$.intermNode = $2;
+    }
+    | function_call_header_with_parameters COMMA assignment_expression {
+        TParameter param = { 0, new TType($3->getType()) };
+        $1.function->addParameter(param);
+        $$.function = $1.function;
+        $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, $3, $2.line);
+    }
+    ;
+
+function_call_header
+    : function_identifier LEFT_PAREN {
+        $$ = $1;
+    }
+    ;
+
+// Grammar Note:  Constructors look like functions, but are recognized as types.
+
+function_identifier
+    : type_specifier {
+        //
+        // Constructor
+        //
+        if ($1.array) {
+            if (parseContext.extensionErrorCheck($1.line, "GL_3DL_array_objects")) {
+                parseContext.recover();
+                $1.setArray(false);
+            }
+        }
+
+        if ($1.userDef) {
+            TString tempString = "";
+            TType type($1);
+            TFunction *function = new TFunction(&tempString, type, EOpConstructStruct);
+            $$ = function;
+        } else {
+            TOperator op = EOpNull;
+            switch ($1.type) {
+            case EbtFloat:
+                if ($1.matrix) {
+                    switch($1.size) {
+                    case 2:                                     op = EOpConstructMat2;  break;
+                    case 3:                                     op = EOpConstructMat3;  break;
+                    case 4:                                     op = EOpConstructMat4;  break;
+                    }
+                } else {
+                    switch($1.size) {
+                    case 1:                                     op = EOpConstructFloat; break;
+                    case 2:                                     op = EOpConstructVec2;  break;
+                    case 3:                                     op = EOpConstructVec3;  break;
+                    case 4:                                     op = EOpConstructVec4;  break;
+                    }
+                }
+                break;
+            case EbtInt:
+                switch($1.size) {
+                case 1:                                         op = EOpConstructInt;   break;
+                case 2:       FRAG_VERT_ONLY("ivec2", $1.line); op = EOpConstructIVec2; break;
+                case 3:       FRAG_VERT_ONLY("ivec3", $1.line); op = EOpConstructIVec3; break;
+                case 4:       FRAG_VERT_ONLY("ivec4", $1.line); op = EOpConstructIVec4; break;
+                }
+                break;
+            case EbtBool:
+                switch($1.size) {
+                case 1:                                         op = EOpConstructBool;  break;
+                case 2:       FRAG_VERT_ONLY("bvec2", $1.line); op = EOpConstructBVec2; break;
+                case 3:       FRAG_VERT_ONLY("bvec3", $1.line); op = EOpConstructBVec3; break;
+                case 4:       FRAG_VERT_ONLY("bvec4", $1.line); op = EOpConstructBVec4; break;
+                }
+                break;
+            }
+            if (op == EOpNull) {
+                parseContext.error($1.line, "cannot construct this type", TType::getBasicString($1.type), "");
+                parseContext.recover();
+                $1.type = EbtFloat;
+                op = EOpConstructFloat;
+            }
+            TString tempString = "";
+            TType type($1);
+            TFunction *function = new TFunction(&tempString, type, op);
+            $$ = function;
+        }
+    }
+    | IDENTIFIER {
+        if (parseContext.reservedErrorCheck($1.line, *$1.string))
+            parseContext.recover();
+        TType type(EbtVoid);
+        TFunction *function = new TFunction($1.string, type);
+        $$ = function;
+    }
+    | FIELD_SELECTION {
+        if (parseContext.reservedErrorCheck($1.line, *$1.string))
+            parseContext.recover();
+        TType type(EbtVoid);
+        TFunction *function = new TFunction($1.string, type);
+        $$ = function;
+    }
+    ;
+
+unary_expression
+    : postfix_expression {
+        $$ = $1;
+    }
+    | INC_OP unary_expression {
+        if (parseContext.lValueErrorCheck($1.line, "++", $2))
+            parseContext.recover();
+        $$ = parseContext.intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.unaryOpError($1.line, "++", $2->getCompleteString());
+            parseContext.recover();
+            $$ = $2;
+        }
+    }
+    | DEC_OP unary_expression {
+        if (parseContext.lValueErrorCheck($1.line, "--", $2))
+            parseContext.recover();
+        $$ = parseContext.intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.unaryOpError($1.line, "--", $2->getCompleteString());
+            parseContext.recover();
+            $$ = $2;
+        }
+    }
+    | unary_operator unary_expression {
+        if ($1.op != EOpNull) {
+            $$ = parseContext.intermediate.addUnaryMath($1.op, $2, $1.line, parseContext.symbolTable);
+            if ($$ == 0) {
+                const char* errorOp = "";
+                switch($1.op) {
+                case EOpNegative:   errorOp = "-"; break;
+                case EOpLogicalNot: errorOp = "!"; break;
+                case EOpBitwiseNot: errorOp = "~"; break;
+				default: break;
+                }
+                parseContext.unaryOpError($1.line, errorOp, $2->getCompleteString());
+                parseContext.recover();
+                $$ = $2;
+            }
+        } else
+            $$ = $2;
+    }
+    ;
+// Grammar Note:  No traditional style type casts.
+
+unary_operator
+    : PLUS  { $$.line = $1.line; $$.op = EOpNull; }
+    | DASH  { $$.line = $1.line; $$.op = EOpNegative; }
+    | BANG  { $$.line = $1.line; $$.op = EOpLogicalNot; }
+    | TILDE { PACK_UNPACK_ONLY("~", $1.line);
+              $$.line = $1.line; $$.op = EOpBitwiseNot; }
+    ;
+// Grammar Note:  No '*' or '&' unary ops.  Pointers are not supported.
+
+multiplicative_expression
+    : unary_expression { $$ = $1; }
+    | multiplicative_expression STAR unary_expression {
+        FRAG_VERT_ONLY("*", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    | multiplicative_expression SLASH unary_expression {
+        FRAG_VERT_ONLY("/", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    | multiplicative_expression PERCENT unary_expression {
+        PACK_UNPACK_ONLY("%", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpMod, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "%", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+additive_expression
+    : multiplicative_expression { $$ = $1; }
+    | additive_expression PLUS multiplicative_expression {
+        $$ = parseContext.intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    | additive_expression DASH multiplicative_expression {
+        $$ = parseContext.intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+shift_expression
+    : additive_expression { $$ = $1; }
+    | shift_expression LEFT_OP additive_expression {
+        PACK_UNPACK_ONLY("<<", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpLeftShift, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "<<", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    | shift_expression RIGHT_OP additive_expression {
+        PACK_UNPACK_ONLY(">>", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpRightShift, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, ">>", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+relational_expression
+    : shift_expression { $$ = $1; }
+    | relational_expression LEFT_ANGLE shift_expression {
+        $$ = parseContext.intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        }
+    }
+    | relational_expression RIGHT_ANGLE shift_expression  {
+        $$ = parseContext.intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        }
+    }
+    | relational_expression LE_OP shift_expression  {
+        $$ = parseContext.intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        }
+    }
+    | relational_expression GE_OP shift_expression  {
+        $$ = parseContext.intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        }
+    }
+    ;
+
+equality_expression
+    : relational_expression { $$ = $1; }
+    | equality_expression EQ_OP relational_expression  {
+        $$ = parseContext.intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        } else if (($1->isArray() || $3->isArray()) && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects"))
+            parseContext.recover();
+    }
+    | equality_expression NE_OP relational_expression {
+        $$ = parseContext.intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        } else if (($1->isArray() || $3->isArray()) && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects"))
+            parseContext.recover();
+    }
+    ;
+
+and_expression
+    : equality_expression { $$ = $1; }
+    | and_expression AMPERSAND equality_expression {
+        PACK_UNPACK_ONLY("&", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpAnd, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "&", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+exclusive_or_expression
+    : and_expression { $$ = $1; }
+    | exclusive_or_expression CARET and_expression {
+        PACK_UNPACK_ONLY("^", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpExclusiveOr, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "^", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+inclusive_or_expression
+    : exclusive_or_expression { $$ = $1; }
+    | inclusive_or_expression VERTICAL_BAR exclusive_or_expression {
+        PACK_UNPACK_ONLY("|", $2.line);
+        $$ = parseContext.intermediate.addBinaryMath(EOpInclusiveOr, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "|", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+logical_and_expression
+    : inclusive_or_expression { $$ = $1; }
+    | logical_and_expression AND_OP inclusive_or_expression {
+        $$ = parseContext.intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        }
+    }
+    ;
+
+logical_xor_expression
+    : logical_and_expression { $$ = $1; }
+    | logical_xor_expression XOR_OP logical_and_expression  {
+        $$ = parseContext.intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        }
+    }
+    ;
+
+logical_or_expression
+    : logical_xor_expression { $$ = $1; }
+    | logical_or_expression OR_OP logical_xor_expression  {
+        $$ = parseContext.intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, parseContext.symbolTable);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            constUnion *unionArray = new constUnion[1];
+            unionArray->setBConst(false);
+            $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+        }
+    }
+    ;
+
+conditional_expression
+    : logical_or_expression { $$ = $1; }
+    | logical_or_expression QUESTION expression COLON assignment_expression {
+       if (parseContext.boolErrorCheck($2.line, $1))
+            parseContext.recover();
+
+        $$ = parseContext.intermediate.addSelection($1, $3, $5, $2.line);
+        if ($3->getType() != $5->getType())
+            $$ = 0;
+
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
+            parseContext.recover();
+            $$ = $5;
+        }
+    }
+    ;
+
+assignment_expression
+    : conditional_expression { $$ = $1; }
+    | unary_expression assignment_operator assignment_expression {
+        if (parseContext.lValueErrorCheck($2.line, "assign", $1))
+            parseContext.recover();
+        $$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.line);
+        if ($$ == 0) {
+            parseContext.assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $1;
+        } else if (($1->isArray() || $3->isArray()) && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects"))
+            parseContext.recover();
+    }
+    ;
+
+assignment_operator
+    : EQUAL        {                                    $$.line = $1.line; $$.op = EOpAssign; }
+    | MUL_ASSIGN   { FRAG_VERT_ONLY("*=", $1.line);     $$.line = $1.line; $$.op = EOpMulAssign; }
+    | DIV_ASSIGN   { FRAG_VERT_ONLY("/=", $1.line);     $$.line = $1.line; $$.op = EOpDivAssign; }
+    | MOD_ASSIGN   { PACK_UNPACK_ONLY("%=", $1.line);   $$.line = $1.line; $$.op = EOpModAssign; }
+    | ADD_ASSIGN   {                                    $$.line = $1.line; $$.op = EOpAddAssign; }
+    | SUB_ASSIGN   {                                    $$.line = $1.line; $$.op = EOpSubAssign; }
+    | LEFT_ASSIGN  { PACK_UNPACK_ONLY("<<=", $1.line);  $$.line = $1.line; $$.op = EOpLeftShiftAssign; }
+    | RIGHT_ASSIGN { PACK_UNPACK_ONLY("<<=", $1.line);  $$.line = $1.line; $$.op = EOpRightShiftAssign; }
+    | AND_ASSIGN   { PACK_UNPACK_ONLY("&=",  $1.line);  $$.line = $1.line; $$.op = EOpAndAssign; }
+    | XOR_ASSIGN   { PACK_UNPACK_ONLY("^=",  $1.line);  $$.line = $1.line; $$.op = EOpExclusiveOrAssign; }
+    | OR_ASSIGN    { PACK_UNPACK_ONLY("|=",  $1.line);  $$.line = $1.line; $$.op = EOpInclusiveOrAssign; }
+    ;
+
+expression
+    : assignment_expression {
+        $$ = $1;
+    }
+    | expression COMMA assignment_expression {
+        $$ = parseContext.intermediate.addComma($1, $3, $2.line);
+        if ($$ == 0) {
+            parseContext.binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString());
+            parseContext.recover();
+            $$ = $3;
+        }
+    }
+    ;
+
+constant_expression
+    : conditional_expression {
+        if (parseContext.constErrorCheck($1))
+            parseContext.recover();
+        $$ = $1;
+    }
+    ;
+
+declaration
+    : function_prototype SEMICOLON   { $$ = 0; }
+    | init_declarator_list SEMICOLON {
+		if ($1.intermAggregate)
+            $1.intermAggregate->setOperator(EOpDeclaration);
+        $$ = $1.intermAggregate;
+    }
+    | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
+    	$$ = 0;
+    }
+    ;
+
+function_prototype
+    : function_declarator RIGHT_PAREN  {
+        //
+        // Multiple declarations of the same function are allowed.
+        //
+        // If this is a definition, the definition production code will check for redefinitions
+        // (we don't know at this point if it's a definition or not).
+        //
+        // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
+        //
+        TFunction* prevDec = static_cast<TFunction*>(parseContext.symbolTable.find($1->getMangledName()));
+        if (prevDec) {
+            if (prevDec->getReturnType() != $1->getReturnType()) {
+                parseContext.error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString(), "");
+                parseContext.recover();
+            }
+            for (int i = 0; i < prevDec->getParamCount(); ++i) {
+                if ((*prevDec)[i].type->getQualifier() != (*$1)[i].type->getQualifier()) {
+                    parseContext.error($2.line, "overloaded functions must have the same parameter qualifiers", (*$1)[i].type->getQualifierString(), "");
+                    parseContext.recover();
+                }
+            }
+        }
+
+        //
+        // If this is a redeclaration, it could also be a definition,
+        // in which case, we want to use the variable names from this one, and not the one that's
+        // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
+        //
+        $$.function = $1;
+        $$.line = $2.line;
+
+        parseContext.symbolTable.insert(*$$.function);
+    }
+    ;
+
+function_declarator
+    : function_header {
+        $$ = $1;
+    }
+    | function_header_with_parameters {
+        $$ = $1;
+    }
+    ;
+
+
+function_header_with_parameters
+    : function_header parameter_declaration {
+        // Add the parameter
+        $$ = $1;
+        if ($2.param.type->getBasicType() != EbtVoid)
+            $1->addParameter($2.param);
+        else
+            delete $2.param.type;
+    }
+    | function_header_with_parameters COMMA parameter_declaration {
+        //
+        // Only first parameter of one-parameter functions can be void
+        // The check for named parameters not being void is done in parameter_declarator
+        //
+        if ($3.param.type->getBasicType() == EbtVoid) {
+            //
+            // This parameter > first is void
+            //
+            parseContext.error($2.line, "cannot be an argument type except for '(void)'", "void", "");
+            parseContext.recover();
+            delete $3.param.type;
+        } else {
+            // Add the parameter
+            $$ = $1;
+            $1->addParameter($3.param);
+        }
+    }
+    ;
+
+function_header
+    : fully_specified_type IDENTIFIER LEFT_PAREN {
+        if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) {
+            parseContext.error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier), "");
+            parseContext.recover();
+        }
+        // make sure a sampler is not involved as well...
+        if (parseContext.structQualifierErrorCheck($2.line, $1))
+            parseContext.recover();
+
+        // Add the function as a prototype after parsing it (we do not support recursion)
+        TFunction *function;
+        TType type($1);
+        function = new TFunction($2.string, type);
+        $$ = function;
+    }
+    ;
+
+parameter_declarator
+    // Type + name
+    : type_specifier IDENTIFIER {
+        if ($1.type == EbtVoid) {
+            parseContext.error($2.line, "illegal use of type 'void'", $2.string->c_str(), "");
+            parseContext.recover();
+        }
+        if (parseContext.reservedErrorCheck($2.line, *$2.string))
+            parseContext.recover();
+        TParameter param = {$2.string, new TType($1)};
+        $$.line = $2.line;
+        $$.param = param;
+    }
+    | type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        // Check that we can make an array out of this type
+        if (parseContext.arrayTypeErrorCheck($3.line, $1))
+            parseContext.recover();
+
+        if (parseContext.reservedErrorCheck($2.line, *$2.string))
+            parseContext.recover();
+
+        int size;
+        if (parseContext.arraySizeErrorCheck($3.line, $4, size))
+            parseContext.recover();
+        $1.setArray(true, size);
+
+        TType* type = new TType($1);
+        TParameter param = { $2.string, type };
+        $$.line = $2.line;
+        $$.param = param;
+    }
+    ;
+
+parameter_declaration
+    //
+    // The only parameter qualifier a parameter can have are
+    // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
+    //
+
+    //
+    // Type + name
+    //
+    : type_qualifier parameter_qualifier parameter_declarator {
+        $$ = $3;
+        if (parseContext.paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+            parseContext.recover();
+    }
+    | parameter_qualifier parameter_declarator {
+        $$ = $2;
+        if (parseContext.parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+            parseContext.recover();
+        if (parseContext.paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+            parseContext.recover();
+    }
+    //
+    // Only type
+    //
+    | type_qualifier parameter_qualifier parameter_type_specifier {
+        $$ = $3;
+        if (parseContext.paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+            parseContext.recover();
+    }
+    | parameter_qualifier parameter_type_specifier {
+        $$ = $2;
+        if (parseContext.parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+            parseContext.recover();
+        if (parseContext.paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+            parseContext.recover();
+    }
+    ;
+
+parameter_qualifier
+    : /* empty */ {
+        $$ = EvqIn;
+    }
+    | IN_QUAL {
+        $$ = EvqIn;
+    }
+    | OUT_QUAL {
+        $$ = EvqOut;
+    }
+    | INOUT_QUAL {
+        $$ = EvqInOut;
+    }
+    ;
+
+parameter_type_specifier
+    : type_specifier {
+        TParameter param = { 0, new TType($1) };
+        $$.param = param;
+    }
+    ;
+
+init_declarator_list
+    : single_declaration {
+        $$ = $1;
+    }
+    | init_declarator_list COMMA IDENTIFIER {
+        $$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, parseContext.intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line), $3.line);
+        
+        if (parseContext.structQualifierErrorCheck($3.line, $$.type))
+            parseContext.recover();
+
+        if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $$.type))
+            parseContext.recover();
+
+        if (parseContext.nonInitErrorCheck($3.line, *$3.string, $$.type))
+            parseContext.recover();
+    }
+    | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
+        if (parseContext.structQualifierErrorCheck($3.line, $1.type))
+            parseContext.recover();
+
+        if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $1.type))
+            parseContext.recover();
+
+        $$ = $1;
+
+        if (parseContext.arrayTypeErrorCheck($4.line, $1.type) || parseContext.arrayQualifierErrorCheck($4.line, $1.type))
+            parseContext.recover();
+        else {
+            $1.type.setArray(true);
+            TVariable* variable;
+            if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+                parseContext.recover();
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        if (parseContext.structQualifierErrorCheck($3.line, $1.type))
+            parseContext.recover();
+
+        if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $1.type))
+            parseContext.recover();
+
+        $$ = $1;
+
+        if (parseContext.arrayTypeErrorCheck($4.line, $1.type) || parseContext.arrayQualifierErrorCheck($4.line, $1.type))
+            parseContext.recover();
+        else {
+            int size;
+            if (parseContext.arraySizeErrorCheck($4.line, $5, size))
+                parseContext.recover();
+            $1.type.setArray(true, size);
+            TVariable* variable;
+            if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+                parseContext.recover();
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET EQUAL initializer {
+        if (parseContext.structQualifierErrorCheck($3.line, $1.type))
+            parseContext.recover();
+
+        $$ = $1;
+
+        TVariable* variable = 0;
+        if (parseContext.arrayTypeErrorCheck($4.line, $1.type) || parseContext.arrayQualifierErrorCheck($4.line, $1.type))
+            parseContext.recover();
+        else {
+			$1.type.setArray(true, $7->getType().getArraySize());
+            if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+                parseContext.recover();
+        }
+
+        if (parseContext.extensionErrorCheck($$.line, "GL_3DL_array_objects"))
+            parseContext.recover();
+        else {
+            TIntermNode* intermNode;
+            if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $7, intermNode, variable)) {
+                //
+                // build the intermediate representation
+                //
+                if (intermNode)
+                    $$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $6.line);
+                else
+                    $$.intermAggregate = $1.intermAggregate;
+            } else {
+                parseContext.recover();
+                $$.intermAggregate = 0;
+            }
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer {
+        if (parseContext.structQualifierErrorCheck($3.line, $1.type))
+            parseContext.recover();
+
+        $$ = $1;
+
+        TVariable* variable = 0;
+        if (parseContext.arrayTypeErrorCheck($4.line, $1.type) || parseContext.arrayQualifierErrorCheck($4.line, $1.type))
+            parseContext.recover();
+        else {
+            int size;
+            if (parseContext.arraySizeErrorCheck($4.line, $5, size))
+                parseContext.recover();
+            $1.type.setArray(true, size);
+            if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+                parseContext.recover();
+        }
+
+        if (parseContext.extensionErrorCheck($$.line, "GL_3DL_array_objects"))
+            parseContext.recover();
+        else {
+            TIntermNode* intermNode;
+            if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $8, intermNode, variable)) {
+                //
+                // build the intermediate representation
+                //
+                if (intermNode)
+                    $$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $7.line);
+                else
+                    $$.intermAggregate = $1.intermAggregate;
+            } else {
+                parseContext.recover();
+                $$.intermAggregate = 0;
+            }
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER EQUAL initializer {
+        if (parseContext.structQualifierErrorCheck($3.line, $1.type))
+            parseContext.recover();
+
+        $$ = $1;
+
+        TIntermNode* intermNode;
+        if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) {
+            //
+            // build the intermediate representation
+            //
+            if (intermNode)
+		$$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $4.line);
+            else
+                $$.intermAggregate = $1.intermAggregate;
+        } else {
+            parseContext.recover();
+            $$.intermAggregate = 0;
+        }
+    }
+    ;
+
+single_declaration
+    : fully_specified_type {
+        $$.type = $1;
+        $$.intermAggregate = 0;
+    }
+    | fully_specified_type IDENTIFIER {
+		$$.intermAggregate = parseContext.intermediate.makeAggregate(parseContext.intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line);
+        
+        if (parseContext.structQualifierErrorCheck($2.line, $$.type))
+            parseContext.recover();
+
+        if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $$.type))
+            parseContext.recover();
+            
+            $$.type = $1;
+
+        if (parseContext.nonInitErrorCheck($2.line, *$2.string, $$.type))
+            parseContext.recover();
+    }
+    | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
+        $$.intermAggregate = parseContext.intermediate.makeAggregate(parseContext.intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line);
+        
+        if (parseContext.structQualifierErrorCheck($2.line, $1))
+            parseContext.recover();
+
+        if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $1))
+            parseContext.recover();
+
+        $$.type = $1;
+
+        if (parseContext.arrayTypeErrorCheck($3.line, $1) || parseContext.arrayQualifierErrorCheck($3.line, $1))
+            parseContext.recover();
+        else {
+            $1.setArray(true);
+            TVariable* variable;
+            if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable))
+                parseContext.recover();
+        }
+    }
+    | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+		TType type = TType($1);
+		int size;
+        if (parseContext.arraySizeErrorCheck($2.line, $4, size))
+            parseContext.recover();
+		type.setArraySize(size);
+        $$.intermAggregate = parseContext.intermediate.makeAggregate(parseContext.intermediate.addSymbol(0, *$2.string, type, $2.line), $2.line);
+        
+        if (parseContext.structQualifierErrorCheck($2.line, $1))
+            parseContext.recover();
+
+        if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $1))
+            parseContext.recover();
+
+        $$.type = $1;
+
+        if (parseContext.arrayTypeErrorCheck($3.line, $1) || parseContext.arrayQualifierErrorCheck($3.line, $1))
+            parseContext.recover();
+        else {
+            int size;
+            if (parseContext.arraySizeErrorCheck($3.line, $4, size))
+                parseContext.recover();
+
+            $1.setArray(true, size);
+            TVariable* variable;
+            if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable))
+                parseContext.recover();
+        }
+    }
+    | fully_specified_type IDENTIFIER EQUAL initializer {
+        if (parseContext.structQualifierErrorCheck($2.line, $1))
+            parseContext.recover();
+
+        $$.type = $1;
+
+	    TIntermNode* intermNode;
+        if (!parseContext.executeInitializer($2.line, *$2.string, $1, $4, intermNode)) {
+		//
+		// Build intermediate representation
+		//
+            if(intermNode)
+				$$.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, $3.line);
+            else
+				$$.intermAggregate = 0;
+        } else {
+			parseContext.recover();
+			$$.intermAggregate = 0;
+		}
+	}
+    | INVARIANT IDENTIFIER {
+		VERTEX_ONLY("invariant declaration", $1.line);
+		$$.qualifier = EvqInvariantVaryingOut;
+	    $$.intermAggregate = 0;
+    }
+
+//
+// Place holder for the pack/unpack languages.
+//
+//    | buffer_specifier {
+//        $$.intermAggregate = 0;
+//    }
+    ;
+
+// Grammar Note:  No 'enum', or 'typedef'.
+
+//
+// Place holder for the pack/unpack languages.
+//
+//%type <interm> buffer_declaration
+//%type <interm.type> buffer_specifier input_or_output buffer_declaration_list
+//buffer_specifier
+//    : input_or_output LEFT_BRACE buffer_declaration_list RIGHT_BRACE {
+//    }
+//    ;
+//
+//input_or_output
+//    : INPUT {
+//        if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "input"))
+//            parseContext.recover();
+//        UNPACK_ONLY("input", $1.line);
+//        $$.qualifier = EvqInput;
+//    }
+//    | OUTPUT {
+//        if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "output"))
+//            parseContext.recover();
+//        PACK_ONLY("output", $1.line);
+//        $$.qualifier = EvqOutput;
+//    }
+//    ;
+
+//
+// Place holder for the pack/unpack languages.
+//
+//buffer_declaration_list
+//    : buffer_declaration {
+//    }
+//    | buffer_declaration_list buffer_declaration {
+//    }
+//    ;
+
+//
+// Input/output semantics:
+//   float must be 16 or 32 bits
+//   float alignment restrictions?
+//   check for only one input and only one output
+//   sum of bitfields has to be multiple of 32
+//
+
+//
+// Place holder for the pack/unpack languages.
+//
+//buffer_declaration
+//    : type_specifier IDENTIFIER COLON constant_expression SEMICOLON {
+//        if (parseContext.reservedErrorCheck($2.line, *$2.string, parseContext))
+//            parseContext.recover();
+//        $$.variable = new TVariable($2.string, $1);
+//        if (! parseContext.symbolTable.insert(*$$.variable)) {
+//            parseContext.error($2.line, "redefinition", $$.variable->getName().c_str(), "");
+//            parseContext.recover();
+//            // don't have to delete $$.variable, the pool pop will take care of it
+//        }
+//    }
+//    ;
+
+fully_specified_type
+    : type_specifier {
+        $$ = $1;
+
+        if ($1.array) {
+            if (parseContext.extensionErrorCheck($1.line, "GL_3DL_array_objects")) {
+                parseContext.recover();
+                $1.setArray(false);
+            }
+        }
+    }
+    | type_qualifier type_specifier  {
+        if ($2.array && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects")) {
+            parseContext.recover();
+            $2.setArray(false);
+        }
+        if ($2.array && parseContext.arrayQualifierErrorCheck($2.line, $1)) {
+            parseContext.recover();
+            $2.setArray(false);
+        }
+
+        if ($1.qualifier == EvqAttribute &&
+            ($2.type == EbtBool || $2.type == EbtInt)) {
+            parseContext.error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), "");
+            parseContext.recover();
+        }
+        if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&
+            ($2.type == EbtBool || $2.type == EbtInt)) {
+            parseContext.error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), "");
+            parseContext.recover();
+        }
+        $$ = $2;
+        $$.qualifier = $1.qualifier;
+    }
+    ;
+
+type_qualifier
+    : CONST_QUAL {
+        $$.setBasic(EbtVoid, EvqConst, $1.line);
+    }
+    | ATTRIBUTE {
+        VERTEX_ONLY("attribute", $1.line);
+        if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "attribute"))
+            parseContext.recover();
+        $$.setBasic(EbtVoid, EvqAttribute, $1.line);
+    }
+    | VARYING {
+        if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "varying"))
+            parseContext.recover();
+        if (parseContext.language == EShLangVertex)
+            $$.setBasic(EbtVoid, EvqVaryingOut, $1.line);
+        else
+            $$.setBasic(EbtVoid, EvqVaryingIn, $1.line);
+    }
+    | INVARIANT VARYING {
+        if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "invariant varying"))
+            parseContext.recover();
+        if (parseContext.language == EShLangVertex)
+            $$.setBasic(EbtVoid, EvqInvariantVaryingOut, $1.line);
+        else
+            $$.setBasic(EbtVoid, EvqInvariantVaryingIn, $1.line);
+    }
+    | UNIFORM {
+        if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "uniform"))
+            parseContext.recover();
+        $$.setBasic(EbtVoid, EvqUniform, $1.line);
+    }
+    ;
+
+type_specifier
+    : type_specifier_no_prec {
+    	$$ = $1;
+    }
+    | precision_qualifier type_specifier_no_prec {
+    	$$ = $2;
+	$$.setPrecision($1);
+    }
+    ;
+
+precision_qualifier
+    : HIGH_PRECISION {
+    	$$ = EbpHigh;
+    }
+    | MEDIUM_PRECISION {
+    	$$ = EbpMedium;
+    }
+    | LOW_PRECISION  {
+    	$$ = EbpLow;
+    }
+    ;
+
+type_specifier_no_prec
+    : type_specifier_nonarray {
+        $$ = $1;
+    }
+    | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        $$ = $1;
+
+        if (parseContext.arrayTypeErrorCheck($2.line, $1))
+            parseContext.recover();
+        else {
+            int size;
+            if (parseContext.arraySizeErrorCheck($2.line, $3, size))
+                parseContext.recover();
+            $$.setArray(true, size);
+        }
+    }
+    ;
+
+type_specifier_nonarray
+    : VOID_TYPE {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtVoid, qual, $1.line);
+    }
+    | FLOAT_TYPE {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+    }
+    | INT_TYPE {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+    }
+    | BOOL_TYPE {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+    }
+//    | UNSIGNED INT_TYPE {
+//        PACK_UNPACK_ONLY("unsigned", $1.line);
+//        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+//        $$.setBasic(EbtInt, qual, $1.line);
+//    }
+    | VEC2 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | VEC3 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | VEC4 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | BVEC2 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | BVEC3 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | BVEC4 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | IVEC2 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | IVEC3 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | IVEC4 {
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | MATRIX2 {
+        FRAG_VERT_ONLY("mat2", $1.line);
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(2, true);
+    }
+    | MATRIX3 {
+        FRAG_VERT_ONLY("mat3", $1.line);
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(3, true);
+    }
+    | MATRIX4 {
+        FRAG_VERT_ONLY("mat4", $1.line);
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(4, true);
+    }
+    | SAMPLER2D {
+        FRAG_VERT_ONLY("sampler2D", $1.line);
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtSampler2D, qual, $1.line);
+    }
+    | SAMPLERCUBE {
+        FRAG_VERT_ONLY("samplerCube", $1.line);
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtSamplerCube, qual, $1.line);
+    }
+    | struct_specifier {
+        FRAG_VERT_ONLY("struct", $1.line);
+        $$ = $1;
+        $$.qualifier = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+    }
+    | TYPE_NAME {
+        //
+        // This is for user defined type names.  The lexical phase looked up the
+        // type.
+        //
+        TType& structure = static_cast<TVariable*>($1.symbol)->getType();
+        TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtStruct, qual, $1.line);
+        $$.userDef = &structure;
+    }
+    ;
+
+struct_specifier
+    : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE {
+        TType* structure = new TType($4, *$2.string);
+        TVariable* userTypeDef = new TVariable($2.string, *structure, true);
+        if (! parseContext.symbolTable.insert(*userTypeDef)) {
+            parseContext.error($2.line, "redefinition", $2.string->c_str(), "struct");
+            parseContext.recover();
+        }
+        $$.setBasic(EbtStruct, EvqTemporary, $1.line);
+        $$.userDef = structure;
+    }
+    | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE {
+        TType* structure = new TType($3, TString(""));
+        $$.setBasic(EbtStruct, EvqTemporary, $1.line);
+        $$.userDef = structure;
+    }
+    ;
+
+struct_declaration_list
+    : struct_declaration {
+        $$ = $1;
+    }
+    | struct_declaration_list struct_declaration {
+        $$ = $1;
+        for (unsigned int i = 0; i < $2->size(); ++i) {
+            for (unsigned int j = 0; j < $$->size(); ++j) {
+                if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) {
+                    parseContext.error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str());
+                    parseContext.recover();
+                }
+            }
+            $$->push_back((*$2)[i]);
+        }
+    }
+    ;
+
+struct_declaration
+    : type_specifier struct_declarator_list SEMICOLON {
+        $$ = $2;
+
+        if (parseContext.voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) {
+            parseContext.recover();
+        }
+        for (unsigned int i = 0; i < $$->size(); ++i) {
+            //
+            // Careful not to replace already know aspects of type, like array-ness
+            //
+            (*$$)[i].type->setType($1.type, $1.size, $1.matrix, $1.userDef);
+
+            // don't allow arrays of arrays
+            if ((*$$)[i].type->isArray()) {
+                if (parseContext.arrayTypeErrorCheck($1.line, $1))
+                    parseContext.recover();
+            }
+            if ($1.array)
+                (*$$)[i].type->setArraySize($1.arraySize);
+            if ($1.userDef)
+                (*$$)[i].type->setTypeName($1.userDef->getTypeName());
+        }
+    }
+    ;
+
+struct_declarator_list
+    : struct_declarator {
+        $$ = NewPoolTTypeList();
+        $$->push_back($1);
+    }
+    | struct_declarator_list COMMA struct_declarator {
+        $$->push_back($3);
+    }
+    ;
+
+struct_declarator
+    : IDENTIFIER {
+        $$.type = new TType(EbtVoid);
+        $$.line = $1.line;
+        $$.type->setFieldName(*$1.string);
+    }
+    | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        $$.type = new TType(EbtVoid);
+        $$.line = $1.line;
+        $$.type->setFieldName(*$1.string);
+
+        int size;
+        if (parseContext.arraySizeErrorCheck($2.line, $3, size))
+            parseContext.recover();
+        $$.type->setArraySize(size);
+    }
+    ;
+
+initializer
+    : assignment_expression { $$ = $1; }
+    ;
+
+declaration_statement
+    : declaration { $$ = $1; }
+    ;
+
+statement
+    : compound_statement  { $$ = $1; }
+    | simple_statement    { $$ = $1; }
+    ;
+
+// Grammar Note:  No labeled statements; 'goto' is not supported.
+
+simple_statement
+    : declaration_statement { $$ = $1; }
+    | expression_statement  { $$ = $1; }
+    | selection_statement   { $$ = $1; }
+    | iteration_statement   { $$ = $1; }
+    | jump_statement        { $$ = $1; }
+    ;
+
+compound_statement
+    : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
+    | LEFT_BRACE { parseContext.symbolTable.push(); } statement_list { parseContext.symbolTable.pop(); } RIGHT_BRACE {
+        if ($3 != 0)
+            $3->setOperator(EOpSequence);
+        $$ = $3;
+    }
+    ;
+
+statement_no_new_scope
+    : compound_statement_no_new_scope { $$ = $1; }
+    | simple_statement                { $$ = $1; }
+    ;
+
+compound_statement_no_new_scope
+    // Statement that doesn't create a new scope, for selection_statement, iteration_statement
+    : LEFT_BRACE RIGHT_BRACE {
+        $$ = 0;
+    }
+    | LEFT_BRACE statement_list RIGHT_BRACE {
+        if ($2)
+            $2->setOperator(EOpSequence);
+        $$ = $2;
+    }
+    ;
+
+statement_list
+    : statement {
+        $$ = parseContext.intermediate.makeAggregate($1, 0);
+    }
+    | statement_list statement {
+        $$ = parseContext.intermediate.growAggregate($1, $2, 0);
+    }
+    ;
+
+expression_statement
+    : SEMICOLON  { $$ = 0; }
+    | expression SEMICOLON  { $$ = static_cast<TIntermNode*>($1); }
+    ;
+
+selection_statement
+    : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
+        if (parseContext.boolErrorCheck($1.line, $3))
+            parseContext.recover();
+        $$ = parseContext.intermediate.addSelection($3, $5, $1.line);
+    }
+    ;
+
+selection_rest_statement
+    : statement ELSE statement {
+        $$.node1 = $1;
+        $$.node2 = $3;
+    }
+    | statement {
+        $$.node1 = $1;
+        $$.node2 = 0;
+    }
+    ;
+
+// Grammar Note:  No 'switch'.  Switch statements not supported.
+
+condition
+    // In 1996 c++ draft, conditions can include single declarations
+    : expression {
+        $$ = $1;
+        if (parseContext.boolErrorCheck($1->getLine(), $1))
+            parseContext.recover();
+    }
+    | fully_specified_type IDENTIFIER EQUAL initializer {
+        TIntermNode* intermNode;
+        if (parseContext.structQualifierErrorCheck($2.line, $1))
+            parseContext.recover();
+        if (parseContext.boolErrorCheck($2.line, $1))
+            parseContext.recover();
+
+        if (!parseContext.executeInitializer($2.line, *$2.string, $1, $4, intermNode))
+            $$ = $4;
+        else {
+            parseContext.recover();
+            $$ = 0;
+        }
+    }
+    ;
+
+iteration_statement
+    : WHILE LEFT_PAREN { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
+        parseContext.symbolTable.pop();
+        $$ = parseContext.intermediate.addLoop(0, $6, $4, 0, true, $1.line);
+        --parseContext.loopNestingLevel;
+    }
+    | DO { ++parseContext.loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
+        if (parseContext.boolErrorCheck($8.line, $6))
+            parseContext.recover();
+
+        $$ = parseContext.intermediate.addLoop(0, $3, $6, 0, false, $4.line);
+        --parseContext.loopNestingLevel;
+    }
+    | FOR LEFT_PAREN { parseContext.symbolTable.push(); ++parseContext.loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
+        parseContext.symbolTable.pop();
+        $$ = parseContext.intermediate.addLoop($4, $7, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), true, $1.line);
+        --parseContext.loopNestingLevel;
+    }
+    ;
+
+for_init_statement
+    : expression_statement {
+        $$ = $1;
+    }
+    | declaration_statement {
+        $$ = $1;
+    }
+    ;
+
+conditionopt
+    : condition {
+        $$ = $1;
+    }
+    | /* May be null */ {
+        $$ = 0;
+    }
+    ;
+
+for_rest_statement
+    : conditionopt SEMICOLON {
+        $$.node1 = $1;
+        $$.node2 = 0;
+    }
+    | conditionopt SEMICOLON expression  {
+        $$.node1 = $1;
+        $$.node2 = $3;
+    }
+    ;
+
+jump_statement
+    : CONTINUE SEMICOLON {
+        if (parseContext.loopNestingLevel <= 0) {
+            parseContext.error($1.line, "continue statement only allowed in loops", "", "");
+            parseContext.recover();
+        }
+        $$ = parseContext.intermediate.addBranch(EOpContinue, $1.line);
+    }
+    | BREAK SEMICOLON {
+        if (parseContext.loopNestingLevel <= 0) {
+            parseContext.error($1.line, "break statement only allowed in loops", "", "");
+            parseContext.recover();
+        }
+        $$ = parseContext.intermediate.addBranch(EOpBreak, $1.line);
+    }
+    | RETURN SEMICOLON {
+        $$ = parseContext.intermediate.addBranch(EOpReturn, $1.line);
+        if (parseContext.currentFunctionType->getBasicType() != EbtVoid) {
+            parseContext.error($1.line, "non-void function must return a value", "return", "");
+            parseContext.recover();
+        }
+    }
+    | RETURN expression SEMICOLON {
+        $$ = parseContext.intermediate.addBranch(EOpReturn, $2, $1.line);
+        parseContext.functionReturnsValue = true;
+        if (parseContext.currentFunctionType->getBasicType() == EbtVoid) {
+            parseContext.error($1.line, "void function cannot return a value", "return", "");
+            parseContext.recover();
+        } else if (*(parseContext.currentFunctionType) != $2->getType()) {
+            parseContext.error($1.line, "function return is not matching type:", "return", "");
+            parseContext.recover();
+        }
+    }
+    | DISCARD SEMICOLON {
+        FRAG_ONLY("discard", $1.line);
+        $$ = parseContext.intermediate.addBranch(EOpKill, $1.line);
+    }
+    ;
+
+// Grammar Note:  No 'goto'.  Gotos are not supported.
+
+translation_unit
+    : external_declaration {
+        $$ = $1;
+        parseContext.treeRoot = $$;
+    }
+    | translation_unit external_declaration {
+        $$ = parseContext.intermediate.growAggregate($1, $2, 0);
+        parseContext.treeRoot = $$;
+    }
+    ;
+
+external_declaration
+    : function_definition {
+        $$ = $1;
+    }
+    | declaration {
+        $$ = $1;
+    }
+    ;
+
+function_definition
+    : function_prototype {
+        TFunction& function = *($1.function);
+        TFunction* prevDec = static_cast<TFunction*>(parseContext.symbolTable.find(function.getMangledName()));
+        //
+        // Note:  'prevDec' could be 'function' if this is the first time we've seen function
+        // as it would have just been put in the symbol table.  Otherwise, we're looking up
+        // an earlier occurance.
+        //
+        if (prevDec->isDefined()) {
+            //
+            // Then this function already has a body.
+            //
+            parseContext.error($1.line, "function already has a body", function.getName().c_str(), "");
+            parseContext.recover();
+        }
+        prevDec->setDefined();
+
+        //
+        // Raise error message if main function takes any parameters or return anything other than void
+        //
+        if (function.getName() == "main") {
+            if (function.getParamCount() > 0) {
+                parseContext.error($1.line, "function cannot take any parameter(s)", function.getName().c_str(), "");
+                parseContext.recover();
+            }
+            if (function.getReturnType().getBasicType() != EbtVoid) {
+                parseContext.error($1.line, "", function.getReturnType().getBasicString(), "main function cannot return a value");
+                parseContext.recover();
+            }
+        }
+
+        //
+        // New symbol table scope for body of function plus its arguments
+        //
+        parseContext.symbolTable.push();
+
+        //
+        // Remember the return type for later checking for RETURN statements.
+        //
+        parseContext.currentFunctionType = &(prevDec->getReturnType());
+        parseContext.functionReturnsValue = false;
+
+        //
+        // Insert parameters into the symbol table.
+        // If the parameter has no name, it's not an error, just don't insert it
+        // (could be used for unused args).
+        //
+        // Also, accumulate the list of parameters into the HIL, so lower level code
+        // knows where to find parameters.
+        //
+        TIntermAggregate* paramNodes = new TIntermAggregate;
+        for (int i = 0; i < function.getParamCount(); i++) {
+            TParameter& param = function[i];
+            if (param.name != 0) {
+                TVariable *variable = new TVariable(param.name, *param.type);
+                //
+                // Insert the parameters with name in the symbol table.
+                //
+                if (! parseContext.symbolTable.insert(*variable)) {
+                    parseContext.error($1.line, "redefinition", variable->getName().c_str(), "");
+                    parseContext.recover();
+                    delete variable;
+                }
+                //
+                // Transfer ownership of name pointer to symbol table.
+                //
+                param.name = 0;
+
+                //
+                // Add the parameter to the HIL
+                //
+                paramNodes = parseContext.intermediate.growAggregate(
+                                               paramNodes,
+                                               parseContext.intermediate.addSymbol(variable->getUniqueId(),
+                                                                       variable->getName(),
+                                                                       variable->getType(), $1.line),
+                                               $1.line);
+            } else {
+                paramNodes = parseContext.intermediate.growAggregate(paramNodes, parseContext.intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
+            }
+        }
+        parseContext.intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line);
+        $1.intermAggregate = paramNodes;
+        parseContext.loopNestingLevel = 0;
+    }
+    compound_statement_no_new_scope {
+        //?? Check that all paths return a value if return type != void ?
+        //   May be best done as post process phase on intermediate code
+        if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) {
+            parseContext.error($1.line, "function does not return a value:", "", $1.function->getName().c_str());
+            parseContext.recover();
+        }
+        parseContext.symbolTable.pop();
+        $$ = parseContext.intermediate.growAggregate($1.intermAggregate, $3, 0);
+        parseContext.intermediate.setAggregateOperator($$, EOpFunction, $1.line);
+        $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
+        $$->getAsAggregate()->setType($1.function->getReturnType());
+
+        // store the pragma information for debug and optimize and other vendor specific
+        // information. This information can be queried from the parse tree
+        $$->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize);
+        $$->getAsAggregate()->setDebug(parseContext.contextPragma.debug);
+        $$->getAsAggregate()->addToPragmaTable(parseContext.contextPragma.pragmaTable);
+    }
+    ;
+
+%%
diff --git a/Compiler/intermOut.cpp b/Compiler/intermOut.cpp
new file mode 100644
index 0000000..6e30b86
--- /dev/null
+++ b/Compiler/intermOut.cpp
@@ -0,0 +1,455 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "localintermediate.h"
+
+//
+// Two purposes:
+// 1.  Show an example of how to iterate tree.  Functions can
+//     also directly call Traverse() on children themselves to
+//     have finer grained control over the process than shown here.
+//     See the last function for how to get started.
+// 2.  Print out a text based description of the tree.
+//
+
+//
+// Use this class to carry along data from node to node in
+// the traversal
+//
+class TOutputTraverser : public TIntermTraverser {
+public:
+	TOutputTraverser(TInfoSink& i) : infoSink(i) { }
+	TInfoSink& infoSink;
+
+protected:
+	void visitSymbol(TIntermSymbol*);
+	void visitConstantUnion(TIntermConstantUnion*);
+	bool visitBinary(Visit visit, TIntermBinary*);
+	bool visitUnary(Visit visit, TIntermUnary*);
+	bool visitSelection(Visit visit, TIntermSelection*);
+	bool visitAggregate(Visit visit, TIntermAggregate*);
+	bool visitLoop(Visit visit, TIntermLoop*);
+	bool visitBranch(Visit visit, TIntermBranch*);
+};
+
+TString TType::getCompleteString() const
+{
+	char buf[100];
+	char *p = &buf[0];
+
+	if (qualifier != EvqTemporary && qualifier != EvqGlobal)
+		p += sprintf(p, "%s ", getQualifierString());
+	if (array)
+		p += sprintf(p, "array of ");
+	if (matrix)
+		p += sprintf(p, "%dX%d matrix of ", size, size);
+	else if (size > 1)
+		p += sprintf(p, "%d-component vector of ", size);
+
+	sprintf(p, "%s", getBasicString());
+
+	return TString(buf);
+}   
+
+//
+// Helper functions for printing, not part of traversing.
+//
+
+void OutputTreeText(TInfoSink& infoSink, TIntermNode* node, const int depth)
+{
+	int i;
+
+	infoSink.debug << FormatSourceLoc(node->getLine());
+
+	for (i = 0; i < depth; ++i)
+		infoSink.debug << "  ";
+}
+
+//
+// The rest of the file are the traversal functions.  The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children.  If you process children yourself,
+// return false.
+//
+
+void TOutputTraverser::visitSymbol(TIntermSymbol* node)
+{
+	OutputTreeText(infoSink, node, depth);
+
+	char buf[100];
+	sprintf(buf, "'%s' (%s)\n",
+		   node->getSymbol().c_str(),
+		   node->getCompleteString().c_str());
+
+	infoSink.debug << buf;
+}
+
+bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node)
+{
+	TInfoSink& out = infoSink;
+
+	OutputTreeText(out, node, depth);
+
+	switch (node->getOp()) {
+	case EOpAssign:                   out.debug << "move second child to first child";           break;
+	case EOpAddAssign:                out.debug << "add second child into first child";          break;
+	case EOpSubAssign:                out.debug << "subtract second child into first child";     break;
+	case EOpMulAssign:                out.debug << "multiply second child into first child";     break;
+	case EOpVectorTimesMatrixAssign:  out.debug << "matrix mult second child into first child";  break;
+	case EOpVectorTimesScalarAssign:  out.debug << "vector scale second child into first child"; break;
+	case EOpMatrixTimesScalarAssign:  out.debug << "matrix scale second child into first child"; break;
+	case EOpMatrixTimesMatrixAssign:  out.debug << "matrix mult second child into first child"; break;
+	case EOpDivAssign:                out.debug << "divide second child into first child";       break;
+	case EOpModAssign:                out.debug << "mod second child into first child";          break;
+	case EOpAndAssign:                out.debug << "and second child into first child";          break;
+	case EOpInclusiveOrAssign:        out.debug << "or second child into first child";           break;
+	case EOpExclusiveOrAssign:        out.debug << "exclusive or second child into first child"; break;
+	case EOpLeftShiftAssign:          out.debug << "left shift second child into first child";   break;
+	case EOpRightShiftAssign:         out.debug << "right shift second child into first child";  break;
+
+	case EOpIndexDirect:   out.debug << "direct index";   break;
+	case EOpIndexIndirect: out.debug << "indirect index"; break;
+	case EOpIndexDirectStruct:   out.debug << "direct index for structure";   break;
+	case EOpVectorSwizzle: out.debug << "vector swizzle"; break;
+
+	case EOpAdd:    out.debug << "add";                     break;
+	case EOpSub:    out.debug << "subtract";                break;
+	case EOpMul:    out.debug << "component-wise multiply"; break;
+	case EOpDiv:    out.debug << "divide";                  break;
+	case EOpMod:    out.debug << "mod";                     break;
+	case EOpRightShift:  out.debug << "right-shift";  break;
+	case EOpLeftShift:   out.debug << "left-shift";   break;
+	case EOpAnd:         out.debug << "bitwise and";  break;
+	case EOpInclusiveOr: out.debug << "inclusive-or"; break;
+	case EOpExclusiveOr: out.debug << "exclusive-or"; break;
+	case EOpEqual:            out.debug << "Compare Equal";                 break;
+	case EOpNotEqual:         out.debug << "Compare Not Equal";             break;
+	case EOpLessThan:         out.debug << "Compare Less Than";             break;
+	case EOpGreaterThan:      out.debug << "Compare Greater Than";          break;
+	case EOpLessThanEqual:    out.debug << "Compare Less Than or Equal";    break;
+	case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
+
+	case EOpVectorTimesScalar: out.debug << "vector-scale";          break;
+	case EOpVectorTimesMatrix: out.debug << "vector-times-matrix";   break;
+	case EOpMatrixTimesVector: out.debug << "matrix-times-vector";   break;
+	case EOpMatrixTimesScalar: out.debug << "matrix-scale";          break;
+	case EOpMatrixTimesMatrix: out.debug << "matrix-multiply";       break;
+
+	case EOpLogicalOr:  out.debug << "logical-or";   break;
+	case EOpLogicalXor: out.debug << "logical-xor"; break;
+	case EOpLogicalAnd: out.debug << "logical-and"; break;
+	default: out.debug << "<unknown op>";
+	}
+
+	out.debug << " (" << node->getCompleteString() << ")";
+
+	out.debug << "\n";
+
+	return true;
+}
+
+bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node)
+{
+	TInfoSink& out = infoSink;
+
+	OutputTreeText(out, node, depth);
+
+	switch (node->getOp()) {
+	case EOpNegative:       out.debug << "Negate value";         break;
+	case EOpVectorLogicalNot:
+	case EOpLogicalNot:     out.debug << "Negate conditional";   break;
+	case EOpBitwiseNot:     out.debug << "Bitwise not";          break;
+
+	case EOpPostIncrement:  out.debug << "Post-Increment";       break;
+	case EOpPostDecrement:  out.debug << "Post-Decrement";       break;
+	case EOpPreIncrement:   out.debug << "Pre-Increment";        break;
+	case EOpPreDecrement:   out.debug << "Pre-Decrement";        break;
+
+	case EOpConvIntToBool:  out.debug << "Convert int to bool";  break;
+	case EOpConvFloatToBool:out.debug << "Convert float to bool";break;
+	case EOpConvBoolToFloat:out.debug << "Convert bool to float";break;
+	case EOpConvIntToFloat: out.debug << "Convert int to float"; break;
+	case EOpConvFloatToInt: out.debug << "Convert float to int"; break;
+	case EOpConvBoolToInt:  out.debug << "Convert bool to int";  break;
+
+	case EOpRadians:        out.debug << "radians";              break;
+	case EOpDegrees:        out.debug << "degrees";              break;
+	case EOpSin:            out.debug << "sine";                 break;
+	case EOpCos:            out.debug << "cosine";               break;
+	case EOpTan:            out.debug << "tangent";              break;
+	case EOpAsin:           out.debug << "arc sine";             break;
+	case EOpAcos:           out.debug << "arc cosine";           break;
+	case EOpAtan:           out.debug << "arc tangent";          break;
+
+	case EOpExp:            out.debug << "exp";                  break;
+	case EOpLog:            out.debug << "log";                  break;
+	case EOpExp2:           out.debug << "exp2";                 break;
+	case EOpLog2:           out.debug << "log2";                 break;
+	case EOpSqrt:           out.debug << "sqrt";                 break;
+	case EOpInverseSqrt:    out.debug << "inverse sqrt";         break;
+
+	case EOpAbs:            out.debug << "Absolute value";       break;
+	case EOpSign:           out.debug << "Sign";                 break;
+	case EOpFloor:          out.debug << "Floor";                break;
+	case EOpCeil:           out.debug << "Ceiling";              break;
+	case EOpFract:          out.debug << "Fraction";             break;
+
+	case EOpLength:         out.debug << "length";               break;
+	case EOpNormalize:      out.debug << "normalize";            break;
+//	case EOpDPdx:           out.debug << "dPdx";                 break;               
+//	case EOpDPdy:           out.debug << "dPdy";                 break;   
+//	case EOpFwidth:         out.debug << "fwidth";               break;                   
+
+	case EOpAny:            out.debug << "any";                  break;
+	case EOpAll:            out.debug << "all";                  break;
+
+	default: out.debug.message(EPrefixError, "Bad unary op");
+	}
+
+	out.debug << " (" << node->getCompleteString() << ")";
+
+	out.debug << "\n";
+
+	return true;
+}
+
+bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+	TInfoSink& out = infoSink;
+
+	if (node->getOp() == EOpNull) {
+		out.debug.message(EPrefixError, "node is still EOpNull!");
+		return true;
+	}
+
+	OutputTreeText(out, node, depth);
+
+	switch (node->getOp()) {
+	case EOpSequence:      out.debug << "Sequence\n"; return true;
+	case EOpComma:         out.debug << "Comma\n"; return true;
+	case EOpFunction:      out.debug << "Function Definition: " << node->getName(); break;
+	case EOpFunctionCall:  out.debug << "Function Call: " << node->getName(); break;
+	case EOpParameters:    out.debug << "Function Parameters: ";              break;
+
+	case EOpConstructFloat: out.debug << "Construct float"; break;
+	case EOpConstructVec2:  out.debug << "Construct vec2";  break;
+	case EOpConstructVec3:  out.debug << "Construct vec3";  break;
+	case EOpConstructVec4:  out.debug << "Construct vec4";  break;
+	case EOpConstructBool:  out.debug << "Construct bool";  break;
+	case EOpConstructBVec2: out.debug << "Construct bvec2"; break;
+	case EOpConstructBVec3: out.debug << "Construct bvec3"; break;
+	case EOpConstructBVec4: out.debug << "Construct bvec4"; break;
+	case EOpConstructInt:   out.debug << "Construct int";   break;
+	case EOpConstructIVec2: out.debug << "Construct ivec2"; break;
+	case EOpConstructIVec3: out.debug << "Construct ivec3"; break;
+	case EOpConstructIVec4: out.debug << "Construct ivec4"; break;
+	case EOpConstructMat2:  out.debug << "Construct mat2";  break;
+	case EOpConstructMat3:  out.debug << "Construct mat3";  break;
+	case EOpConstructMat4:  out.debug << "Construct mat4";  break;
+	case EOpConstructStruct:  out.debug << "Construct structure";  break;
+
+	case EOpLessThan:         out.debug << "Compare Less Than";             break;
+	case EOpGreaterThan:      out.debug << "Compare Greater Than";          break;
+	case EOpLessThanEqual:    out.debug << "Compare Less Than or Equal";    break;
+	case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
+	case EOpVectorEqual:      out.debug << "Equal";                         break;
+	case EOpVectorNotEqual:   out.debug << "NotEqual";                      break;
+
+	case EOpMod:           out.debug << "mod";         break;
+	case EOpPow:           out.debug << "pow";         break;
+
+	case EOpAtan:          out.debug << "arc tangent"; break;
+
+	case EOpMin:           out.debug << "min";         break;
+	case EOpMax:           out.debug << "max";         break;
+	case EOpClamp:         out.debug << "clamp";       break;
+	case EOpMix:           out.debug << "mix";         break;
+	case EOpStep:          out.debug << "step";        break;
+	case EOpSmoothStep:    out.debug << "smoothstep";  break;
+
+	case EOpDistance:      out.debug << "distance";                break;
+	case EOpDot:           out.debug << "dot-product";             break;
+	case EOpCross:         out.debug << "cross-product";           break;
+	case EOpFaceForward:   out.debug << "face-forward";            break;
+	case EOpReflect:       out.debug << "reflect";                 break;
+	case EOpRefract:       out.debug << "refract";                 break;
+	case EOpMul:           out.debug << "component-wise multiply"; break;
+
+	case EOpItof:          out.debug << "itof";        break;
+	case EOpFtoi:          out.debug << "ftoi";        break;
+	case EOpSkipPixels:    out.debug << "skipPixels";  break;
+	case EOpReadInput:     out.debug << "readInput";   break;
+	case EOpWritePixel:    out.debug << "writePixel";  break;
+	case EOpBitmapLsb:     out.debug << "bitmapLSB";   break;
+	case EOpBitmapMsb:     out.debug << "bitmapMSB";   break;
+	case EOpWriteOutput:   out.debug << "writeOutput"; break;
+	case EOpReadPixel:     out.debug << "readPixel";   break;
+
+	default: out.debug.message(EPrefixError, "Bad aggregation op");
+	}
+
+	if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
+		out.debug << " (" << node->getCompleteString() << ")";
+
+	out.debug << "\n";
+
+	return true;
+}
+
+bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node)
+{
+	TInfoSink& out = infoSink;
+
+	OutputTreeText(out, node, depth);
+
+	out.debug << "Test condition and select";
+	out.debug << " (" << node->getCompleteString() << ")\n";
+
+	++depth;
+
+	OutputTreeText(infoSink, node, depth);
+	out.debug << "Condition\n";
+	node->getCondition()->traverse(this);
+
+	OutputTreeText(infoSink, node, depth);
+	if (node->getTrueBlock()) {
+		out.debug << "true case\n";
+		node->getTrueBlock()->traverse(this);
+	} else
+		out.debug << "true case is null\n";
+
+	if (node->getFalseBlock()) {
+		OutputTreeText(infoSink, node, depth);
+		out.debug << "false case\n";
+		node->getFalseBlock()->traverse(this);
+	}
+
+	--depth;
+
+	return false;
+}
+
+void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+	TInfoSink& out = infoSink;
+
+	int size = node->getType().getObjectSize();
+
+	for (int i = 0; i < size; i++) {
+		OutputTreeText(out, node, depth);
+		switch (node->getUnionArrayPointer()[i].getType()) {
+		case EbtBool:
+			if (node->getUnionArrayPointer()[i].getBConst())
+				out.debug << "true";
+			else
+				out.debug << "false";
+
+			out.debug << " (" << "const bool" << ")";
+
+			out.debug << "\n";
+			break;
+		case EbtFloat:
+			{
+				char buf[300];
+				sprintf(buf, "%f (%s)", node->getUnionArrayPointer()[i].getFConst(), "const float");
+
+				out.debug << buf << "\n";
+			}
+			break;
+		case EbtInt:
+			{
+				char buf[300];
+				sprintf(buf, "%d (%s)", node->getUnionArrayPointer()[i].getIConst(), "const int");
+
+				out.debug << buf << "\n";
+				break;
+			}
+		default:
+			out.info.message(EPrefixInternalError, "Unknown constant", node->getLine());
+			break;
+		}
+	}
+}
+
+bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node)
+{
+	TInfoSink& out = infoSink;
+
+	OutputTreeText(out, node, depth);
+
+	out.debug << "Loop with condition ";
+	if (! node->testFirst())
+		out.debug << "not ";
+	out.debug << "tested first\n";
+
+	++depth;
+
+	OutputTreeText(infoSink, node, depth);
+	if (node->getTest()) {
+		out.debug << "Loop Condition\n";
+		node->getTest()->traverse(this);
+	} else
+		out.debug << "No loop condition\n";
+
+	OutputTreeText(infoSink, node, depth);
+	if (node->getBody()) {
+		out.debug << "Loop Body\n";
+		node->getBody()->traverse(this);
+	} else
+		out.debug << "No loop body\n";
+
+	if (node->getTerminal()) {
+		OutputTreeText(infoSink, node, depth);
+		out.debug << "Loop Terminal Expression\n";
+		node->getTerminal()->traverse(this);
+	}
+
+	--depth;
+
+	return false;
+}
+
+bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node)
+{
+	TInfoSink& out = infoSink;
+
+	OutputTreeText(out, node, depth);
+
+	switch (node->getFlowOp()) {
+	case EOpKill:      out.debug << "Branch: Kill";           break;
+	case EOpBreak:     out.debug << "Branch: Break";          break;
+	case EOpContinue:  out.debug << "Branch: Continue";       break;
+	case EOpReturn:    out.debug << "Branch: Return";         break;
+	default:           out.debug << "Branch: Unknown Branch"; break;
+	}
+
+	if (node->getExpression()) {
+		out.debug << " with expression\n";
+		++depth;
+		node->getExpression()->traverse(this);
+		--depth;
+	} else
+		out.debug << "\n";
+
+	return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node.  It's children will still be processed.
+//
+void TIntermediate::outputTree(TIntermNode* root)
+{
+	if (root == 0)
+		return;
+
+	TOutputTraverser it(infoSink);
+
+	root->traverse(&it);
+}
diff --git a/Compiler/intermediate.h b/Compiler/intermediate.h
new file mode 100644
index 0000000..f80691e
--- /dev/null
+++ b/Compiler/intermediate.h
@@ -0,0 +1,508 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Definition of the in-memory high-level intermediate representation
+// of shaders.  This is a tree that parser creates.
+//
+// Nodes in the tree are defined as a hierarchy of classes derived from 
+// TIntermNode. Each is a node in a tree.  There is no preset branching factor;
+// each node can have it's own type of list of children.
+//
+
+#ifndef __INTERMEDIATE_H
+#define __INTERMEDIATE_H
+
+#include "Common.h"
+#include "Types.h"
+#include "ConstantUnion.h"
+
+//
+// Operators used by the high-level (parse tree) representation.
+//
+enum TOperator {
+	EOpNull,            // if in a node, should only mean a node is still being built
+	EOpSequence,        // denotes a list of statements, or parameters, etc.
+	EOpFunctionCall,    
+	EOpFunction,        // For function definition
+	EOpParameters,      // an aggregate listing the parameters to a function
+	EOpDeclaration,
+
+	//
+	// Unary operators
+	//
+	
+	EOpNegative,
+	EOpLogicalNot,
+	EOpVectorLogicalNot,
+	EOpBitwiseNot,
+
+	EOpPostIncrement,
+	EOpPostDecrement,
+	EOpPreIncrement,
+	EOpPreDecrement,
+
+	EOpConvIntToBool,
+	EOpConvFloatToBool,
+	EOpConvBoolToFloat,
+	EOpConvIntToFloat,
+	EOpConvFloatToInt,
+	EOpConvBoolToInt,
+
+	//
+	// binary operations
+	//
+
+	EOpAdd,
+	EOpSub,
+	EOpMul,
+	EOpDiv,
+	EOpMod,
+	EOpRightShift,
+	EOpLeftShift,
+	EOpAnd,
+	EOpInclusiveOr,
+	EOpExclusiveOr,
+	EOpEqual,
+	EOpNotEqual,
+	EOpVectorEqual,
+	EOpVectorNotEqual,
+	EOpLessThan,
+	EOpGreaterThan,
+	EOpLessThanEqual,
+	EOpGreaterThanEqual,
+	EOpComma,
+
+	EOpVectorTimesScalar,
+	EOpVectorTimesMatrix,
+	EOpMatrixTimesVector,
+	EOpMatrixTimesScalar,
+
+	EOpLogicalOr,
+	EOpLogicalXor,
+	EOpLogicalAnd,
+
+	EOpIndexDirect,
+	EOpIndexIndirect,
+	EOpIndexDirectStruct,
+
+	EOpVectorSwizzle,
+
+	//
+	// Built-in functions potentially mapped to operators
+	//
+
+	EOpRadians,
+	EOpDegrees,
+	EOpSin,
+	EOpCos,
+	EOpTan,
+	EOpAsin,
+	EOpAcos,
+	EOpAtan,
+
+	EOpPow,
+	EOpExp,
+	EOpLog,
+	EOpExp2,
+	EOpLog2,
+	EOpSqrt,
+	EOpInverseSqrt,
+
+	EOpAbs,
+	EOpSign,
+	EOpFloor,
+	EOpCeil,
+	EOpFract,
+	EOpMin,
+	EOpMax,
+	EOpClamp,
+	EOpMix,
+	EOpStep,
+	EOpSmoothStep,
+
+	EOpLength,
+	EOpDistance,
+	EOpDot,
+	EOpCross,
+	EOpNormalize,
+	EOpFaceForward,
+	EOpReflect,
+	EOpRefract,
+
+//	EOpDPdx,            // Fragment only
+//	EOpDPdy,            // Fragment only
+//	EOpFwidth,          // Fragment only
+
+	EOpMatrixTimesMatrix,
+
+	EOpAny,
+	EOpAll,
+	
+	EOpItof,         // pack/unpack only
+	EOpFtoi,         // pack/unpack only    
+	EOpSkipPixels,   // pack/unpack only
+	EOpReadInput,    // unpack only
+	EOpWritePixel,   // unpack only
+	EOpBitmapLsb,    // unpack only
+	EOpBitmapMsb,    // unpack only
+	EOpWriteOutput,  // pack only
+	EOpReadPixel,    // pack only
+	
+	//
+	// Branch
+	//
+
+	EOpKill,            // Fragment only
+	EOpReturn,
+	EOpBreak,
+	EOpContinue,
+
+	//
+	// Constructors
+	//
+
+	EOpConstructInt,
+	EOpConstructBool,
+	EOpConstructFloat,
+	EOpConstructVec2,
+	EOpConstructVec3,
+	EOpConstructVec4,
+	EOpConstructBVec2,
+	EOpConstructBVec3,
+	EOpConstructBVec4,
+	EOpConstructIVec2,
+	EOpConstructIVec3,
+	EOpConstructIVec4,
+	EOpConstructMat2,
+	EOpConstructMat3,
+	EOpConstructMat4,
+	EOpConstructStruct,
+
+	//
+	// moves
+	//
+
+	EOpAssign,
+	EOpInitialize,
+	EOpAddAssign,
+	EOpSubAssign,
+	EOpMulAssign,
+	EOpVectorTimesMatrixAssign,
+	EOpVectorTimesScalarAssign,
+	EOpMatrixTimesScalarAssign,
+	EOpMatrixTimesMatrixAssign,
+	EOpDivAssign,
+	EOpModAssign,
+	EOpAndAssign,
+	EOpInclusiveOrAssign,
+	EOpExclusiveOrAssign,
+	EOpLeftShiftAssign,
+	EOpRightShiftAssign,
+
+	//
+	// Array operators
+	//
+
+	EOpArrayLength,
+};
+
+class TIntermTraverser;
+class TIntermAggregate;
+class TIntermBinary;
+class TIntermConstantUnion;
+class TIntermSelection;
+class TIntermTyped;
+class TIntermSymbol;
+class TInfoSink;
+
+//
+// Base class for the tree nodes
+//
+class TIntermNode {
+public:
+	POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+	TIntermNode() : line(0) {}
+	virtual TSourceLoc getLine() const { return line; }
+	virtual void setLine(TSourceLoc l) { line = l; }
+	virtual void traverse(TIntermTraverser*) = 0;
+	virtual TIntermTyped*     getAsTyped()         { return 0; }
+	virtual TIntermConstantUnion*     getAsConstantUnion()         { return 0; }
+	virtual TIntermAggregate* getAsAggregate()     { return 0; }
+	virtual TIntermBinary*    getAsBinaryNode()    { return 0; }
+	virtual TIntermSelection* getAsSelectionNode() { return 0; }
+	virtual TIntermSymbol*    getAsSymbolNode()    { return 0; }
+	virtual ~TIntermNode() { }
+protected:
+	TSourceLoc line;
+};
+
+//
+// This is just to help yacc.
+//
+struct TIntermNodePair {
+	TIntermNode* node1;
+	TIntermNode* node2;
+};
+
+class TIntermSymbol;
+class TIntermBinary;
+
+//
+// Intermediate class for nodes that have a type.
+//
+class TIntermTyped : public TIntermNode {
+public:
+	TIntermTyped(const TType& t) : type(t)  { }
+	virtual TIntermTyped* getAsTyped()         { return this; }
+	virtual void setType(const TType& t) { type = t; }
+	virtual TType getType() const { return type; }
+	virtual TType* getTypePointer() { return &type; }
+	
+	virtual TBasicType getBasicType() const { return type.getBasicType(); }
+	virtual TQualifier getQualifier() const { return type.getQualifier(); }
+	virtual int getNominalSize() const { return type.getNominalSize(); }
+	virtual int getSize() const { return type.getInstanceSize(); }
+	virtual bool isMatrix() const { return type.isMatrix(); }
+	virtual bool isArray()  const { return type.isArray(); }
+	virtual bool isVector() const { return type.isVector(); }
+	const char* getBasicString()      const { return type.getBasicString(); }
+	const char* getQualifierString()  const { return type.getQualifierString(); }
+	TString getCompleteString() const { return type.getCompleteString(); }
+
+protected:
+	TType type;
+};
+
+//
+// Handle for, do-while, and while loops.
+//
+class TIntermLoop : public TIntermNode {
+public:
+	TIntermLoop(TIntermNode *init, TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) : 
+	    init(init),
+		body(aBody),
+		test(aTest),
+		terminal(aTerminal),
+		first(testFirst) { }
+	virtual void traverse(TIntermTraverser*);
+	TIntermNode *getInit() { return init; }
+	TIntermNode *getBody() { return body; }
+	TIntermTyped *getTest() { return test; }
+	TIntermTyped *getTerminal() { return terminal; }
+	bool testFirst() { return first; }
+protected:
+	TIntermNode *init;
+	TIntermNode *body;       // code to loop over
+	TIntermTyped *test;      // exit condition associated with loop, could be 0 for 'for' loops
+	TIntermTyped *terminal;  // exists for for-loops
+	bool first;              // true for while and for, not for do-while
+};
+
+//
+// Handle break, continue, return, and kill.
+//
+class TIntermBranch : public TIntermNode {
+public:
+	TIntermBranch(TOperator op, TIntermTyped* e) :
+		flowOp(op),
+		expression(e) { }
+	virtual void traverse(TIntermTraverser*);
+	TOperator getFlowOp() { return flowOp; }
+	TIntermTyped* getExpression() { return expression; }
+protected:
+	TOperator flowOp;
+	TIntermTyped* expression;  // non-zero except for "return exp;" statements
+};
+
+//
+// Nodes that correspond to symbols or constants in the source code.
+//
+class TIntermSymbol : public TIntermTyped {
+public:
+	// if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
+	// per process globalpoolallocator, then it causes increased memory usage per compile
+	// it is essential to use "symbol = sym" to assign to symbol
+	TIntermSymbol(int i, const TString& sym, const TType& t) : 
+		TIntermTyped(t), id(i)  { symbol = sym;} 
+	virtual int getId() const { return id; }
+	virtual const TString& getSymbol() const { return symbol;  }
+	virtual void traverse(TIntermTraverser*);
+	virtual TIntermSymbol* getAsSymbolNode() { return this; }
+protected:
+	int id;
+	TString symbol;
+};
+
+class TIntermConstantUnion : public TIntermTyped {
+public:
+	TIntermConstantUnion(constUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
+	constUnion* getUnionArrayPointer() const { return unionArrayPointer; }
+	void setUnionArrayPointer(constUnion *c) { unionArrayPointer = c; }
+	virtual TIntermConstantUnion* getAsConstantUnion()  { return this; }
+	virtual void traverse(TIntermTraverser* );
+	virtual TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
+protected:
+	constUnion *unionArrayPointer;
+};
+
+//
+// Intermediate class for node types that hold operators.
+//
+class TIntermOperator : public TIntermTyped {
+public:
+	TOperator getOp() const { return op; }
+	bool modifiesState() const;
+	bool isConstructor() const;
+	virtual bool promote(TInfoSink&) { return true; }
+protected:
+	TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat)), op(o) {}
+	TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}   
+	TOperator op;
+};
+
+//
+// Nodes for all the basic binary math operators.
+//
+class TIntermBinary : public TIntermOperator {
+public:
+	TIntermBinary(TOperator o) : TIntermOperator(o) {}
+	virtual void traverse(TIntermTraverser*);
+	virtual void setLeft(TIntermTyped* n) { left = n; }
+	virtual void setRight(TIntermTyped* n) { right = n; }
+	virtual TIntermTyped* getLeft() const { return left; }
+	virtual TIntermTyped* getRight() const { return right; }
+	virtual TIntermBinary* getAsBinaryNode() { return this; }
+	virtual bool promote(TInfoSink&);
+protected:
+	TIntermTyped* left;
+	TIntermTyped* right;
+};
+
+//
+// Nodes for unary math operators.
+//
+class TIntermUnary : public TIntermOperator {
+public:
+	TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
+	TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
+	virtual void traverse(TIntermTraverser*);
+	virtual void setOperand(TIntermTyped* o) { operand = o; }
+	virtual TIntermTyped* getOperand() { return operand; }
+	virtual bool promote(TInfoSink&);
+protected:
+	TIntermTyped* operand;
+};
+
+typedef TVector<TIntermNode*> TIntermSequence;
+typedef TVector<int> TQualifierList;
+//
+// Nodes that operate on an arbitrary sized set of children.
+//
+class TIntermAggregate : public TIntermOperator {
+public:
+	TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { }
+	TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
+	~TIntermAggregate() { delete pragmaTable; }
+	virtual TIntermAggregate* getAsAggregate() { return this; }
+	virtual void setOperator(TOperator o) { op = o; }
+	virtual TIntermSequence& getSequence() { return sequence; }
+	virtual void setName(const TString& n) { name = n; }
+	virtual const TString& getName() const { return name; }
+	virtual void traverse(TIntermTraverser*);
+	virtual void setUserDefined() { userDefined = true; }
+	virtual bool isUserDefined() { return userDefined; }
+	virtual TQualifierList& getQualifier() { return qualifier; }
+	void setOptimize(bool o) { optimize = o; }
+	void setDebug(bool d) { debug = d; }
+	bool getOptimize() { return optimize; }
+	bool getDebug() { return debug; }
+	void addToPragmaTable(const TPragmaTable& pTable);
+	const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
+protected:
+	TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
+	TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
+	TIntermSequence sequence;
+	TQualifierList qualifier;
+	TString name;
+	bool userDefined; // used for user defined function names
+	bool optimize;
+	bool debug;
+	TPragmaTable *pragmaTable;
+};
+
+//
+// For if tests.  Simplified since there is no switch statement.
+//
+class TIntermSelection : public TIntermTyped {
+public:
+	TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
+		TIntermTyped(TType(EbtVoid)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
+	TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
+		TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
+	virtual void traverse(TIntermTraverser*);
+	virtual TIntermNode* getCondition() const { return condition; }
+	virtual TIntermNode* getTrueBlock() const { return trueBlock; }
+	virtual TIntermNode* getFalseBlock() const { return falseBlock; }
+	virtual TIntermSelection* getAsSelectionNode() { return this; }
+protected:
+	TIntermTyped* condition;
+	TIntermNode* trueBlock;
+	TIntermNode* falseBlock;
+};
+
+enum Visit
+{
+	PreVisit,
+	InVisit,
+	PostVisit
+};
+
+//
+// For traversing the tree.  User should derive from this, 
+// put their traversal specific data in it, and then pass
+// it to a Traverse method.
+//
+// When using this, just fill in the methods for nodes you want visited.
+// Return false from a pre-visit to skip visiting that node's subtree.
+//
+class TIntermTraverser
+{
+public:
+	POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+	TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : 
+		preVisit(preVisit),
+		inVisit(inVisit),
+		postVisit(postVisit),
+		rightToLeft(rightToLeft)
+	{
+		depth = 0;
+	}
+
+	virtual void visitSymbol(TIntermSymbol*) {}
+	virtual void visitConstantUnion(TIntermConstantUnion*) {}
+	virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
+	virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
+	virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
+	virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
+	virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
+	virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
+
+	void incrementDepth() {depth++;}
+	void decrementDepth() {depth--;}
+
+	const bool preVisit;
+	const bool inVisit;
+	const bool postVisit;
+	const bool rightToLeft;
+
+protected:
+	int depth;
+};
+
+#endif // __INTERMEDIATE_H
diff --git a/Compiler/localintermediate.h b/Compiler/localintermediate.h
new file mode 100644
index 0000000..b9cd3f2
--- /dev/null
+++ b/Compiler/localintermediate.h
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _LOCAL_INTERMEDIATE_INCLUDED_
+#define _LOCAL_INTERMEDIATE_INCLUDED_
+
+#include "intermediate.h"
+#include "ShaderLang.h"
+#include "SymbolTable.h"
+
+struct TVectorFields {
+    int offsets[4];
+    int num;
+};
+
+//
+// Set of helper functions to help parse and build the tree.
+//
+class TInfoSink;
+class TIntermediate {
+public:    
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+    TIntermediate(TInfoSink& i) : infoSink(i) { }
+    TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
+    TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
+    TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&);
+    TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
+    TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
+    TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&);
+    TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
+    TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);
+    TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, TSourceLoc);
+    TIntermNode*  addSelection(TIntermTyped* cond, TIntermNodePair code, TSourceLoc);
+    TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc);
+    TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc);
+    TIntermConstantUnion* addConstantUnion(constUnion*, const TType&, TSourceLoc);
+    TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
+    bool parseConstTree(TSourceLoc, TIntermNode*, constUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);        
+    TIntermNode* addLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc);
+    TIntermBranch* addBranch(TOperator, TSourceLoc);
+    TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
+    TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
+    bool postProcess(TIntermNode*, EShLanguage);
+	void remove(TIntermNode*);
+    void outputTree(TIntermNode*);
+    
+protected:
+    TInfoSink& infoSink;
+
+private:
+    void operator=(TIntermediate&); // prevent assignments
+};
+
+#endif // _LOCAL_INTERMEDIATE_INCLUDED_
diff --git a/Compiler/osinclude.h b/Compiler/osinclude.h
new file mode 100644
index 0000000..ddeb34e
--- /dev/null
+++ b/Compiler/osinclude.h
@@ -0,0 +1,41 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef __OSINCLUDE_H
+#define __OSINCLUDE_H
+
+//
+// This file contains contains the window's specific datatypes and
+// declares any windows specific functions.
+//
+
+#if !(defined(_WIN32) || defined(_WIN64))
+#error Trying to include a windows specific file in a non windows build.
+#endif
+
+#define STRICT
+#define VC_EXTRALEAN 1
+#include <windows.h>
+#include <assert.h>
+
+
+//
+// Thread Local Storage Operations
+//
+typedef DWORD OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES)
+
+OS_TLSIndex OS_AllocTLSIndex();
+bool        OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue);
+bool        OS_FreeTLSIndex(OS_TLSIndex nIndex);
+
+inline void* OS_GetTLSValue(OS_TLSIndex nIndex)
+{
+	assert(nIndex != OS_INVALID_TLS_INDEX);
+	return TlsGetValue(nIndex);
+}
+
+#endif // __OSINCLUDE_H
diff --git a/Compiler/ossource.cpp b/Compiler/ossource.cpp
new file mode 100644
index 0000000..ed93efe
--- /dev/null
+++ b/Compiler/ossource.cpp
@@ -0,0 +1,57 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "osinclude.h"
+//
+// This file contains contains the window's specific functions
+//
+
+#if !(defined(_WIN32) || defined(_WIN64))
+#error Trying to build a windows specific file in a non windows build.
+#endif
+
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+	DWORD dwIndex = TlsAlloc();
+	if (dwIndex == TLS_OUT_OF_INDEXES) {
+		assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+		return OS_INVALID_TLS_INDEX;
+	}
+
+	return dwIndex;
+}
+
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+	if (nIndex == OS_INVALID_TLS_INDEX) {
+		assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+		return false;
+	}
+
+	if (TlsSetValue(nIndex, lpvValue))
+		return true;
+	else
+		return false;
+}
+
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+	if (nIndex == OS_INVALID_TLS_INDEX) {
+		assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+		return false;
+	}
+
+	if (TlsFree(nIndex))
+		return true;
+	else
+		return false;
+}
diff --git a/Compiler/parseConst.cpp b/Compiler/parseConst.cpp
new file mode 100644
index 0000000..39606e9
--- /dev/null
+++ b/Compiler/parseConst.cpp
@@ -0,0 +1,227 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "ParseHelper.h"
+
+//
+// Use this class to carry along data from node to node in 
+// the traversal
+//
+class TConstTraverser : public TIntermTraverser {
+public:
+    TConstTraverser(constUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t) : unionArray(cUnion), type(t),
+        constructorType(constructType), singleConstantParam(singleConstParam), infoSink(sink), symbolTable(symTable), error(false), isMatrix(false), matrixSize(0)
+	{
+		index = 0;
+	}
+
+	bool error;
+
+protected:
+	void visitSymbol(TIntermSymbol*);
+	void visitConstantUnion(TIntermConstantUnion*);
+	bool visitBinary(Visit visit, TIntermBinary*);
+	bool visitUnary(Visit visit, TIntermUnary*);
+	bool visitSelection(Visit visit, TIntermSelection*);
+	bool visitAggregate(Visit visit, TIntermAggregate*);
+	bool visitLoop(Visit visit, TIntermLoop*);
+	bool visitBranch(Visit visit, TIntermBranch*);
+
+    int index;
+    constUnion *unionArray;
+    TType type;
+    TOperator constructorType;
+    bool singleConstantParam;
+    TInfoSink& infoSink;
+    TSymbolTable& symbolTable;
+    int size; // size of the constructor ( 4 for vec4)
+    bool isMatrix;
+    int matrixSize; // dimension of the matrix (nominal size and not the instance size)
+};
+
+//
+// The rest of the file are the traversal functions.  The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children.  If you process children yourself,
+// return false.
+//
+
+void TConstTraverser::visitSymbol(TIntermSymbol* node)
+{
+    infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
+    return;
+
+}
+
+bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
+{
+    TQualifier qualifier = node->getType().getQualifier();
+    
+    if (qualifier != EvqConst) {
+        char buf[200];
+        sprintf(buf, "'constructor' : assigning non-constant to %s", type.getCompleteString().c_str());
+        infoSink.info.message(EPrefixError, buf, node->getLine());
+        error = true;
+        return false;  
+    }
+
+   infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
+    
+    return false;
+}
+
+bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
+{
+    char buf[200];
+    sprintf(buf, "'constructor' : assigning non-constant to '%s'", type.getCompleteString().c_str());
+    infoSink.info.message(EPrefixError, buf, node->getLine());
+    error = true;
+    return false;  
+}
+
+bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    if (!node->isConstructor() && node->getOp() != EOpComma) {
+        char buf[200];
+        sprintf(buf, "'constructor' : assigning non-constant to '%s'", type.getCompleteString().c_str());
+        infoSink.info.message(EPrefixError, buf, node->getLine());
+        error = true;
+        return false;  
+    }
+
+    if (node->getSequence().size() == 0) {
+        error = true;
+        return false;
+    }
+
+    bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
+    if (flag) 
+    {
+        singleConstantParam = true; 
+        constructorType = node->getOp();
+        size = node->getType().getObjectSize();
+
+        if (node->getType().isMatrix()) {
+            isMatrix = true;
+            matrixSize = node->getType().getNominalSize();
+        }
+    }       
+
+    for (TIntermSequence::iterator p = node->getSequence().begin(); 
+                                   p != node->getSequence().end(); p++) {
+
+        if (node->getOp() == EOpComma)
+            index = 0;           
+
+        (*p)->traverse(this);
+    }   
+    if (flag) 
+    {
+        singleConstantParam = false;   
+        constructorType = EOpNull;
+        size = 0;
+        isMatrix = false;
+        matrixSize = 0;
+    }
+    return false;
+}
+
+bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
+{
+    infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
+    error = true;
+    return false;
+}
+
+void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+    constUnion* leftUnionArray = unionArray;
+    int instanceSize = type.getObjectSize();
+
+    if (index >= instanceSize)
+        return;
+
+    if (!singleConstantParam) {
+        int size = node->getType().getObjectSize();
+    
+        constUnion *rightUnionArray = node->getUnionArrayPointer();
+        for (int i=0; i < size; i++) {
+            if (index >= instanceSize)
+                return;
+            leftUnionArray[index] = rightUnionArray[i];
+
+            (index)++;
+        }
+    } else {
+        int totalSize = index + size;
+        constUnion *rightUnionArray = node->getUnionArrayPointer();
+        if (!isMatrix) {
+            int count = 0;
+            for (int i = index; i < totalSize; i++) {
+                if (i >= instanceSize)
+                    return;
+
+                leftUnionArray[i] = rightUnionArray[count];
+
+                (index)++;
+                
+                if (node->getType().getObjectSize() > 1)
+                    count++;
+            }
+        } else {  // for matrix constructors
+            int count = 0;
+            int element = index;
+            for (int i = index; i < totalSize; i++) {
+                if (i >= instanceSize)
+                    return;
+                if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
+                    leftUnionArray[i] = rightUnionArray[count];
+                else 
+                    leftUnionArray[i].setFConst(0.0f);
+
+                (element)++;
+
+                if (node->getType().getObjectSize() > 1)
+                    count++;                
+            }
+        }
+    }
+}
+
+bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
+{
+    infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
+    error = true;
+    return false;
+}
+
+bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
+{
+    infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
+    error = true;
+    return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node.  It's children will still be processed.
+//
+bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, constUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
+{
+    if (root == 0)
+        return false;
+
+    TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);
+
+    root->traverse(&it);
+    if (it.error)
+        return true;
+    else
+        return false;
+}
diff --git a/Compiler/unistd.h b/Compiler/unistd.h
new file mode 100644
index 0000000..c7c9147
--- /dev/null
+++ b/Compiler/unistd.h
@@ -0,0 +1 @@
+// This is a NULL file and is meant to be empty