Add SwiftShader source to repo

Oct 6 code drop from Transgaming
Review URL: https://chromereviews.googleplex.com/3846015
diff --git a/src/OpenGL ES 2.0/compiler/BaseTypes.h b/src/OpenGL ES 2.0/compiler/BaseTypes.h
new file mode 100644
index 0000000..9f4a860
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/BaseTypes.h
@@ -0,0 +1,147 @@
+//
+// 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
+{
+    // These need to be kept sorted
+    EbpUndefined,
+    EbpLow,
+    EbpMedium,
+    EbpHigh,
+};
+
+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 "mediump";   break;   // Safest fallback
+    }
+}
+
+//
+// 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 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";
+    }
+}
+
+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/src/OpenGL ES 2.0/compiler/CodeGenGLSL.cpp b/src/OpenGL ES 2.0/compiler/CodeGenGLSL.cpp
new file mode 100644
index 0000000..d140b37
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/CodeGenGLSL.cpp
@@ -0,0 +1,25 @@
+//
+// 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 "compiler/TranslatorGLSL.h"
+
+//
+// This function must be provided to create the actual
+// compile object used by higher level code.  It returns
+// a subclass of TCompiler.
+//
+TCompiler* ConstructCompiler(ShShaderType type, ShShaderSpec spec)
+{
+    return new TranslatorGLSL(type, spec);
+}
+
+//
+// Delete the compiler made by ConstructCompiler
+//
+void DeleteCompiler(TCompiler* compiler)
+{
+    delete compiler;
+}
diff --git a/src/OpenGL ES 2.0/compiler/CodeGenHLSL.cpp b/src/OpenGL ES 2.0/compiler/CodeGenHLSL.cpp
new file mode 100644
index 0000000..e04e789
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/CodeGenHLSL.cpp
@@ -0,0 +1,25 @@
+//
+// 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 "compiler/TranslatorHLSL.h"
+
+//
+// This function must be provided to create the actual
+// compile object used by higher level code.  It returns
+// a subclass of TCompiler.
+//
+TCompiler* ConstructCompiler(ShShaderType type, ShShaderSpec spec)
+{
+    return new TranslatorHLSL(type, spec);
+}
+
+//
+// Delete the compiler made by ConstructCompiler
+//
+void DeleteCompiler(TCompiler* compiler)
+{
+    delete compiler;
+}
diff --git a/src/OpenGL ES 2.0/compiler/Common.h b/src/OpenGL ES 2.0/compiler/Common.h
new file mode 100644
index 0000000..27a5598
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/Common.h
@@ -0,0 +1,89 @@
+//
+// 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_
+
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "compiler/PoolAlloc.h"
+
+// We need two pieces of information to report errors/warnings - string and
+// line number. We encode these into a single int so that it can be easily
+// incremented/decremented by lexer. The right SOURCE_LOC_LINE_SIZE bits store
+// line number while the rest store the string number. Since the shaders are
+// usually small, we should not run out of memory. SOURCE_LOC_LINE_SIZE
+// can be increased to alleviate this issue.
+typedef int TSourceLoc;
+const unsigned int SOURCE_LOC_LINE_SIZE = 16;  // in bits.
+const unsigned int SOURCE_LOC_LINE_MASK = (1 << SOURCE_LOC_LINE_SIZE) - 1;
+
+inline TSourceLoc EncodeSourceLoc(int string, int line) {
+    return (string << SOURCE_LOC_LINE_SIZE) | (line & SOURCE_LOC_LINE_MASK);
+}
+
+inline void DecodeSourceLoc(TSourceLoc loc, int* string, int* line) {
+    if (string) *string = loc >> SOURCE_LOC_LINE_SIZE;
+    if (line) *line = loc & SOURCE_LOC_LINE_MASK;
+}
+
+//
+// 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 *) { }
+
+//
+// Pool version of string.
+//
+typedef pool_allocator<char> TStringAllocator;
+typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TString;
+typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
+inline TString* NewPoolTString(const char* s)
+{
+	void* memory = GlobalPoolAllocator.allocate(sizeof(TString));
+	return new(memory) TString(s);
+}
+
+//
+// Persistent string memory.  Should only be used for strings that survive
+// across compiles.
+//
+#define TPersistString std::string
+#define TPersistStringStream std::ostringstream
+
+//
+// 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 K, class D, class CMP = std::less<K> > 
+class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D> > > {
+public:
+    typedef pool_allocator<std::pair<const K, D> > tAllocator;
+
+    TMap() : std::map<K, D, CMP, tAllocator>() {}
+    // use correct two-stage name lookup supported in gcc 3.4 and above
+    TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {}
+};
+
+#endif // _COMMON_INCLUDED_
diff --git a/src/OpenGL ES 2.0/compiler/Compiler.cpp b/src/OpenGL ES 2.0/compiler/Compiler.cpp
new file mode 100644
index 0000000..28bebef
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/Compiler.cpp
@@ -0,0 +1,240 @@
+//
+// Copyright (c) 2002-2011 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 "compiler/DetectRecursion.h"
+#include "compiler/Initialize.h"
+#include "compiler/ParseHelper.h"
+#include "compiler/ShHandle.h"
+#include "compiler/ValidateLimitations.h"
+#include "compiler/MapLongVariableNames.h"
+
+namespace {
+bool InitializeSymbolTable(
+    const TBuiltInStrings& builtInStrings,
+    ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
+    TInfoSink& infoSink, TSymbolTable& symbolTable)
+{
+    TIntermediate intermediate(infoSink);
+    TExtensionBehavior extBehavior;
+    TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, 0, NULL, infoSink);
+
+    GlobalParseContext = &parseContext;
+
+    assert(symbolTable.isEmpty());       
+    //
+    // 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();
+
+    for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
+    {
+        const char* builtInShaders = i->c_str();
+        int builtInLengths = static_cast<int>(i->size());
+        if (builtInLengths <= 0)
+          continue;
+
+        if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0)
+        {
+            infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
+            return false;
+        }
+    }
+
+    IdentifyBuiltIns(type, spec, resources, symbolTable);
+
+    return true;
+}
+
+class TScopedPoolAllocator {
+public:
+    TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
+        : mAllocator(allocator), mPushPopAllocator(pushPop) {
+        if (mPushPopAllocator) mAllocator->push();
+        SetGlobalPoolAllocator(mAllocator);
+    }
+    ~TScopedPoolAllocator() {
+        SetGlobalPoolAllocator(NULL);
+        if (mPushPopAllocator) mAllocator->pop();
+    }
+
+private:
+    TPoolAllocator* mAllocator;
+    bool mPushPopAllocator;
+};
+}  // namespace
+
+TShHandleBase::TShHandleBase() {
+    allocator.push();
+    SetGlobalPoolAllocator(&allocator);
+}
+
+TShHandleBase::~TShHandleBase() {
+    SetGlobalPoolAllocator(NULL);
+    allocator.popAll();
+}
+
+TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
+    : shaderType(type),
+      shaderSpec(spec) 
+{
+}
+
+TCompiler::~TCompiler()
+{
+}
+
+bool TCompiler::Init(const ShBuiltInResources& resources)
+{
+    TScopedPoolAllocator scopedAlloc(&allocator, false);
+
+    // Generate built-in symbol table.
+    if (!InitBuiltInSymbolTable(resources))
+        return false;
+    InitExtensionBehavior(resources, extensionBehavior);
+
+    return true;
+}
+
+bool TCompiler::compile(const char* const shaderStrings[],
+                        const int numStrings,
+                        int compileOptions)
+{
+    TScopedPoolAllocator scopedAlloc(&allocator, true);
+    clearResults();
+
+    if (numStrings == 0)
+        return true;
+
+    // If compiling for WebGL, validate loop and indexing as well.
+    if (shaderSpec == SH_WEBGL_SPEC)
+        compileOptions |= SH_VALIDATE_LOOP_INDEXING;
+
+    // First string is path of source file if flag is set. The actual source follows.
+    const char* sourcePath = NULL;
+    int firstSource = 0;
+    if (compileOptions & SH_SOURCE_PATH)
+    {
+        sourcePath = shaderStrings[0];
+        ++firstSource;
+    }
+
+    TIntermediate intermediate(infoSink);
+    TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
+                               shaderType, shaderSpec, compileOptions,
+                               sourcePath, infoSink);
+    GlobalParseContext = &parseContext;
+
+    // We preserve symbols at the built-in level from compile-to-compile.
+    // Start pushing the user-defined symbols at global level.
+    symbolTable.push();
+    if (!symbolTable.atGlobalLevel())
+        infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
+
+    // Parse shader.
+    bool success =
+        (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) &&
+        (parseContext.treeRoot != NULL);
+    if (success) {
+        TIntermNode* root = parseContext.treeRoot;
+        success = intermediate.postProcess(root);
+
+        if (success)
+            success = detectRecursion(root);
+
+        if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
+            success = validateLimitations(root);
+
+        // Call mapLongVariableNames() before collectAttribsUniforms() so in
+        // collectAttribsUniforms() we already have the mapped symbol names and
+        // we could composite mapped and original variable names.
+        if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES))
+            mapLongVariableNames(root);
+
+        if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS))
+            collectAttribsUniforms(root);
+
+        if (success && (compileOptions & SH_INTERMEDIATE_TREE))
+            intermediate.outputTree(root);
+
+        if (success && (compileOptions & SH_OBJECT_CODE))
+            translate(root);
+    }
+
+    // Cleanup memory.
+    intermediate.remove(parseContext.treeRoot);
+    // Ensure symbol table is returned to the built-in level,
+    // throwing away all but the built-ins.
+    while (!symbolTable.atBuiltInLevel())
+        symbolTable.pop();
+
+    return success;
+}
+
+bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
+{
+    TBuiltIns builtIns;
+
+    builtIns.initialize(shaderType, shaderSpec, resources);
+    return InitializeSymbolTable(builtIns.getBuiltInStrings(),
+        shaderType, shaderSpec, resources, infoSink, symbolTable);
+}
+
+void TCompiler::clearResults()
+{
+    infoSink.info.erase();
+    infoSink.obj.erase();
+    infoSink.debug.erase();
+
+    attribs.clear();
+    uniforms.clear();
+}
+
+bool TCompiler::detectRecursion(TIntermNode* root)
+{
+    DetectRecursion detect;
+    root->traverse(&detect);
+    switch (detect.detectRecursion()) {
+        case DetectRecursion::kErrorNone:
+            return true;
+        case DetectRecursion::kErrorMissingMain:
+            infoSink.info.message(EPrefixError, "Missing main()");
+            return false;
+        case DetectRecursion::kErrorRecursion:
+            infoSink.info.message(EPrefixError, "Function recursion detected");
+            return false;
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
+bool TCompiler::validateLimitations(TIntermNode* root) {
+    ValidateLimitations validate(shaderType, infoSink.info);
+    root->traverse(&validate);
+    return validate.numErrors() == 0;
+}
+
+void TCompiler::collectAttribsUniforms(TIntermNode* root)
+{
+    CollectAttribsUniforms collect(attribs, uniforms);
+    root->traverse(&collect);
+}
+
+void TCompiler::mapLongVariableNames(TIntermNode* root)
+{
+    MapLongVariableNames map(varyingLongNameMap);
+    root->traverse(&map);
+}
+
+int TCompiler::getMappedNameMaxLength() const
+{
+    return MAX_IDENTIFIER_NAME_SIZE + 1;
+}
diff --git a/src/OpenGL ES 2.0/compiler/ConstantUnion.h b/src/OpenGL ES 2.0/compiler/ConstantUnion.h
new file mode 100644
index 0000000..d28a11b
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/ConstantUnion.h
@@ -0,0 +1,258 @@
+//
+// 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_
+
+#include <assert.h>
+
+class ConstantUnion {
+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
+    {
+        return i == iConst;
+    }
+
+    bool operator==(const float f) const
+    {
+        return f == fConst;
+    }
+
+    bool operator==(const bool b) const
+    {
+        return b == bConst;
+    }
+
+    bool operator==(const ConstantUnion& constant) const
+    {
+        if (constant.type != type)
+            return false;
+
+        switch (type) {
+        case EbtInt:
+            return constant.iConst == iConst;
+        case EbtFloat:
+            return constant.fConst == fConst;
+        case EbtBool:
+            return constant.bConst == bConst;
+        default:
+            return false;
+        }
+
+        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 ConstantUnion& constant) const
+    {
+        return !operator==(constant);
+    }
+
+    bool operator>(const ConstantUnion& constant) const
+    { 
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:
+            return iConst > constant.iConst;
+        case EbtFloat:
+            return fConst > constant.fConst;
+        default:
+            return false;   // Invalid operation, handled at semantic analysis
+        }
+
+        return false;
+    }
+
+    bool operator<(const ConstantUnion& constant) const
+    { 
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:
+            return iConst < constant.iConst;
+        case EbtFloat:
+            return fConst < constant.fConst;
+        default:
+            return false;   // Invalid operation, handled at semantic analysis
+        }
+
+        return false;
+    }
+
+    ConstantUnion operator+(const ConstantUnion& constant) const
+    { 
+        ConstantUnion 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;
+    }
+
+    ConstantUnion operator-(const ConstantUnion& constant) const
+    { 
+        ConstantUnion 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;
+    }
+
+    ConstantUnion operator*(const ConstantUnion& constant) const
+    { 
+        ConstantUnion 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;
+    }
+
+    ConstantUnion operator%(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator>>(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator<<(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator&(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst & constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator|(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst | constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator^(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtInt:  returnValue.setIConst(iConst ^ constant.iConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator&&(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    ConstantUnion operator||(const ConstantUnion& constant) const
+    { 
+        ConstantUnion returnValue;
+        assert(type == constant.type);
+        switch (type) {
+        case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
+        default:     assert(false && "Default missing");
+        }
+
+        return returnValue;
+    }
+
+    TBasicType getType() const { 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/src/OpenGL ES 2.0/compiler/DetectRecursion.cpp b/src/OpenGL ES 2.0/compiler/DetectRecursion.cpp
new file mode 100644
index 0000000..b4354fc
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/DetectRecursion.cpp
@@ -0,0 +1,125 @@
+//
+// Copyright (c) 2002-2011 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 "compiler/DetectRecursion.h"
+
+DetectRecursion::FunctionNode::FunctionNode(const TString& fname)
+    : name(fname),
+      visit(PreVisit)
+{
+}
+
+const TString& DetectRecursion::FunctionNode::getName() const
+{
+    return name;
+}
+
+void DetectRecursion::FunctionNode::addCallee(
+    DetectRecursion::FunctionNode* callee)
+{
+    for (size_t i = 0; i < callees.size(); ++i) {
+        if (callees[i] == callee)
+            return;
+    }
+    callees.push_back(callee);
+}
+
+bool DetectRecursion::FunctionNode::detectRecursion()
+{
+    ASSERT(visit == PreVisit);
+    visit = InVisit;
+    for (size_t i = 0; i < callees.size(); ++i) {
+        switch (callees[i]->visit) {
+            case InVisit:
+                // cycle detected, i.e., recursion detected.
+                return true;
+            case PostVisit:
+                break;
+            case PreVisit: {
+                bool recursion = callees[i]->detectRecursion();
+                if (recursion)
+                    return true;
+                break;
+            }
+            default:
+                UNREACHABLE();
+                break;
+        }
+    }
+    visit = PostVisit;
+    return false;
+}
+
+DetectRecursion::DetectRecursion()
+    : currentFunction(NULL)
+{
+}
+
+DetectRecursion::~DetectRecursion()
+{
+    for (int i = 0; i < functions.size(); ++i)
+        delete functions[i];
+}
+
+bool DetectRecursion::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    switch (node->getOp())
+    {
+        case EOpPrototype:
+            // Function declaration.
+            // Don't add FunctionNode here because node->getName() is the
+            // unmangled function name.
+            break;
+        case EOpFunction: {
+            // Function definition.
+            if (visit == PreVisit) {
+                currentFunction = findFunctionByName(node->getName());
+                if (currentFunction == NULL) {
+                    currentFunction = new FunctionNode(node->getName());
+                    functions.push_back(currentFunction);
+                }
+            }
+            break;
+        }
+        case EOpFunctionCall: {
+            // Function call.
+            if (visit == PreVisit) {
+                ASSERT(currentFunction != NULL);
+                FunctionNode* func = findFunctionByName(node->getName());
+                if (func == NULL) {
+                    func = new FunctionNode(node->getName());
+                    functions.push_back(func);
+                }
+                currentFunction->addCallee(func);
+            }
+            break;
+        }
+        default:
+            break;
+    }
+    return true;
+}
+
+DetectRecursion::ErrorCode DetectRecursion::detectRecursion()
+{
+    FunctionNode* main = findFunctionByName("main(");
+    if (main == NULL)
+        return kErrorMissingMain;
+    if (main->detectRecursion())
+        return kErrorRecursion;
+    return kErrorNone;
+}
+
+DetectRecursion::FunctionNode* DetectRecursion::findFunctionByName(
+    const TString& name)
+{
+    for (size_t i = 0; i < functions.size(); ++i) {
+        if (functions[i]->getName() == name)
+            return functions[i];
+    }
+    return NULL;
+}
+
diff --git a/src/OpenGL ES 2.0/compiler/DetectRecursion.h b/src/OpenGL ES 2.0/compiler/DetectRecursion.h
new file mode 100644
index 0000000..bbac79d
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/DetectRecursion.h
@@ -0,0 +1,60 @@
+//
+// Copyright (c) 2002-2011 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_DETECT_RECURSION_H_
+#define COMPILER_DETECT_RECURSION_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/intermediate.h"
+#include "compiler/VariableInfo.h"
+
+// Traverses intermediate tree to detect function recursion.
+class DetectRecursion : public TIntermTraverser {
+public:
+    enum ErrorCode {
+        kErrorMissingMain,
+        kErrorRecursion,
+        kErrorNone
+    };
+
+    DetectRecursion();
+    ~DetectRecursion();
+
+    virtual bool visitAggregate(Visit, TIntermAggregate*);
+
+    ErrorCode detectRecursion();
+
+private:
+    class FunctionNode {
+    public:
+        FunctionNode(const TString& fname);
+
+        const TString& getName() const;
+
+        // If a function is already in the callee list, this becomes a no-op.
+        void addCallee(FunctionNode* callee);
+
+        // Return true if recursive function calls are detected.
+        bool detectRecursion();
+
+    private:
+        // mangled function name is unique.
+        TString name;
+
+        // functions that are directly called by this function.
+        TVector<FunctionNode*> callees;
+
+        Visit visit;
+    };
+
+    FunctionNode* findFunctionByName(const TString& name);
+
+    TVector<FunctionNode*> functions;
+    FunctionNode* currentFunction;
+};
+
+#endif  // COMPILER_DETECT_RECURSION_H_
diff --git a/src/OpenGL ES 2.0/compiler/ExtensionBehavior.h b/src/OpenGL ES 2.0/compiler/ExtensionBehavior.h
new file mode 100644
index 0000000..da96c24
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/ExtensionBehavior.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 _EXTENSION_BEHAVIOR_INCLUDED_
+#define _EXTENSION_BEHAVIOR_INCLUDED_
+
+#include "compiler/Common.h"
+
+typedef enum {
+    EBhRequire,
+    EBhEnable,
+    EBhWarn,
+    EBhDisable
+} TBehavior;
+
+typedef TMap<TString, TBehavior> TExtensionBehavior;
+
+#endif // _EXTENSION_TABLE_INCLUDED_
diff --git a/src/OpenGL ES 2.0/compiler/ForLoopUnroll.cpp b/src/OpenGL ES 2.0/compiler/ForLoopUnroll.cpp
new file mode 100644
index 0000000..d631af4
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/ForLoopUnroll.cpp
@@ -0,0 +1,172 @@
+//
+// Copyright (c) 2002-2011 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 "compiler/ForLoopUnroll.h"
+
+void ForLoopUnroll::FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info)
+{
+    ASSERT(node->getType() == ELoopFor);
+    ASSERT(node->getUnrollFlag());
+
+    TIntermNode* init = node->getInit();
+    ASSERT(init != NULL);
+    TIntermAggregate* decl = init->getAsAggregate();
+    ASSERT((decl != NULL) && (decl->getOp() == EOpDeclaration));
+    TIntermSequence& declSeq = decl->getSequence();
+    ASSERT(declSeq.size() == 1);
+    TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
+    ASSERT((declInit != NULL) && (declInit->getOp() == EOpInitialize));
+    TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
+    ASSERT(symbol != NULL);
+    ASSERT(symbol->getBasicType() == EbtInt);
+
+    info.id = symbol->getId();
+
+    ASSERT(declInit->getRight() != NULL);
+    TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion();
+    ASSERT(initNode != NULL);
+
+    info.initValue = evaluateIntConstant(initNode);
+    info.currentValue = info.initValue;
+
+    TIntermNode* cond = node->getCondition();
+    ASSERT(cond != NULL);
+    TIntermBinary* binOp = cond->getAsBinaryNode();
+    ASSERT(binOp != NULL);
+    ASSERT(binOp->getRight() != NULL);
+    ASSERT(binOp->getRight()->getAsConstantUnion() != NULL);
+
+    info.incrementValue = getLoopIncrement(node);
+    info.stopValue = evaluateIntConstant(
+        binOp->getRight()->getAsConstantUnion());
+    info.op = binOp->getOp();
+}
+
+void ForLoopUnroll::Step()
+{
+    ASSERT(mLoopIndexStack.size() > 0);
+    TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1];
+    info.currentValue += info.incrementValue;
+}
+
+bool ForLoopUnroll::SatisfiesLoopCondition()
+{
+    ASSERT(mLoopIndexStack.size() > 0);
+    TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1];
+    // Relational operator is one of: > >= < <= == or !=.
+    switch (info.op) {
+      case EOpEqual:
+        return (info.currentValue == info.stopValue);
+      case EOpNotEqual:
+        return (info.currentValue != info.stopValue);
+      case EOpLessThan:
+        return (info.currentValue < info.stopValue);
+      case EOpGreaterThan:
+        return (info.currentValue > info.stopValue);
+      case EOpLessThanEqual:
+        return (info.currentValue <= info.stopValue);
+      case EOpGreaterThanEqual:
+        return (info.currentValue >= info.stopValue);
+      default:
+        UNREACHABLE();
+    }
+    return false;
+}
+
+bool ForLoopUnroll::NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol)
+{
+    for (TVector<TLoopIndexInfo>::iterator i = mLoopIndexStack.begin();
+         i != mLoopIndexStack.end();
+         ++i) {
+        if (i->id == symbol->getId())
+            return true;
+    }
+    return false;
+}
+
+int ForLoopUnroll::GetLoopIndexValue(TIntermSymbol* symbol)
+{
+    for (TVector<TLoopIndexInfo>::iterator i = mLoopIndexStack.begin();
+         i != mLoopIndexStack.end();
+         ++i) {
+        if (i->id == symbol->getId())
+            return i->currentValue;
+    }
+    UNREACHABLE();
+    return false;
+}
+
+void ForLoopUnroll::Push(TLoopIndexInfo& info)
+{
+    mLoopIndexStack.push_back(info);
+}
+
+void ForLoopUnroll::Pop()
+{
+    mLoopIndexStack.pop_back();
+}
+
+int ForLoopUnroll::getLoopIncrement(TIntermLoop* node)
+{
+    TIntermNode* expr = node->getExpression();
+    ASSERT(expr != NULL);
+    // for expression has one of the following forms:
+    //     loop_index++
+    //     loop_index--
+    //     loop_index += constant_expression
+    //     loop_index -= constant_expression
+    //     ++loop_index
+    //     --loop_index
+    // The last two forms are not specified in the spec, but I am assuming
+    // its an oversight.
+    TIntermUnary* unOp = expr->getAsUnaryNode();
+    TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode();
+
+    TOperator op = EOpNull;
+    TIntermConstantUnion* incrementNode = NULL;
+    if (unOp != NULL) {
+        op = unOp->getOp();
+    } else if (binOp != NULL) {
+        op = binOp->getOp();
+        ASSERT(binOp->getRight() != NULL);
+        incrementNode = binOp->getRight()->getAsConstantUnion();
+        ASSERT(incrementNode != NULL);
+    }
+
+    int increment = 0;
+    // The operator is one of: ++ -- += -=.
+    switch (op) {
+        case EOpPostIncrement:
+        case EOpPreIncrement:
+            ASSERT((unOp != NULL) && (binOp == NULL));
+            increment = 1;
+            break;
+        case EOpPostDecrement:
+        case EOpPreDecrement:
+            ASSERT((unOp != NULL) && (binOp == NULL));
+            increment = -1;
+            break;
+        case EOpAddAssign:
+            ASSERT((unOp == NULL) && (binOp != NULL));
+            increment = evaluateIntConstant(incrementNode);
+            break;
+        case EOpSubAssign:
+            ASSERT((unOp == NULL) && (binOp != NULL));
+            increment = - evaluateIntConstant(incrementNode);
+            break;
+        default:
+            ASSERT(false);
+    }
+
+    return increment;
+}
+
+int ForLoopUnroll::evaluateIntConstant(TIntermConstantUnion* node)
+{
+    ASSERT((node != NULL) && (node->getUnionArrayPointer() != NULL));
+    return node->getUnionArrayPointer()->getIConst();
+}
+
diff --git a/src/OpenGL ES 2.0/compiler/ForLoopUnroll.h b/src/OpenGL ES 2.0/compiler/ForLoopUnroll.h
new file mode 100644
index 0000000..b2b2b58
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/ForLoopUnroll.h
@@ -0,0 +1,46 @@
+//
+// Copyright (c) 2011 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 "compiler/intermediate.h"
+
+struct TLoopIndexInfo {
+    int id;
+    int initValue;
+    int stopValue;
+    int incrementValue;
+    TOperator op;
+    int currentValue;
+};
+
+class ForLoopUnroll {
+public:
+    ForLoopUnroll() { }
+
+    void FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info);
+
+    // Update the info.currentValue for the next loop iteration.
+    void Step();
+
+    // Return false if loop condition is no longer satisfied.
+    bool SatisfiesLoopCondition();
+
+    // Check if the symbol is the index of a loop that's unrolled.
+    bool NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol);
+
+    // Return the current value of a given loop index symbol.
+    int GetLoopIndexValue(TIntermSymbol* symbol);
+
+    void Push(TLoopIndexInfo& info);
+    void Pop();
+
+private:
+    int getLoopIncrement(TIntermLoop* node);
+
+    int evaluateIntConstant(TIntermConstantUnion* node);
+
+    TVector<TLoopIndexInfo> mLoopIndexStack;
+};
+
diff --git a/src/OpenGL ES 2.0/compiler/InfoSink.cpp b/src/OpenGL ES 2.0/compiler/InfoSink.cpp
new file mode 100644
index 0000000..ba32f78
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/InfoSink.cpp
@@ -0,0 +1,59 @@
+//
+// 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 "compiler/InfoSink.h"
+
+void TInfoSinkBase::prefix(TPrefixType message) {
+    switch(message) {
+        case EPrefixNone:
+            break;
+        case EPrefixWarning:
+            sink.append("WARNING: ");
+            break;
+        case EPrefixError:
+            sink.append("ERROR: ");
+            break;
+        case EPrefixInternalError:
+            sink.append("INTERNAL ERROR: ");
+            break;
+        case EPrefixUnimplemented:
+            sink.append("UNIMPLEMENTED: ");
+            break;
+        case EPrefixNote:
+            sink.append("NOTE: ");
+            break;
+        default:
+            sink.append("UNKOWN ERROR: ");
+            break;
+    }
+}
+
+void TInfoSinkBase::location(TSourceLoc loc) {
+    int string = 0, line = 0;
+    DecodeSourceLoc(loc, &string, &line);
+
+    TPersistStringStream stream;
+    if (line)
+        stream << string << ":" << line;
+    else
+        stream << string << ":? ";
+    stream << ": ";
+
+    sink.append(stream.str());
+}
+
+void TInfoSinkBase::message(TPrefixType message, const char* s) {
+    prefix(message);
+    sink.append(s);
+    sink.append("\n");
+}
+
+void TInfoSinkBase::message(TPrefixType message, const char* s, TSourceLoc loc) {
+    prefix(message);
+    location(loc);
+    sink.append(s);
+    sink.append("\n");
+}
diff --git a/src/OpenGL ES 2.0/compiler/InfoSink.h b/src/OpenGL ES 2.0/compiler/InfoSink.h
new file mode 100644
index 0000000..e2224e918
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/InfoSink.h
@@ -0,0 +1,115 @@
+//
+// 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 <math.h>
+#include "compiler/Common.h"
+
+// Returns the fractional part of the given floating-point number.
+inline float fractionalPart(float f) {
+  float intPart = 0.0f;
+  return modff(f, &intPart);
+}
+
+//
+// TPrefixType is used to centralize how info log messages start.
+// See below.
+//
+enum TPrefixType {
+    EPrefixNone,
+    EPrefixWarning,
+    EPrefixError,
+    EPrefixInternalError,
+    EPrefixUnimplemented,
+    EPrefixNote
+};
+
+//
+// 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() {}
+
+    template <typename T>
+    TInfoSinkBase& operator<<(const T& t) {
+        TPersistStringStream stream;
+        stream << t;
+        sink.append(stream.str());
+        return *this;
+    }
+    // Override << operator for specific types. It is faster to append strings
+    // and characters directly to the sink.
+    TInfoSinkBase& operator<<(char c) {
+        sink.append(1, c);
+        return *this;
+    }
+    TInfoSinkBase& operator<<(const char* str) {
+        sink.append(str);
+        return *this;
+    }
+    TInfoSinkBase& operator<<(const TPersistString& str) {
+        sink.append(str);
+        return *this;
+    }
+    TInfoSinkBase& operator<<(const TString& str) {
+        sink.append(str.c_str());
+        return *this;
+    }
+    // Make sure floats are written with correct precision.
+    TInfoSinkBase& operator<<(float f) {
+        // Make sure that at least one decimal point is written. If a number
+        // does not have a fractional part, the default precision format does
+        // not write the decimal portion which gets interpreted as integer by
+        // the compiler.
+        TPersistStringStream stream;
+        if (fractionalPart(f) == 0.0f) {
+            stream.precision(1);
+            stream << std::showpoint << std::fixed << f;
+        } else {
+            stream.unsetf(std::ios::fixed);
+            stream.unsetf(std::ios::scientific);
+            stream.precision(8);
+            stream << f;
+        }
+        sink.append(stream.str());
+        return *this;
+    }
+    // Write boolean values as their names instead of integral value.
+    TInfoSinkBase& operator<<(bool b) {
+        const char* str = b ? "true" : "false";
+        sink.append(str);
+        return *this;
+    }
+
+    void erase() { sink.clear(); }
+    int size() { return static_cast<int>(sink.size()); }
+
+    const TPersistString& str() const { return sink; }
+    const char* c_str() const { return sink.c_str(); }
+
+    void prefix(TPrefixType message);
+    void location(TSourceLoc loc);
+    void message(TPrefixType message, const char* s);
+    void message(TPrefixType message, const char* s, TSourceLoc loc);
+
+private:
+    TPersistString sink;
+};
+
+class TInfoSink {
+public:
+    TInfoSinkBase info;
+    TInfoSinkBase debug;
+    TInfoSinkBase obj;
+};
+
+#endif // _INFOSINK_INCLUDED_
diff --git a/src/OpenGL ES 2.0/compiler/Initialize.cpp b/src/OpenGL ES 2.0/compiler/Initialize.cpp
new file mode 100644
index 0000000..74a2de3
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/Initialize.cpp
@@ -0,0 +1,629 @@
+//
+// 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 "compiler/Initialize.h"
+
+#include "compiler/intermediate.h"
+
+//============================================================================
+//
+// Prototypes for built-in functions seen by both vertex and fragment shaders.
+//
+//============================================================================
+static TString BuiltInFunctionsCommon()
+{
+    TString s;
+
+    //
+    // 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);"));
+
+    //
+    // 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);"));
+
+    return s;
+}
+
+//============================================================================
+//
+// Prototypes for built-in functions seen by vertex shaders only.
+//
+//============================================================================
+static TString BuiltInFunctionsVertex(const ShBuiltInResources& resources)
+{
+    TString s;
+
+    //
+    // Geometric Functions.
+    //
+    //s.append(TString("vec4 ftransform();"));
+
+    //
+    // 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);"));
+
+    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);"));
+
+    return s;
+}
+
+//============================================================================
+//
+// Prototypes for built-in functions seen by fragment shaders only.
+//
+//============================================================================
+static TString BuiltInFunctionsFragment(const ShBuiltInResources& resources)
+{
+    TString s;
+
+    //
+    // 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);"));
+
+    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);"));
+
+    if (resources.OES_standard_derivatives) {
+        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);"));
+    }
+
+    return s;
+}
+
+//============================================================================
+//
+// Standard uniforms.
+//
+//============================================================================
+static TString StandardUniforms()
+{
+    TString s;
+
+    //
+    // Depth range in window coordinates
+    //
+    s.append(TString("struct gl_DepthRangeParameters {"));
+    s.append(TString("    highp float near;"));        // n
+    s.append(TString("    highp float far;"));         // f
+    s.append(TString("    highp float diff;"));        // f - n
+    s.append(TString("};"));
+    s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;"));
+
+    return s;
+}
+
+//============================================================================
+//
+// Default precision for vertex shaders.
+//
+//============================================================================
+static TString DefaultPrecisionVertex()
+{
+    TString s;
+
+    s.append(TString("precision highp int;"));
+    s.append(TString("precision highp float;"));
+
+    return s;
+}
+
+//============================================================================
+//
+// Default precision for fragment shaders.
+//
+//============================================================================
+static TString DefaultPrecisionFragment()
+{
+    TString s;
+
+    s.append(TString("precision mediump int;"));
+    // No default precision for float in fragment shaders
+
+    return s;
+}
+
+//============================================================================
+//
+// Implementation dependent built-in constants.
+//
+//============================================================================
+static TString BuiltInConstants(const ShBuiltInResources &resources)
+{
+    TStringStream s;
+
+    s << "const int gl_MaxVertexAttribs = " << resources.MaxVertexAttribs << ";";
+    s << "const int gl_MaxVertexUniformVectors = " << resources.MaxVertexUniformVectors << ";";
+
+    s << "const int gl_MaxVaryingVectors = " << resources.MaxVaryingVectors << ";";
+    s << "const int gl_MaxVertexTextureImageUnits = " << resources.MaxVertexTextureImageUnits << ";";
+    s << "const int gl_MaxCombinedTextureImageUnits = " << resources.MaxCombinedTextureImageUnits << ";";
+    s << "const int gl_MaxTextureImageUnits = " << resources.MaxTextureImageUnits << ";";
+    s << "const int gl_MaxFragmentUniformVectors = " << resources.MaxFragmentUniformVectors << ";";
+    s << "const int gl_MaxDrawBuffers = " << resources.MaxDrawBuffers << ";";
+
+    return s.str();
+}
+
+void TBuiltIns::initialize(ShShaderType type, ShShaderSpec spec,
+                           const ShBuiltInResources& resources)
+{
+    switch (type) {
+    case SH_FRAGMENT_SHADER:
+        builtInStrings.push_back(DefaultPrecisionFragment());
+        builtInStrings.push_back(BuiltInFunctionsCommon());
+        builtInStrings.push_back(BuiltInFunctionsFragment(resources));
+        builtInStrings.push_back(StandardUniforms());
+        break;
+
+    case SH_VERTEX_SHADER:
+        builtInStrings.push_back(DefaultPrecisionVertex());
+        builtInStrings.push_back(BuiltInFunctionsCommon());
+        builtInStrings.push_back(BuiltInFunctionsVertex(resources));
+        builtInStrings.push_back(StandardUniforms());
+        break;
+
+    default: assert(false && "Language not supported");
+    }
+
+    builtInStrings.push_back(BuiltInConstants(resources));
+}
+
+void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
+                      const ShBuiltInResources& resources,
+                      TSymbolTable& symbolTable)
+{
+    //
+    // First, insert some special built-in variables that are not in 
+    // the built-in header files.
+    //
+    switch(type) {
+    case SH_FRAGMENT_SHADER:
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"),                   TType(EbtFloat, EbpMedium, EvqFragCoord,   4)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"),                 TType(EbtBool,  EbpUndefined, EvqFrontFacing, 1)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"),                   TType(EbtFloat, EbpMedium, EvqFragColor,   4)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData,    4)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"),                  TType(EbtFloat, EbpMedium, EvqPointCoord,  2)));
+        break;
+
+    case SH_VERTEX_SHADER:
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"),    TType(EbtFloat, EbpHigh, EvqPosition,    4)));
+        symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"),   TType(EbtFloat, EbpMedium, EvqPointSize,   1)));
+        break;
+
+    default: assert(false && "Language not supported");
+    }
+
+    //
+    // 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("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("mod",          EOpMod);
+    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("faceforward",  EOpFaceForward);
+    symbolTable.relateToOperator("reflect",      EOpReflect);
+    symbolTable.relateToOperator("refract",      EOpRefract);
+    
+    symbolTable.relateToOperator("any",          EOpAny);
+    symbolTable.relateToOperator("all",          EOpAll);
+
+    // Map language-specific operators.
+    switch(type) {
+    case SH_VERTEX_SHADER:
+        break;
+    case SH_FRAGMENT_SHADER:
+        if (resources.OES_standard_derivatives) {
+            symbolTable.relateToOperator("dFdx",   EOpDFdx);
+            symbolTable.relateToOperator("dFdy",   EOpDFdy);
+            symbolTable.relateToOperator("fwidth", EOpFwidth);
+
+            symbolTable.relateToExtension("dFdx", "GL_OES_standard_derivatives");
+            symbolTable.relateToExtension("dFdy", "GL_OES_standard_derivatives");
+            symbolTable.relateToExtension("fwidth", "GL_OES_standard_derivatives");
+        }
+        break;
+    default: break;
+    }
+
+    // Finally add resource-specific variables.
+    switch(type) {
+    case SH_FRAGMENT_SHADER: {
+            // Set up gl_FragData.  The array size.
+            TType fragData(EbtFloat, EbpMedium, EvqFragColor,   4, false, true);
+            fragData.setArraySize(resources.MaxDrawBuffers);
+            symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"),    fragData));
+        }
+        break;
+    default: break;
+    }
+}
+
+void InitExtensionBehavior(const ShBuiltInResources& resources,
+                           TExtensionBehavior& extBehavior)
+{
+    if (resources.OES_standard_derivatives)
+        extBehavior["GL_OES_standard_derivatives"] = EBhDisable;
+}
diff --git a/src/OpenGL ES 2.0/compiler/Initialize.h b/src/OpenGL ES 2.0/compiler/Initialize.h
new file mode 100644
index 0000000..8b0adc6
--- /dev/null
+++ b/src/OpenGL ES 2.0/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 "compiler/Common.h"
+#include "compiler/ShHandle.h"
+#include "compiler/SymbolTable.h"
+
+typedef TVector<TString> TBuiltInStrings;
+
+class TBuiltIns {
+public:
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+    void initialize(ShShaderType type, ShShaderSpec spec,
+                    const ShBuiltInResources& resources);
+    const TBuiltInStrings& getBuiltInStrings() { return builtInStrings; }
+
+protected:
+    TBuiltInStrings builtInStrings;
+};
+
+void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
+                      const ShBuiltInResources& resources,
+                      TSymbolTable& symbolTable);
+
+void InitExtensionBehavior(const ShBuiltInResources& resources,
+                           TExtensionBehavior& extensionBehavior);
+
+#endif // _INITIALIZE_INCLUDED_
diff --git a/src/OpenGL ES 2.0/compiler/InitializeDll.cpp b/src/OpenGL ES 2.0/compiler/InitializeDll.cpp
new file mode 100644
index 0000000..8763cfe
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/InitializeDll.cpp
@@ -0,0 +1,115 @@
+//
+// 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 "compiler/InitializeDll.h"
+
+#include "compiler/InitializeGlobals.h"
+#include "compiler/InitializeParseContext.h"
+#include "compiler/osinclude.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;
+    }
+
+    return InitThread();
+}
+
+bool DetachProcess()
+{
+    bool success = true;
+
+    if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
+        return true;
+
+    success = DetachThread();
+
+    if (!FreeParseContextIndex())
+        success = false;
+
+    FreePoolIndex();
+
+    OS_FreeTLSIndex(ThreadInitializeIndex);
+    ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
+
+    return success;
+}
+
+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;
+        }
+
+        if (!FreeParseContext())
+            success = false;
+
+        FreeGlobalPools();
+    }
+
+    return success;
+}
+
diff --git a/src/OpenGL ES 2.0/compiler/InitializeDll.h b/src/OpenGL ES 2.0/compiler/InitializeDll.h
new file mode 100644
index 0000000..857238e
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/InitializeDll.h
@@ -0,0 +1,16 @@
+//
+// 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
+
+bool InitProcess();
+bool DetachProcess();
+
+bool InitThread();
+bool DetachThread();
+
+#endif // __INITIALIZEDLL_H
+
diff --git a/src/OpenGL ES 2.0/compiler/InitializeGlobals.h b/src/OpenGL ES 2.0/compiler/InitializeGlobals.h
new file mode 100644
index 0000000..842a452
--- /dev/null
+++ b/src/OpenGL ES 2.0/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/src/OpenGL ES 2.0/compiler/InitializeParseContext.h b/src/OpenGL ES 2.0/compiler/InitializeParseContext.h
new file mode 100644
index 0000000..760fd09
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/InitializeParseContext.h
@@ -0,0 +1,16 @@
+//
+// 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_
+
+bool InitializeParseContextIndex();
+bool FreeParseContextIndex();
+
+bool InitializeGlobalParseContext();
+bool FreeParseContext();
+
+#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
diff --git a/src/OpenGL ES 2.0/compiler/IntermTraverse.cpp b/src/OpenGL ES 2.0/compiler/IntermTraverse.cpp
new file mode 100644
index 0000000..a13877f
--- /dev/null
+++ b/src/OpenGL ES 2.0/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 "compiler/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(expr)
+			{
+				expr->traverse(it);
+			}
+
+			if(body)
+			{
+				body->traverse(it);
+			}
+
+			if(cond)
+			{
+				cond->traverse(it);
+			}
+		}
+		else
+		{
+			if(cond)
+			{
+				cond->traverse(it);
+			}
+
+			if(body)
+			{
+				body->traverse(it);
+			}
+
+			if(expr)
+			{
+				expr->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/src/OpenGL ES 2.0/compiler/Intermediate.cpp b/src/OpenGL ES 2.0/compiler/Intermediate.cpp
new file mode 100644
index 0000000..e1e8da2
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/Intermediate.cpp
@@ -0,0 +1,1454 @@
+//
+// 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 <float.h>
+#include <limits.h>
+#include <algorithm>
+
+#include "compiler/localintermediate.h"
+#include "compiler/QualifierAlive.h"
+#include "compiler/RemoveTree.h"
+
+bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
+
+static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){
+    return left > right ? left : right;
+}
+
+const char* getOperatorString(TOperator op) {
+    switch (op) {
+      case EOpInitialize: return "=";
+      case EOpAssign: return "=";
+      case EOpAddAssign: return "+=";
+      case EOpSubAssign: return "-=";
+      case EOpDivAssign: return "/=";
+
+      // Fall-through.
+      case EOpMulAssign: 
+      case EOpVectorTimesMatrixAssign:
+      case EOpVectorTimesScalarAssign:
+      case EOpMatrixTimesScalarAssign:
+      case EOpMatrixTimesMatrixAssign: return "*=";
+
+      // Fall-through.
+      case EOpIndexDirect:
+      case EOpIndexIndirect: return "[]";
+
+      case EOpIndexDirectStruct: return ".";
+      case EOpVectorSwizzle: return ".";
+      case EOpAdd: return "+";
+      case EOpSub: return "-";
+      case EOpMul: return "*";
+      case EOpDiv: return "/";
+      case EOpMod: UNIMPLEMENTED(); break;
+      case EOpEqual: return "==";
+      case EOpNotEqual: return "!=";
+      case EOpLessThan: return "<";
+      case EOpGreaterThan: return ">";
+      case EOpLessThanEqual: return "<=";
+      case EOpGreaterThanEqual: return ">=";
+
+      // Fall-through.
+      case EOpVectorTimesScalar:
+      case EOpVectorTimesMatrix:
+      case EOpMatrixTimesVector:
+      case EOpMatrixTimesScalar:
+      case EOpMatrixTimesMatrix: return "*";
+
+      case EOpLogicalOr: return "||";
+      case EOpLogicalXor: return "^^";
+      case EOpLogicalAnd: return "&&";
+      case EOpNegative: return "-";
+      case EOpVectorLogicalNot: return "not";
+      case EOpLogicalNot: return "!";
+      case EOpPostIncrement: return "++";
+      case EOpPostDecrement: return "--";
+      case EOpPreIncrement: return "++";
+      case EOpPreDecrement: return "--";
+
+      // Fall-through.
+      case EOpConvIntToBool:
+      case EOpConvFloatToBool: return "bool";
+ 
+      // Fall-through.
+      case EOpConvBoolToFloat:
+      case EOpConvIntToFloat: return "float";
+ 
+      // Fall-through.
+      case EOpConvFloatToInt:
+      case EOpConvBoolToInt: return "int";
+
+      case EOpRadians: return "radians";
+      case EOpDegrees: return "degrees";
+      case EOpSin: return "sin";
+      case EOpCos: return "cos";
+      case EOpTan: return "tan";
+      case EOpAsin: return "asin";
+      case EOpAcos: return "acos";
+      case EOpAtan: return "atan";
+      case EOpExp: return "exp";
+      case EOpLog: return "log";
+      case EOpExp2: return "exp2";
+      case EOpLog2: return "log2";
+      case EOpSqrt: return "sqrt";
+      case EOpInverseSqrt: return "inversesqrt";
+      case EOpAbs: return "abs";
+      case EOpSign: return "sign";
+      case EOpFloor: return "floor";
+      case EOpCeil: return "ceil";
+      case EOpFract: return "fract";
+      case EOpLength: return "length";
+      case EOpNormalize: return "normalize";
+      case EOpDFdx: return "dFdx";
+      case EOpDFdy: return "dFdy";
+      case EOpFwidth: return "fwidth";
+      case EOpAny: return "any";
+      case EOpAll: return "all";
+
+      default: break;
+    }
+    return "";
+}
+
+////////////////////////////////////////////////////////////////////////////
+//
+// 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 EOpEqual:
+        case EOpNotEqual:
+            if (left->isArray())
+                return 0;
+            break;
+        case EOpLessThan:
+        case EOpGreaterThan:
+        case EOpLessThanEqual:
+        case EOpGreaterThanEqual:
+            if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
+                return 0;
+            }
+            break;
+        case EOpLogicalOr:
+        case EOpLogicalXor:
+        case EOpLogicalAnd:
+            if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
+                return 0;
+            }
+            break;
+        case EOpAdd:
+        case EOpSub:
+        case EOpDiv:
+        case EOpMul:
+            if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
+                return 0;
+        default: break;
+    }
+
+    //
+    // First try converting the children to compatible types.
+    //
+    if (left->getType().getStruct() && right->getType().getStruct()) {
+        if (left->getType() != right->getType())
+            return 0;
+    } else {
+        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;
+        }
+    }
+
+    //
+    // 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;
+
+    //
+    // See if we can fold constants.
+    //
+    TIntermTyped* typedReturnNode = 0;
+    TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
+    TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
+    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, child->getPrecision(), 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->setOp(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, node->getPrecision(), 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()->setOp(EOpComma);
+        commaAggregate->setType(right->getType());
+        commaAggregate->getTypePointer()->setQualifier(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(ConstantUnion* 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();
+    ConstantUnion* unionArray;
+
+    for (int i = 0; i < fields.num; i++) {
+        unionArray = new ConstantUnion[1];
+        unionArray->setIConst(fields.offsets[i]);
+        constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
+        sequenceVector.push_back(constIntNode);
+    }
+
+    return node;
+}
+
+//
+// Create loop nodes.
+//
+TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, TSourceLoc line)
+{
+    TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
+    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)
+{
+    if (root == 0)
+        return true;
+
+    //
+    // First, finish off the top level sequence, if any
+    //
+    TIntermAggregate* aggRoot = root->getAsAggregate();
+    if (aggRoot && aggRoot->getOp() == EOpNull)
+        aggRoot->setOp(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:
+            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 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)
+{
+    // This function only handles scalars, vectors, and matrices.
+    if (left->isArray() || right->isArray()) {
+        infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine());
+        return false;
+    }
+
+    // GLSL ES 2.0 does not support implicit type casting.
+    // So the basic type should always match.
+    if (left->getBasicType() != right->getBasicType())
+        return false;
+
+    //
+    // Base assumption:  just make the type the same as the left
+    // operand.  Then only deviations from this need be coded.
+    //
+    setType(left->getType());
+
+    // The result gets promoted to the highest precision.
+    TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
+    getTypePointer()->setPrecision(higherPrecision);
+
+    // Binary operations results in temporary variables unless both
+    // operands are const.
+    if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) {
+        getTypePointer()->setQualifier(EvqTemporary);
+    }
+
+    int size = std::max(left->getNominalSize(), right->getNominalSize());
+
+    //
+    // 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, EbpUndefined));
+                break;
+
+            //
+            // And and Or operate on conditionals
+            //
+            case EOpLogicalAnd:
+            case EOpLogicalOr:
+                // Both operands must be of type bool.
+                if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
+                    return false;
+                setType(TType(EbtBool, EbpUndefined));
+                break;
+
+            default:
+                break;
+        }
+        return true;
+    }
+
+    // If we reach here, at least one of the operands is vector or matrix.
+    // The other operand could be a scalar, vector, or matrix.
+    // Are the sizes compatible?
+    //
+    if (left->getNominalSize() != right->getNominalSize()) {
+        // If the nominal size of operands do not match:
+        // One of them must be scalar.
+        if (left->getNominalSize() != 1 && right->getNominalSize() != 1)
+            return false;
+        // Operator cannot be of type pure assignment.
+        if (op == EOpAssign || op == EOpInitialize)
+            return false;
+    }
+
+    //
+    // Can these two operands be combined?
+    //
+    TBasicType basicType = left->getBasicType();
+    switch (op) {
+        case EOpMul:
+            if (!left->isMatrix() && right->isMatrix()) {
+                if (left->isVector())
+                    op = EOpVectorTimesMatrix;
+                else {
+                    op = EOpMatrixTimesScalar;
+                    setType(TType(basicType, higherPrecision, EvqTemporary, size, true));
+                }
+            } else if (left->isMatrix() && !right->isMatrix()) {
+                if (right->isVector()) {
+                    op = EOpMatrixTimesVector;
+                    setType(TType(basicType, higherPrecision, 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(basicType, higherPrecision, 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(basicType, higherPrecision, EvqTemporary, size, false));
+                }
+            } else {
+                infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
+                return false;
+            }
+            break;
+
+        case EOpAssign:
+        case EOpInitialize:
+        case EOpAdd:
+        case EOpSub:
+        case EOpDiv:
+        case EOpAddAssign:
+        case EOpSubAssign:
+        case EOpDivAssign:
+            if ((left->isMatrix() && right->isVector()) ||
+                (left->isVector() && right->isMatrix()))
+                return false;
+            setType(TType(basicType, higherPrecision, 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()))
+                return false;
+            setType(TType(EbtBool, EbpUndefined));
+            break;
+
+        default:
+            return false;
+    }
+    
+    return true;
+}
+
+bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
+{
+    const 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, ConstantUnion* rightUnionArray, ConstantUnion* 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)
+{
+    ConstantUnion *unionArray = getUnionArrayPointer();
+    int objectSize = getType().getObjectSize();
+
+    if (constantNode) {  // binary operations
+        TIntermConstantUnion *node = constantNode->getAsConstantUnion();
+        ConstantUnion *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 ConstantUnion[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 ConstantUnion[constantNode->getType().getObjectSize()];
+            for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
+                unionArray[i] = *getUnionArrayPointer();
+            returnType = node->getType();
+            objectSize = constantNode->getType().getObjectSize();
+        }
+
+        ConstantUnion* tempConstArray = 0;
+        TIntermConstantUnion *tempNode;
+
+        bool boolNodeFlag = false;
+        switch(op) {
+            case EOpAdd:
+                tempConstArray = new ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] + rightUnionArray[i];
+                }
+                break;
+            case EOpSub:
+                tempConstArray = new ConstantUnion[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 ConstantUnion[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 ConstantUnion[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 ConstantUnion[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 ConstantUnion[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 ConstantUnion[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 EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
+                tempConstArray = new ConstantUnion[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 ConstantUnion[objectSize];
+                {// support MSVC++6.0
+                    for (int i = 0; i < objectSize; i++)
+                        tempConstArray[i] = unionArray[i] || rightUnionArray[i];
+                }
+                break;
+
+            case EOpLogicalXor:
+                tempConstArray = new ConstantUnion[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 ConstantUnion[1];
+                tempConstArray->setBConst(*unionArray < *rightUnionArray);
+                returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                break;
+            case EOpGreaterThan:
+                assert(objectSize == 1);
+                tempConstArray = new ConstantUnion[1];
+                tempConstArray->setBConst(*unionArray > *rightUnionArray);
+                returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                break;
+            case EOpLessThanEqual:
+                {
+                    assert(objectSize == 1);
+                    ConstantUnion constant;
+                    constant.setBConst(*unionArray > *rightUnionArray);
+                    tempConstArray = new ConstantUnion[1];
+                    tempConstArray->setBConst(!constant.getBConst());
+                    returnType = TType(EbtBool, EbpUndefined, EvqConst);
+                    break;
+                }
+            case EOpGreaterThanEqual:
+                {
+                    assert(objectSize == 1);
+                    ConstantUnion constant;
+                    constant.setBConst(*unionArray < *rightUnionArray);
+                    tempConstArray = new ConstantUnion[1];
+                    tempConstArray->setBConst(!constant.getBConst());
+                    returnType = TType(EbtBool, EbpUndefined, 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 ConstantUnion[1];
+                if (!boolNodeFlag) {
+                    tempConstArray->setBConst(true);
+                }
+                else {
+                    tempConstArray->setBConst(false);
+                }
+
+                tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, 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 ConstantUnion[1];
+                if (!boolNodeFlag) {
+                    tempConstArray->setBConst(true);
+                }
+                else {
+                    tempConstArray->setBConst(false);
+                }
+
+                tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, 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;
+        ConstantUnion* tempConstArray = new ConstantUnion[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)
+{
+    ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+    int size = node->getType().getObjectSize();
+
+    ConstantUnion *leftUnionArray = new ConstantUnion[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.getPrecision(), 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/src/OpenGL ES 2.0/compiler/MMap.h b/src/OpenGL ES 2.0/compiler/MMap.h
new file mode 100644
index 0000000..a308671
--- /dev/null
+++ b/src/OpenGL ES 2.0/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/src/OpenGL ES 2.0/compiler/MapLongVariableNames.cpp b/src/OpenGL ES 2.0/compiler/MapLongVariableNames.cpp
new file mode 100644
index 0000000..8f35560
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/MapLongVariableNames.cpp
@@ -0,0 +1,69 @@
+//
+// Copyright (c) 2002-2011 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 "compiler/MapLongVariableNames.h"
+
+namespace {
+
+TString mapLongName(int id, const TString& name, bool isVarying)
+{
+    ASSERT(name.size() > MAX_IDENTIFIER_NAME_SIZE);
+    TStringStream stream;
+    stream << "webgl_";
+    if (isVarying)
+        stream << "v";
+    stream << id << "_";
+    stream << name.substr(0, MAX_IDENTIFIER_NAME_SIZE - stream.str().size());
+    return stream.str();
+}
+
+}  // anonymous namespace
+
+MapLongVariableNames::MapLongVariableNames(
+    std::map<std::string, std::string>& varyingLongNameMap)
+    : mVaryingLongNameMap(varyingLongNameMap)
+{
+}
+
+void MapLongVariableNames::visitSymbol(TIntermSymbol* symbol)
+{
+    ASSERT(symbol != NULL);
+    if (symbol->getSymbol().size() > MAX_IDENTIFIER_NAME_SIZE) {
+        switch (symbol->getQualifier()) {
+          case EvqVaryingIn:
+          case EvqVaryingOut:
+          case EvqInvariantVaryingIn:
+          case EvqInvariantVaryingOut:
+            symbol->setSymbol(
+                mapVaryingLongName(symbol->getSymbol()));
+            break;
+          default:
+            symbol->setSymbol(
+                mapLongName(symbol->getId(), symbol->getSymbol(), false));
+            break;
+        };
+    }
+}
+
+bool MapLongVariableNames::visitLoop(Visit, TIntermLoop* node)
+{
+    if (node->getInit())
+        node->getInit()->traverse(this);
+    return true;
+}
+
+TString MapLongVariableNames::mapVaryingLongName(const TString& name)
+{
+    std::map<std::string, std::string>::const_iterator it = mVaryingLongNameMap.find(name.c_str());
+    if (it != mVaryingLongNameMap.end())
+        return (*it).second.c_str();
+
+    int id = mVaryingLongNameMap.size();
+    TString mappedName = mapLongName(id, name, true);
+    mVaryingLongNameMap.insert(
+        std::map<std::string, std::string>::value_type(name.c_str(), mappedName.c_str()));
+    return mappedName;
+}
diff --git a/src/OpenGL ES 2.0/compiler/MapLongVariableNames.h b/src/OpenGL ES 2.0/compiler/MapLongVariableNames.h
new file mode 100644
index 0000000..46f19b8
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/MapLongVariableNames.h
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2002-2011 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_MAP_LONG_VARIABLE_NAMES_H_
+#define COMPILER_MAP_LONG_VARIABLE_NAMES_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/intermediate.h"
+#include "compiler/VariableInfo.h"
+
+// This size does not include '\0' in the end.
+#define MAX_IDENTIFIER_NAME_SIZE 32
+
+// Traverses intermediate tree to map attributes and uniforms names that are
+// longer than MAX_IDENTIFIER_NAME_SIZE to MAX_IDENTIFIER_NAME_SIZE.
+class MapLongVariableNames : public TIntermTraverser {
+public:
+    MapLongVariableNames(std::map<std::string, std::string>& varyingLongNameMap);
+
+    virtual void visitSymbol(TIntermSymbol*);
+    virtual bool visitLoop(Visit, TIntermLoop*);
+
+private:
+    TString mapVaryingLongName(const TString& name);
+
+    std::map<std::string, std::string>& mVaryingLongNameMap;
+};
+
+#endif  // COMPILER_MAP_LONG_VARIABLE_NAMES_H_
diff --git a/src/OpenGL ES 2.0/compiler/OutputGLSL.cpp b/src/OpenGL ES 2.0/compiler/OutputGLSL.cpp
new file mode 100644
index 0000000..3224dfd
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/OutputGLSL.cpp
@@ -0,0 +1,710 @@
+//
+// Copyright (c) 2002-2011 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 "compiler/OutputGLSL.h"
+#include "compiler/debug.h"
+
+namespace
+{
+TString getTypeName(const TType& type)
+{
+    TInfoSinkBase out;
+    if (type.isMatrix())
+    {
+        out << "mat";
+        out << type.getNominalSize();
+    }
+    else if (type.isVector())
+    {
+        switch (type.getBasicType())
+        {
+            case EbtFloat: out << "vec"; break;
+            case EbtInt: out << "ivec"; break;
+            case EbtBool: out << "bvec"; break;
+            default: UNREACHABLE(); break;
+        }
+        out << type.getNominalSize();
+    }
+    else
+    {
+        if (type.getBasicType() == EbtStruct)
+            out << type.getTypeName();
+        else
+            out << type.getBasicString();
+    }
+    return TString(out.c_str());
+}
+
+TString arrayBrackets(const TType& type)
+{
+    ASSERT(type.isArray());
+    TInfoSinkBase out;
+    out << "[" << type.getArraySize() << "]";
+    return TString(out.c_str());
+}
+
+bool isSingleStatement(TIntermNode* node) {
+    if (const TIntermAggregate* aggregate = node->getAsAggregate())
+    {
+        return (aggregate->getOp() != EOpFunction) &&
+               (aggregate->getOp() != EOpSequence);
+    }
+    else if (const TIntermSelection* selection = node->getAsSelectionNode())
+    {
+        // Ternary operators are usually part of an assignment operator.
+        // This handles those rare cases in which they are all by themselves.
+        return selection->usesTernaryOperator();
+    }
+    else if (node->getAsLoopNode())
+    {
+        return false;
+    }
+    return true;
+}
+}  // namespace
+
+TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink)
+    : TIntermTraverser(true, true, true),
+      mObjSink(objSink),
+      mDeclaringVariables(false)
+{
+}
+
+void TOutputGLSL::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr)
+{
+    TInfoSinkBase& out = objSink();
+    if (visit == PreVisit && preStr)
+    {
+        out << preStr;
+    }
+    else if (visit == InVisit && inStr)
+    {
+        out << inStr;
+    }
+    else if (visit == PostVisit && postStr)
+    {
+        out << postStr;
+    }
+}
+
+void TOutputGLSL::writeVariableType(const TType& type)
+{
+    TInfoSinkBase& out = objSink();
+    TQualifier qualifier = type.getQualifier();
+    // TODO(alokp): Validate qualifier for variable declarations.
+    if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
+        out << type.getQualifierString() << " ";
+
+    // Declare the struct if we have not done so already.
+    if ((type.getBasicType() == EbtStruct) &&
+        (mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end()))
+    {
+        out << "struct " << type.getTypeName() << "{\n";
+        const TTypeList* structure = type.getStruct();
+        ASSERT(structure != NULL);
+        for (size_t i = 0; i < structure->size(); ++i)
+        {
+            const TType* fieldType = (*structure)[i].type;
+            ASSERT(fieldType != NULL);
+            out << getTypeName(*fieldType) << " " << fieldType->getFieldName();
+            if (fieldType->isArray())
+                out << arrayBrackets(*fieldType);
+            out << ";\n";
+        }
+        out << "}";
+        mDeclaredStructs.insert(type.getTypeName());
+    }
+    else
+    {
+        out << getTypeName(type);
+    }
+}
+
+void TOutputGLSL::writeFunctionParameters(const TIntermSequence& args)
+{
+    TInfoSinkBase& out = objSink();
+    for (TIntermSequence::const_iterator iter = args.begin();
+         iter != args.end(); ++iter)
+    {
+        const TIntermSymbol* arg = (*iter)->getAsSymbolNode();
+        ASSERT(arg != NULL);
+
+        const TType& type = arg->getType();
+        TQualifier qualifier = type.getQualifier();
+        // TODO(alokp): Validate qualifier for function arguments.
+        if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
+            out << type.getQualifierString() << " ";
+
+        out << getTypeName(type);
+
+        const TString& name = arg->getSymbol();
+        if (!name.empty())
+            out << " " << name;
+        if (type.isArray())
+            out << arrayBrackets(type);
+
+        // Put a comma if this is not the last argument.
+        if (iter != args.end() - 1)
+            out << ", ";
+    }
+}
+
+const ConstantUnion* TOutputGLSL::writeConstantUnion(const TType& type,
+                                                     const ConstantUnion* pConstUnion)
+{
+    TInfoSinkBase& out = objSink();
+
+    if (type.getBasicType() == EbtStruct)
+    {
+        out << type.getTypeName() << "(";
+        const TTypeList* structure = type.getStruct();
+        ASSERT(structure != NULL);
+        for (size_t i = 0; i < structure->size(); ++i)
+        {
+            const TType* fieldType = (*structure)[i].type;
+            ASSERT(fieldType != NULL);
+            pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
+            if (i != structure->size() - 1) out << ", ";
+        }
+        out << ")";
+    }
+    else
+    {
+        int size = type.getObjectSize();
+        bool writeType = size > 1;
+        if (writeType) out << getTypeName(type) << "(";
+        for (int i = 0; i < size; ++i, ++pConstUnion)
+        {
+            switch (pConstUnion->getType())
+            {
+                case EbtFloat: out << pConstUnion->getFConst(); break;
+                case EbtInt: out << pConstUnion->getIConst(); break;
+                case EbtBool: out << pConstUnion->getBConst(); break;
+                default: UNREACHABLE();
+            }
+            if (i != size - 1) out << ", ";
+        }
+        if (writeType) out << ")";
+    }
+    return pConstUnion;
+}
+
+void TOutputGLSL::visitSymbol(TIntermSymbol* node)
+{
+    TInfoSinkBase& out = objSink();
+    if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node))
+        out << mLoopUnroll.GetLoopIndexValue(node);
+    else
+        out << node->getSymbol();
+
+    if (mDeclaringVariables && node->getType().isArray())
+        out << arrayBrackets(node->getType());
+}
+
+void TOutputGLSL::visitConstantUnion(TIntermConstantUnion* node)
+{
+    writeConstantUnion(node->getType(), node->getUnionArrayPointer());
+}
+
+bool TOutputGLSL::visitBinary(Visit visit, TIntermBinary* node)
+{
+    bool visitChildren = true;
+    TInfoSinkBase& out = objSink();
+    switch (node->getOp())
+    {
+        case EOpInitialize:
+            if (visit == InVisit)
+            {
+                out << " = ";
+                // RHS of initialize is not being declared.
+                mDeclaringVariables = false;
+            }
+            break;
+        case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break;
+        case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break;
+        case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break;
+        case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break;
+        // Notice the fall-through.
+        case EOpMulAssign: 
+        case EOpVectorTimesMatrixAssign:
+        case EOpVectorTimesScalarAssign:
+        case EOpMatrixTimesScalarAssign:
+        case EOpMatrixTimesMatrixAssign:
+            writeTriplet(visit, "(", " *= ", ")");
+            break;
+
+        case EOpIndexDirect:
+        case EOpIndexIndirect:
+            writeTriplet(visit, NULL, "[", "]");
+            break;
+        case EOpIndexDirectStruct:
+            if (visit == InVisit)
+            {
+                out << ".";
+                // TODO(alokp): ASSERT
+                out << node->getType().getFieldName();
+                visitChildren = false;
+            }
+            break;
+        case EOpVectorSwizzle:
+            if (visit == InVisit)
+            {
+                out << ".";
+                TIntermAggregate* rightChild = node->getRight()->getAsAggregate();
+                TIntermSequence& sequence = rightChild->getSequence();
+                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
+                {
+                    TIntermConstantUnion* element = (*sit)->getAsConstantUnion();
+                    ASSERT(element->getBasicType() == EbtInt);
+                    ASSERT(element->getNominalSize() == 1);
+                    const ConstantUnion& data = element->getUnionArrayPointer()[0];
+                    ASSERT(data.getType() == EbtInt);
+                    switch (data.getIConst())
+                    {
+                        case 0: out << "x"; break;
+                        case 1: out << "y"; break;
+                        case 2: out << "z"; break;
+                        case 3: out << "w"; break;
+                        default: UNREACHABLE(); break;
+                    }
+                }
+                visitChildren = false;
+            }
+            break;
+
+        case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break;
+        case EOpSub: writeTriplet(visit, "(", " - ", ")"); break;
+        case EOpMul: writeTriplet(visit, "(", " * ", ")"); break;
+        case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break;
+        case EOpMod: UNIMPLEMENTED(); break;
+        case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break;
+        case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break;
+        case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break;
+        case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break;
+        case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break;
+        case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break;
+
+        // Notice the fall-through.
+        case EOpVectorTimesScalar:
+        case EOpVectorTimesMatrix:
+        case EOpMatrixTimesVector:
+        case EOpMatrixTimesScalar:
+        case EOpMatrixTimesMatrix:
+            writeTriplet(visit, "(", " * ", ")");
+            break;
+
+        case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break;
+        case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break;
+        case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break;
+        default: UNREACHABLE(); break;
+    }
+
+    return visitChildren;
+}
+
+bool TOutputGLSL::visitUnary(Visit visit, TIntermUnary* node)
+{
+    switch (node->getOp())
+    {
+        case EOpNegative: writeTriplet(visit, "(-", NULL, ")"); break;
+        case EOpVectorLogicalNot: writeTriplet(visit, "not(", NULL, ")"); break;
+        case EOpLogicalNot: writeTriplet(visit, "(!", NULL, ")"); break;
+
+        case EOpPostIncrement: writeTriplet(visit, "(", NULL, "++)"); break;
+        case EOpPostDecrement: writeTriplet(visit, "(", NULL, "--)"); break;
+        case EOpPreIncrement: writeTriplet(visit, "(++", NULL, ")"); break;
+        case EOpPreDecrement: writeTriplet(visit, "(--", NULL, ")"); break;
+
+        case EOpConvIntToBool:
+        case EOpConvFloatToBool:
+            switch (node->getOperand()->getType().getNominalSize())
+            {
+                case 1: writeTriplet(visit, "bool(", NULL, ")");  break;
+                case 2: writeTriplet(visit, "bvec2(", NULL, ")"); break;
+                case 3: writeTriplet(visit, "bvec3(", NULL, ")"); break;
+                case 4: writeTriplet(visit, "bvec4(", NULL, ")"); break;
+                default: UNREACHABLE();
+            }
+            break;
+        case EOpConvBoolToFloat:
+        case EOpConvIntToFloat:
+            switch (node->getOperand()->getType().getNominalSize())
+            {
+                case 1: writeTriplet(visit, "float(", NULL, ")");  break;
+                case 2: writeTriplet(visit, "vec2(", NULL, ")"); break;
+                case 3: writeTriplet(visit, "vec3(", NULL, ")"); break;
+                case 4: writeTriplet(visit, "vec4(", NULL, ")"); break;
+                default: UNREACHABLE();
+            }
+            break;
+        case EOpConvFloatToInt:
+        case EOpConvBoolToInt:
+            switch (node->getOperand()->getType().getNominalSize())
+            {
+                case 1: writeTriplet(visit, "int(", NULL, ")");  break;
+                case 2: writeTriplet(visit, "ivec2(", NULL, ")"); break;
+                case 3: writeTriplet(visit, "ivec3(", NULL, ")"); break;
+                case 4: writeTriplet(visit, "ivec4(", NULL, ")"); break;
+                default: UNREACHABLE();
+            }
+            break;
+
+        case EOpRadians: writeTriplet(visit, "radians(", NULL, ")"); break;
+        case EOpDegrees: writeTriplet(visit, "degrees(", NULL, ")"); break;
+        case EOpSin: writeTriplet(visit, "sin(", NULL, ")"); break;
+        case EOpCos: writeTriplet(visit, "cos(", NULL, ")"); break;
+        case EOpTan: writeTriplet(visit, "tan(", NULL, ")"); break;
+        case EOpAsin: writeTriplet(visit, "asin(", NULL, ")"); break;
+        case EOpAcos: writeTriplet(visit, "acos(", NULL, ")"); break;
+        case EOpAtan: writeTriplet(visit, "atan(", NULL, ")"); break;
+
+        case EOpExp: writeTriplet(visit, "exp(", NULL, ")"); break;
+        case EOpLog: writeTriplet(visit, "log(", NULL, ")"); break;
+        case EOpExp2: writeTriplet(visit, "exp2(", NULL, ")"); break;
+        case EOpLog2: writeTriplet(visit, "log2(", NULL, ")"); break;
+        case EOpSqrt: writeTriplet(visit, "sqrt(", NULL, ")"); break;
+        case EOpInverseSqrt: writeTriplet(visit, "inversesqrt(", NULL, ")"); break;
+
+        case EOpAbs: writeTriplet(visit, "abs(", NULL, ")"); break;
+        case EOpSign: writeTriplet(visit, "sign(", NULL, ")"); break;
+        case EOpFloor: writeTriplet(visit, "floor(", NULL, ")"); break;
+        case EOpCeil: writeTriplet(visit, "ceil(", NULL, ")"); break;
+        case EOpFract: writeTriplet(visit, "fract(", NULL, ")"); break;
+
+        case EOpLength: writeTriplet(visit, "length(", NULL, ")"); break;
+        case EOpNormalize: writeTriplet(visit, "normalize(", NULL, ")"); break;
+
+        case EOpDFdx: writeTriplet(visit, "dFdx(", NULL, ")"); break;
+        case EOpDFdy: writeTriplet(visit, "dFdy(", NULL, ")"); break;
+        case EOpFwidth: writeTriplet(visit, "fwidth(", NULL, ")"); break;
+
+        case EOpAny: writeTriplet(visit, "any(", NULL, ")"); break;
+        case EOpAll: writeTriplet(visit, "all(", NULL, ")"); break;
+
+        default: UNREACHABLE(); break;
+    }
+
+    return true;
+}
+
+bool TOutputGLSL::visitSelection(Visit visit, TIntermSelection* node)
+{
+    TInfoSinkBase& out = objSink();
+
+    if (node->usesTernaryOperator())
+    {
+        // Notice two brackets at the beginning and end. The outer ones
+        // encapsulate the whole ternary expression. This preserves the
+        // order of precedence when ternary expressions are used in a
+        // compound expression, i.e., c = 2 * (a < b ? 1 : 2).
+        out << "((";
+        node->getCondition()->traverse(this);
+        out << ") ? (";
+        node->getTrueBlock()->traverse(this);
+        out << ") : (";
+        node->getFalseBlock()->traverse(this);
+        out << "))";
+    }
+    else
+    {
+        out << "if (";
+        node->getCondition()->traverse(this);
+        out << ")\n";
+
+        incrementDepth();
+        visitCodeBlock(node->getTrueBlock());
+
+        if (node->getFalseBlock())
+        {
+            out << "else\n";
+            visitCodeBlock(node->getFalseBlock());
+        }
+        decrementDepth();
+    }
+    return false;
+}
+
+bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    bool visitChildren = true;
+    TInfoSinkBase& out = objSink();
+    switch (node->getOp())
+    {
+        case EOpSequence: {
+            // Scope the sequences except when at the global scope.
+            if (depth > 0) out << "{\n";
+
+            incrementDepth();
+            const TIntermSequence& sequence = node->getSequence();
+            for (TIntermSequence::const_iterator iter = sequence.begin();
+                 iter != sequence.end(); ++iter)
+            {
+                TIntermNode* node = *iter;
+                ASSERT(node != NULL);
+                node->traverse(this);
+
+                if (isSingleStatement(node))
+                    out << ";\n";
+            }
+            decrementDepth();
+
+            // Scope the sequences except when at the global scope.
+            if (depth > 0) out << "}\n";
+            visitChildren = false;
+            break;
+        }
+        case EOpPrototype: {
+            // Function declaration.
+            ASSERT(visit == PreVisit);
+            TString returnType = getTypeName(node->getType());
+            out << returnType << " " << node->getName();
+
+            out << "(";
+            writeFunctionParameters(node->getSequence());
+            out << ")";
+
+            visitChildren = false;
+            break;
+        }
+        case EOpFunction: {
+            // Function definition.
+            ASSERT(visit == PreVisit);
+            TString returnType = getTypeName(node->getType());
+            TString functionName = TFunction::unmangleName(node->getName());
+            out << returnType << " " << functionName;
+
+            incrementDepth();
+            // Function definition node contains one or two children nodes
+            // representing function parameters and function body. The latter
+            // is not present in case of empty function bodies.
+            const TIntermSequence& sequence = node->getSequence();
+            ASSERT((sequence.size() == 1) || (sequence.size() == 2));
+            TIntermSequence::const_iterator seqIter = sequence.begin();
+
+            // Traverse function parameters.
+            TIntermAggregate* params = (*seqIter)->getAsAggregate();
+            ASSERT(params != NULL);
+            ASSERT(params->getOp() == EOpParameters);
+            params->traverse(this);
+
+            // Traverse function body.
+            TIntermAggregate* body = ++seqIter != sequence.end() ?
+                (*seqIter)->getAsAggregate() : NULL;
+            visitCodeBlock(body);
+            decrementDepth();
+ 
+            // Fully processed; no need to visit children.
+            visitChildren = false;
+            break;
+        }
+        case EOpFunctionCall:
+            // Function call.
+            if (visit == PreVisit)
+            {
+                TString functionName = TFunction::unmangleName(node->getName());
+                out << functionName << "(";
+            }
+            else if (visit == InVisit)
+            {
+                out << ", ";
+            }
+            else
+            {
+                out << ")";
+            }
+            break;
+        case EOpParameters: {
+            // Function parameters.
+            ASSERT(visit == PreVisit);
+            out << "(";
+            writeFunctionParameters(node->getSequence());
+            out << ")";
+            visitChildren = false;
+            break;
+        }
+        case EOpDeclaration: {
+            // Variable declaration.
+            if (visit == PreVisit)
+            {
+                const TIntermSequence& sequence = node->getSequence();
+                const TIntermTyped* variable = sequence.front()->getAsTyped();
+                writeVariableType(variable->getType());
+                out << " ";
+                mDeclaringVariables = true;
+            }
+            else if (visit == InVisit)
+            {
+                out << ", ";
+                mDeclaringVariables = true;
+            }
+            else
+            {
+                mDeclaringVariables = false;
+            }
+            break;
+        }
+        case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break;
+        case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break;
+        case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break;
+        case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break;
+        case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break;
+        case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break;
+        case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break;
+        case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break;
+        case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break;
+        case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break;
+        case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break;
+        case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break;
+        case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break;
+        case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break;
+        case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break;
+        case EOpConstructStruct:
+            if (visit == PreVisit)
+            {
+                const TType& type = node->getType();
+                ASSERT(type.getBasicType() == EbtStruct);
+                out << type.getTypeName() << "(";
+            }
+            else if (visit == InVisit)
+            {
+                out << ", ";
+            }
+            else
+            {
+                out << ")";
+            }
+            break;
+
+        case EOpLessThan: writeTriplet(visit, "lessThan(", ", ", ")"); break;
+        case EOpGreaterThan: writeTriplet(visit, "greaterThan(", ", ", ")"); break;
+        case EOpLessThanEqual: writeTriplet(visit, "lessThanEqual(", ", ", ")"); break;
+        case EOpGreaterThanEqual: writeTriplet(visit, "greaterThanEqual(", ", ", ")"); break;
+        case EOpVectorEqual: writeTriplet(visit, "equal(", ", ", ")"); break;
+        case EOpVectorNotEqual: writeTriplet(visit, "notEqual(", ", ", ")"); break;
+        case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break;
+
+        case EOpMod: writeTriplet(visit, "mod(", ", ", ")"); break;
+        case EOpPow: writeTriplet(visit, "pow(", ", ", ")"); break;
+        case EOpAtan: writeTriplet(visit, "atan(", ", ", ")"); break;
+        case EOpMin: writeTriplet(visit, "min(", ", ", ")"); break;
+        case EOpMax: writeTriplet(visit, "max(", ", ", ")"); break;
+        case EOpClamp: writeTriplet(visit, "clamp(", ", ", ")"); break;
+        case EOpMix: writeTriplet(visit, "mix(", ", ", ")"); break;
+        case EOpStep: writeTriplet(visit, "step(", ", ", ")"); break;
+        case EOpSmoothStep: writeTriplet(visit, "smoothstep(", ", ", ")"); break;
+
+        case EOpDistance: writeTriplet(visit, "distance(", ", ", ")"); break;
+        case EOpDot: writeTriplet(visit, "dot(", ", ", ")"); break;
+        case EOpCross: writeTriplet(visit, "cross(", ", ", ")"); break;
+        case EOpFaceForward: writeTriplet(visit, "faceforward(", ", ", ")"); break;
+        case EOpReflect: writeTriplet(visit, "reflect(", ", ", ")"); break;
+        case EOpRefract: writeTriplet(visit, "refract(", ", ", ")"); break;
+        case EOpMul: writeTriplet(visit, "matrixCompMult(", ", ", ")"); break;
+
+        default: UNREACHABLE(); break;
+    }
+    return visitChildren;
+}
+
+bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node)
+{
+    TInfoSinkBase& out = objSink();
+
+    incrementDepth();
+    // Loop header.
+    TLoopType loopType = node->getType();
+    if (loopType == ELoopFor)  // for loop
+    {
+        if (!node->getUnrollFlag()) {
+            out << "for (";
+            if (node->getInit())
+                node->getInit()->traverse(this);
+            out << "; ";
+
+            if (node->getCondition())
+                node->getCondition()->traverse(this);
+            out << "; ";
+
+            if (node->getExpression())
+                node->getExpression()->traverse(this);
+            out << ")\n";
+        }
+    }
+    else if (loopType == ELoopWhile)  // while loop
+    {
+        out << "while (";
+        ASSERT(node->getCondition() != NULL);
+        node->getCondition()->traverse(this);
+        out << ")\n";
+    }
+    else  // do-while loop
+    {
+        ASSERT(loopType == ELoopDoWhile);
+        out << "do\n";
+    }
+
+    // Loop body.
+    if (node->getUnrollFlag())
+    {
+        TLoopIndexInfo indexInfo;
+        mLoopUnroll.FillLoopIndexInfo(node, indexInfo);
+        mLoopUnroll.Push(indexInfo);
+        while (mLoopUnroll.SatisfiesLoopCondition())
+        {
+            visitCodeBlock(node->getBody());
+            mLoopUnroll.Step();
+        }
+        mLoopUnroll.Pop();
+    }
+    else
+    {
+        visitCodeBlock(node->getBody());
+    }
+
+    // Loop footer.
+    if (loopType == ELoopDoWhile)  // do-while loop
+    {
+        out << "while (";
+        ASSERT(node->getCondition() != NULL);
+        node->getCondition()->traverse(this);
+        out << ");\n";
+    }
+    decrementDepth();
+
+    // No need to visit children. They have been already processed in
+    // this function.
+    return false;
+}
+
+bool TOutputGLSL::visitBranch(Visit visit, TIntermBranch* node)
+{
+    switch (node->getFlowOp())
+    {
+        case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break;
+        case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break;
+        case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break;
+        case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break;
+        default: UNREACHABLE(); break;
+    }
+
+    return true;
+}
+
+void TOutputGLSL::visitCodeBlock(TIntermNode* node) {
+    TInfoSinkBase &out = objSink();
+    if (node != NULL)
+    {
+        node->traverse(this);
+        // Single statements not part of a sequence need to be terminated
+        // with semi-colon.
+        if (isSingleStatement(node))
+            out << ";\n";
+    }
+    else
+    {
+        out << "{\n}\n";  // Empty code block.
+    }
+}
diff --git a/src/OpenGL ES 2.0/compiler/OutputGLSL.h b/src/OpenGL ES 2.0/compiler/OutputGLSL.h
new file mode 100644
index 0000000..ace110a
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/OutputGLSL.h
@@ -0,0 +1,52 @@
+//
+// 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 CROSSCOMPILERGLSL_OUTPUTGLSL_H_
+#define CROSSCOMPILERGLSL_OUTPUTGLSL_H_
+
+#include <set>
+
+#include "compiler/ForLoopUnroll.h"
+#include "compiler/intermediate.h"
+#include "compiler/ParseHelper.h"
+
+class TOutputGLSL : public TIntermTraverser
+{
+public:
+    TOutputGLSL(TInfoSinkBase& objSink);
+
+protected:
+    TInfoSinkBase& objSink() { return mObjSink; }
+    void writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr);
+    void writeVariableType(const TType& type);
+    void writeFunctionParameters(const TIntermSequence& args);
+    const ConstantUnion* writeConstantUnion(const TType& type, const ConstantUnion* pConstUnion);
+
+    virtual void visitSymbol(TIntermSymbol* node);
+    virtual void visitConstantUnion(TIntermConstantUnion* node);
+    virtual bool visitBinary(Visit visit, TIntermBinary* node);
+    virtual bool visitUnary(Visit visit, TIntermUnary* node);
+    virtual bool visitSelection(Visit visit, TIntermSelection* node);
+    virtual bool visitAggregate(Visit visit, TIntermAggregate* node);
+    virtual bool visitLoop(Visit visit, TIntermLoop* node);
+    virtual bool visitBranch(Visit visit, TIntermBranch* node);
+
+    void visitCodeBlock(TIntermNode* node);
+
+private:
+    TInfoSinkBase& mObjSink;
+    bool mDeclaringVariables;
+
+    // Structs are declared as the tree is traversed. This set contains all
+    // the structs already declared. It is maintained so that a struct is
+    // declared only once.
+    typedef std::set<TString> DeclaredStructs;
+    DeclaredStructs mDeclaredStructs;
+
+    ForLoopUnroll mLoopUnroll;
+};
+
+#endif  // CROSSCOMPILERGLSL_OUTPUTGLSL_H_
diff --git a/src/OpenGL ES 2.0/compiler/OutputHLSL.cpp b/src/OpenGL ES 2.0/compiler/OutputHLSL.cpp
new file mode 100644
index 0000000..af5696f
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/OutputHLSL.cpp
@@ -0,0 +1,2347 @@
+//
+// Copyright (c) 2002-2011 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 "compiler/OutputHLSL.h"
+
+#include "compiler/debug.h"
+#include "compiler/InfoSink.h"
+#include "compiler/UnfoldSelect.h"
+#include "compiler/SearchSymbol.h"
+
+#include <stdio.h>
+#include <algorithm>
+
+namespace sh
+{
+// Integer to TString conversion
+TString str(int i)
+{
+    char buffer[20];
+    sprintf(buffer, "%d", i);
+    return buffer;
+}
+
+OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, true), mContext(context)
+{
+    mUnfoldSelect = new UnfoldSelect(context, this);
+    mInsideFunction = false;
+
+    mUsesTexture2D = false;
+    mUsesTexture2D_bias = false;
+    mUsesTexture2DProj = false;
+    mUsesTexture2DProj_bias = false;
+    mUsesTexture2DProjLod = false;
+    mUsesTexture2DLod = false;
+    mUsesTextureCube = false;
+    mUsesTextureCube_bias = false;
+    mUsesTextureCubeLod = false;
+    mUsesDepthRange = false;
+    mUsesFragCoord = false;
+    mUsesPointCoord = false;
+    mUsesFrontFacing = false;
+    mUsesPointSize = false;
+    mUsesXor = false;
+    mUsesMod1 = false;
+    mUsesMod2 = false;
+    mUsesMod3 = false;
+    mUsesMod4 = false;
+    mUsesFaceforward1 = false;
+    mUsesFaceforward2 = false;
+    mUsesFaceforward3 = false;
+    mUsesFaceforward4 = false;
+    mUsesEqualMat2 = false;
+    mUsesEqualMat3 = false;
+    mUsesEqualMat4 = false;
+    mUsesEqualVec2 = false;
+    mUsesEqualVec3 = false;
+    mUsesEqualVec4 = false;
+    mUsesEqualIVec2 = false;
+    mUsesEqualIVec3 = false;
+    mUsesEqualIVec4 = false;
+    mUsesEqualBVec2 = false;
+    mUsesEqualBVec3 = false;
+    mUsesEqualBVec4 = false;
+    mUsesAtan2 = false;
+
+    mScopeDepth = 0;
+
+    mUniqueIndex = 0;
+}
+
+OutputHLSL::~OutputHLSL()
+{
+    delete mUnfoldSelect;
+}
+
+void OutputHLSL::output()
+{
+    mContext.treeRoot->traverse(this);   // Output the body first to determine what has to go in the header
+    header();
+
+    mContext.infoSink.obj << mHeader.c_str();
+    mContext.infoSink.obj << mBody.c_str();
+}
+
+TInfoSinkBase &OutputHLSL::getBodyStream()
+{
+    return mBody;
+}
+
+int OutputHLSL::vectorSize(const TType &type) const
+{
+    int elementSize = type.isMatrix() ? type.getNominalSize() : 1;
+    int arraySize = type.isArray() ? type.getArraySize() : 1;
+
+    return elementSize * arraySize;
+}
+
+void OutputHLSL::header()
+{
+    ShShaderType shaderType = mContext.shaderType;
+    TInfoSinkBase &out = mHeader;
+
+    for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++)
+    {
+        out << *structDeclaration;
+    }
+
+    for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++)
+    {
+        out << *constructor;
+    }
+
+    if (shaderType == SH_FRAGMENT_SHADER)
+    {
+        TString uniforms;
+        TString varyings;
+
+        TSymbolTableLevel *symbols = mContext.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)
+                {
+                    if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end())
+                    {
+                        uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type.isArray()) + arrayString(type) + ";\n";
+                    }
+                }
+                else if (qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
+                {
+                    if (mReferencedVaryings.find(name.c_str()) != mReferencedVaryings.end())
+                    {
+                        // Program linking depends on this exact format
+                        varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
+
+                        semanticIndex += type.isArray() ? type.getArraySize() : 1;
+                    }
+                }
+                else if (qualifier == EvqGlobal || qualifier == EvqTemporary)
+                {
+                    // Globals are declared and intialized as an aggregate node
+                }
+                else if (qualifier == EvqConst)
+                {
+                    // Constants are repeated as literals where used
+                }
+                else UNREACHABLE();
+            }
+        }
+
+        out << "// Varyings\n";
+        out <<  varyings;
+        out << "\n"
+               "static float4 gl_Color[1] = {float4(0, 0, 0, 0)};\n";
+
+        if (mUsesFragCoord)
+        {
+            out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n";
+        }
+
+        if (mUsesPointCoord)
+        {
+            out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n";
+        }
+
+        if (mUsesFrontFacing)
+        {
+            out << "static bool gl_FrontFacing = false;\n";
+        }
+
+        out << "\n";
+
+        if (mUsesFragCoord)
+        {
+            out << "uniform float4 dx_Viewport;\n"
+                   "uniform float2 dx_Depth;\n";
+        }
+
+        if (mUsesFrontFacing)
+        {
+            out << "uniform bool dx_PointsOrLines;\n"
+                   "uniform bool dx_FrontCCW;\n";
+        }
+        
+        out << "\n";
+        out <<  uniforms;
+        out << "\n";
+
+        // The texture fetch functions "flip" the Y coordinate in one way or another. This is because textures are stored
+        // according to the OpenGL convention, i.e. (0, 0) is "bottom left", rather than the D3D convention where (0, 0)
+        // is "top left". Since the HLSL texture fetch functions expect textures to be stored according to the D3D
+        // convention, the Y coordinate passed to these functions is adjusted to compensate.
+        //
+        // The simplest case is texture2D where the mapping is Y -> 1-Y, which maps [0, 1] -> [1, 0].
+        //
+        // The texture2DProj functions are more complicated because the projection divides by either Z or W. For the vec3
+        // case, the mapping is Y -> Z-Y or Y/Z -> 1-Y/Z, which again maps [0, 1] -> [1, 0].
+        //
+        // For cube textures the mapping is Y -> -Y, which maps [-1, 1] -> [1, -1]. This is not sufficient on its own for the
+        // +Y and -Y faces, which are now on the "wrong sides" of the cube. This is compensated for by exchanging the
+        // +Y and -Y faces everywhere else throughout the code.
+        
+        if (mUsesTexture2D)
+        {
+            out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
+                   "{\n"
+                   "    return tex2D(s, float2(t.x, 1 - t.y));\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTexture2D_bias)
+        {
+            out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n"
+                   "{\n"
+                   "    return tex2Dbias(s, float4(t.x, 1 - t.y, 0, bias));\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTexture2DProj)
+        {
+            out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
+                   "{\n"
+                   "    return tex2Dproj(s, float4(t.x, t.z - t.y, 0, t.z));\n"
+                   "}\n"
+                   "\n"
+                   "float4 gl_texture2DProj(sampler2D s, float4 t)\n"
+                   "{\n"
+                   "    return tex2Dproj(s, float4(t.x, t.w - t.y, t.z, t.w));\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTexture2DProj_bias)
+        {
+            out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n"
+                   "{\n"
+                   "    return tex2Dbias(s, float4(t.x / t.z, 1 - (t.y / t.z), 0, bias));\n"
+                   "}\n"
+                   "\n"
+                   "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n"
+                   "{\n"
+                   "    return tex2Dbias(s, float4(t.x / t.w, 1 - (t.y / t.w), 0, bias));\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTextureCube)
+        {
+            out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
+                   "{\n"
+                   "    return texCUBE(s, float3(t.x, -t.y, t.z));\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTextureCube_bias)
+        {
+            out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n"
+                   "{\n"
+                   "    return texCUBEbias(s, float4(t.x, -t.y, t.z, bias));\n"
+                   "}\n"
+                   "\n";
+        }
+    }
+    else   // Vertex shader
+    {
+        TString uniforms;
+        TString attributes;
+        TString varyings;
+
+        TSymbolTableLevel *symbols = mContext.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);
+                const TType &type = variable->getType();
+                TQualifier qualifier = type.getQualifier();
+
+                if (qualifier == EvqUniform)
+                {
+                    if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end())
+                    {
+                        uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type.isArray()) + arrayString(type) + ";\n";
+                    }
+                }
+                else if (qualifier == EvqAttribute)
+                {
+                    if (mReferencedAttributes.find(name.c_str()) != mReferencedAttributes.end())
+                    {
+                        attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
+                    }
+                }
+                else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut)
+                {
+                    if (mReferencedVaryings.find(name.c_str()) != mReferencedVaryings.end())
+                    {
+                        // Program linking depends on this exact format
+                        varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
+                    }
+                }
+                else if (qualifier == EvqGlobal || qualifier == EvqTemporary)
+                {
+                    // Globals are declared and intialized as an aggregate node
+                }
+                else if (qualifier == EvqConst)
+                {
+                    // Constants are repeated as literals where used
+                }
+                else UNREACHABLE();
+            }
+        }
+
+        out << "// Attributes\n";
+        out <<  attributes;
+        out << "\n"
+               "static float4 gl_Position = float4(0, 0, 0, 0);\n";
+        
+        if (mUsesPointSize)
+        {
+            out << "static float gl_PointSize = float(1);\n";
+        }
+
+        out << "\n"
+               "// Varyings\n";
+        out <<  varyings;
+        out << "\n"
+               "uniform float2 dx_HalfPixelSize;\n"
+               "\n";
+        out <<  uniforms;
+        out << "\n";
+
+        // The texture fetch functions "flip" the Y coordinate in one way or another. This is because textures are stored
+        // according to the OpenGL convention, i.e. (0, 0) is "bottom left", rather than the D3D convention where (0, 0)
+        // is "top left". Since the HLSL texture fetch functions expect textures to be stored according to the D3D
+        // convention, the Y coordinate passed to these functions is adjusted to compensate.
+        //
+        // The simplest case is texture2D where the mapping is Y -> 1-Y, which maps [0, 1] -> [1, 0].
+        //
+        // The texture2DProj functions are more complicated because the projection divides by either Z or W. For the vec3
+        // case, the mapping is Y -> Z-Y or Y/Z -> 1-Y/Z, which again maps [0, 1] -> [1, 0].
+        //
+        // For cube textures the mapping is Y -> -Y, which maps [-1, 1] -> [1, -1]. This is not sufficient on its own for the
+        // +Y and -Y faces, which are now on the "wrong sides" of the cube. This is compensated for by exchanging the
+        // +Y and -Y faces everywhere else throughout the code.
+        
+        if (mUsesTexture2D)
+        {
+            out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
+                   "{\n"
+                   "    return tex2Dlod(s, float4(t.x, 1 - t.y, 0, 0));\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTexture2DLod)
+        {
+            out << "float4 gl_texture2DLod(sampler2D s, float2 t, float lod)\n"
+                   "{\n"
+                   "    return tex2Dlod(s, float4(t.x, 1 - t.y, 0, lod));\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTexture2DProj)
+        {
+            out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
+                   "{\n"
+                   "    return tex2Dlod(s, float4(t.x / t.z, 1 - t.y / t.z, 0, 0));\n"
+                   "}\n"
+                   "\n"
+                   "float4 gl_texture2DProj(sampler2D s, float4 t)\n"
+                   "{\n"
+                   "    return tex2Dlod(s, float4(t.x / t.w, 1 - t.y / t.w, 0, 0));\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTexture2DProjLod)
+        {
+            out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n"
+                   "{\n"
+                   "    return tex2Dlod(s, float4(t.x / t.z, 1 - t.y / t.z, 0, lod));\n"
+                   "}\n"
+                   "\n"
+                   "float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n"
+                   "{\n"
+                   "    return tex2Dlod(s, float4(t.x / t.w, 1 - t.y / t.w, 0, lod));\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTextureCube)
+        {
+            out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
+                   "{\n"
+                   "    return texCUBElod(s, float4(t.x, -t.y, t.z, 0));\n"
+                   "}\n"
+                   "\n";
+        }
+
+        if (mUsesTextureCubeLod)
+        {
+            out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n"
+                   "{\n"
+                   "    return texCUBElod(s, float4(t.x, -t.y, t.z, lod));\n"
+                   "}\n"
+                   "\n";
+        }
+    }
+
+    if (mUsesFragCoord)
+    {
+        out << "#define GL_USES_FRAG_COORD\n";
+    }
+
+    if (mUsesPointCoord)
+    {
+        out << "#define GL_USES_POINT_COORD\n";
+    }
+
+    if (mUsesFrontFacing)
+    {
+        out << "#define GL_USES_FRONT_FACING\n";
+    }
+
+    if (mUsesPointSize)
+    {
+        out << "#define GL_USES_POINT_SIZE\n";
+    }
+
+    if (mUsesDepthRange)
+    {
+        out << "struct gl_DepthRangeParameters\n"
+               "{\n"
+               "    float near;\n"
+               "    float far;\n"
+               "    float diff;\n"
+               "};\n"
+               "\n"
+               "uniform float3 dx_DepthRange;"
+               "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
+               "\n";
+    }
+
+    if (mUsesXor)
+    {
+        out << "bool xor(bool p, bool q)\n"
+               "{\n"
+               "    return (p || q) && !(p && q);\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesMod1)
+    {
+        out << "float mod(float x, float y)\n"
+               "{\n"
+               "    return x - y * floor(x / y);\n"
+               "}\n"
+               "\n";
+    }
+    
+    if (mUsesMod2)
+    {
+        out << "float2 mod(float2 x, float y)\n"
+               "{\n"
+               "    return x - y * floor(x / y);\n"
+               "}\n"
+               "\n";
+    }
+    
+    if (mUsesMod3)
+    {
+        out << "float3 mod(float3 x, float y)\n"
+               "{\n"
+               "    return x - y * floor(x / y);\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesMod4)
+    {
+        out << "float4 mod(float4 x, float y)\n"
+               "{\n"
+               "    return x - y * floor(x / y);\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesFaceforward1)
+    {
+        out << "float faceforward(float N, float I, float Nref)\n"
+               "{\n"
+               "    if(dot(Nref, I) >= 0)\n"
+               "    {\n"
+               "        return -N;\n"
+               "    }\n"
+               "    else\n"
+               "    {\n"
+               "        return N;\n"
+               "    }\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesFaceforward2)
+    {
+        out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n"
+               "{\n"
+               "    if(dot(Nref, I) >= 0)\n"
+               "    {\n"
+               "        return -N;\n"
+               "    }\n"
+               "    else\n"
+               "    {\n"
+               "        return N;\n"
+               "    }\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesFaceforward3)
+    {
+        out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n"
+               "{\n"
+               "    if(dot(Nref, I) >= 0)\n"
+               "    {\n"
+               "        return -N;\n"
+               "    }\n"
+               "    else\n"
+               "    {\n"
+               "        return N;\n"
+               "    }\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesFaceforward4)
+    {
+        out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n"
+               "{\n"
+               "    if(dot(Nref, I) >= 0)\n"
+               "    {\n"
+               "        return -N;\n"
+               "    }\n"
+               "    else\n"
+               "    {\n"
+               "        return N;\n"
+               "    }\n"
+               "}\n"
+               "\n";
+    }
+
+    if (mUsesEqualMat2)
+    {
+        out << "bool equal(float2x2 m, float2x2 n)\n"
+               "{\n"
+               "    return m[0][0] == n[0][0] && m[0][1] == n[0][1] &&\n"
+               "           m[1][0] == n[1][0] && m[1][1] == n[1][1];\n"
+               "}\n";
+    }
+
+    if (mUsesEqualMat3)
+    {
+        out << "bool equal(float3x3 m, float3x3 n)\n"
+               "{\n"
+               "    return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] &&\n"
+               "           m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] &&\n"
+               "           m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2];\n"
+               "}\n";
+    }
+
+    if (mUsesEqualMat4)
+    {
+        out << "bool equal(float4x4 m, float4x4 n)\n"
+               "{\n"
+               "    return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] && m[0][3] == n[0][3] &&\n"
+               "           m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] && m[1][3] == n[1][3] &&\n"
+               "           m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2] && m[2][3] == n[2][3] &&\n"
+               "           m[3][0] == n[3][0] && m[3][1] == n[3][1] && m[3][2] == n[3][2] && m[3][3] == n[3][3];\n"
+               "}\n";
+    }
+
+    if (mUsesEqualVec2)
+    {
+        out << "bool equal(float2 v, float2 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualVec3)
+    {
+        out << "bool equal(float3 v, float3 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y && v.z == u.z;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualVec4)
+    {
+        out << "bool equal(float4 v, float4 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualIVec2)
+    {
+        out << "bool equal(int2 v, int2 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualIVec3)
+    {
+        out << "bool equal(int3 v, int3 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y && v.z == u.z;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualIVec4)
+    {
+        out << "bool equal(int4 v, int4 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualBVec2)
+    {
+        out << "bool equal(bool2 v, bool2 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualBVec3)
+    {
+        out << "bool equal(bool3 v, bool3 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y && v.z == u.z;\n"
+               "}\n";
+    }
+
+    if (mUsesEqualBVec4)
+    {
+        out << "bool equal(bool4 v, bool4 u)\n"
+               "{\n"
+               "    return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
+               "}\n";
+    }
+
+    if (mUsesAtan2)
+    {
+        out << "float atanyx(float y, float x)\n"
+               "{\n"
+               "    if(x == 0 && y == 0) x = 1;\n"   // Avoid producing a NaN
+               "    return atan2(y, x);\n"
+               "}\n";
+    }
+}
+
+void OutputHLSL::visitSymbol(TIntermSymbol *node)
+{
+    TInfoSinkBase &out = mBody;
+
+    TString name = node->getSymbol();
+
+    if (name == "gl_FragColor")
+    {
+        out << "gl_Color[0]";
+    }
+    else if (name == "gl_FragData")
+    {
+        out << "gl_Color";
+    }
+    else if (name == "gl_DepthRange")
+    {
+        mUsesDepthRange = true;
+        out << name;
+    }
+    else if (name == "gl_FragCoord")
+    {
+        mUsesFragCoord = true;
+        out << name;
+    }
+    else if (name == "gl_PointCoord")
+    {
+        mUsesPointCoord = true;
+        out << name;
+    }
+    else if (name == "gl_FrontFacing")
+    {
+        mUsesFrontFacing = true;
+        out << name;
+    }
+    else if (name == "gl_PointSize")
+    {
+        mUsesPointSize = true;
+        out << name;
+    }
+    else
+    {
+        TQualifier qualifier = node->getQualifier();
+
+        if (qualifier == EvqUniform)
+        {
+            mReferencedUniforms.insert(name.c_str());
+            out << decorateUniform(name, node->isArray());
+        }
+        else if (qualifier == EvqAttribute)
+        {
+            mReferencedAttributes.insert(name.c_str());
+            out << decorate(name);
+        }
+        else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
+        {
+            mReferencedVaryings.insert(name.c_str());
+            out << decorate(name);
+        }
+        else
+        {
+            out << decorate(name);
+        }
+    }
+}
+
+bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
+{
+    TInfoSinkBase &out = mBody;
+
+    switch (node->getOp())
+    {
+      case EOpAssign:                  outputTriplet(visit, "(", " = ", ")");           break;
+      case EOpInitialize:
+        if (visit == PreVisit)
+        {
+            // GLSL allows to write things like "float x = x;" where a new variable x is defined
+            // and the value of an existing variable x is assigned. HLSL uses C semantics (the
+            // new variable is created before the assignment is evaluated), so we need to convert
+            // this to "float t = x, x = t;".
+
+            TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode();
+            TIntermTyped *expression = node->getRight();
+
+            sh::SearchSymbol searchSymbol(symbolNode->getSymbol());
+            expression->traverse(&searchSymbol);
+            bool sameSymbol = searchSymbol.foundMatch();
+
+            if (sameSymbol)
+            {
+                // Type already printed
+                out << "t" + str(mUniqueIndex) + " = ";
+                expression->traverse(this);
+                out << ", ";
+                symbolNode->traverse(this);
+                out << " = t" + str(mUniqueIndex);
+
+                mUniqueIndex++;
+                return false;
+            }
+        }
+        else if (visit == InVisit)
+        {
+            out << " = ";
+        }
+        break;
+      case EOpAddAssign:               outputTriplet(visit, "(", " += ", ")");          break;
+      case EOpSubAssign:               outputTriplet(visit, "(", " -= ", ")");          break;
+      case EOpMulAssign:               outputTriplet(visit, "(", " *= ", ")");          break;
+      case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")");          break;
+      case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")");          break;
+      case EOpVectorTimesMatrixAssign:
+        if (visit == PreVisit)
+        {
+            out << "(";
+        }
+        else if (visit == InVisit)
+        {
+            out << " = mul(";
+            node->getLeft()->traverse(this);
+            out << ", transpose(";   
+        }
+        else
+        {
+            out << ")))";
+        }
+        break;
+      case EOpMatrixTimesMatrixAssign:
+        if (visit == PreVisit)
+        {
+            out << "(";
+        }
+        else if (visit == InVisit)
+        {
+            out << " = mul(";
+            node->getLeft()->traverse(this);
+            out << ", ";   
+        }
+        else
+        {
+            out << "))";
+        }
+        break;
+      case EOpDivAssign:               outputTriplet(visit, "(", " /= ", ")");          break;
+      case EOpIndexDirect:             outputTriplet(visit, "", "[", "]");              break;
+      case EOpIndexIndirect:           outputTriplet(visit, "", "[", "]");              break;
+      case EOpIndexDirectStruct:
+        if (visit == InVisit)
+        {
+            out << "." + node->getType().getFieldName();
+
+            return false;
+        }
+        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 EOpEqual:
+      case EOpNotEqual:
+        if (node->getLeft()->isScalar())
+        {
+            if (node->getOp() == EOpEqual)
+            {
+                outputTriplet(visit, "(", " == ", ")");
+            }
+            else
+            {
+                outputTriplet(visit, "(", " != ", ")");
+            }
+        }
+        else if (node->getLeft()->getBasicType() == EbtStruct)
+        {
+            if (node->getOp() == EOpEqual)
+            {
+                out << "(";
+            }
+            else
+            {
+                out << "!(";
+            }
+
+            const TTypeList *fields = node->getLeft()->getType().getStruct();
+
+            for (size_t i = 0; i < fields->size(); i++)
+            {
+                const TType *fieldType = (*fields)[i].type;
+
+                node->getLeft()->traverse(this);
+                out << "." + fieldType->getFieldName() + " == ";
+                node->getRight()->traverse(this);
+                out << "." + fieldType->getFieldName();
+
+                if (i < fields->size() - 1)
+                {
+                    out << " && ";
+                }
+            }
+
+            out << ")";
+
+            return false;
+        }
+        else
+        {
+            if (node->getLeft()->isMatrix())
+            {
+                switch (node->getLeft()->getNominalSize())
+                {
+                  case 2: mUsesEqualMat2 = true; break;
+                  case 3: mUsesEqualMat3 = true; break;
+                  case 4: mUsesEqualMat4 = true; break;
+                  default: UNREACHABLE();
+                }
+            }
+            else if (node->getLeft()->isVector())
+            {
+                switch (node->getLeft()->getBasicType())
+                {
+                  case EbtFloat:
+                    switch (node->getLeft()->getNominalSize())
+                    {
+                      case 2: mUsesEqualVec2 = true; break;
+                      case 3: mUsesEqualVec3 = true; break;
+                      case 4: mUsesEqualVec4 = true; break;
+                      default: UNREACHABLE();
+                    }
+                    break;
+                  case EbtInt:
+                    switch (node->getLeft()->getNominalSize())
+                    {
+                      case 2: mUsesEqualIVec2 = true; break;
+                      case 3: mUsesEqualIVec3 = true; break;
+                      case 4: mUsesEqualIVec4 = true; break;
+                      default: UNREACHABLE();
+                    }
+                    break;
+                  case EbtBool:
+                    switch (node->getLeft()->getNominalSize())
+                    {
+                      case 2: mUsesEqualBVec2 = true; break;
+                      case 3: mUsesEqualBVec3 = true; break;
+                      case 4: mUsesEqualBVec4 = true; break;
+                      default: UNREACHABLE();
+                    }
+                    break;
+                  default: UNREACHABLE();
+                }
+            }
+            else UNREACHABLE();
+
+            if (node->getOp() == EOpEqual)
+            {
+                outputTriplet(visit, "equal(", ", ", ")");
+            }
+            else
+            {
+                outputTriplet(visit, "!equal(", ", ", ")");
+            }
+        }
+        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 EOpMatrixTimesScalar: outputTriplet(visit, "(", " * ", ")");   break;
+      case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break;
+      case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break;
+      case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break;
+      case EOpLogicalOr:         outputTriplet(visit, "(", " || ", ")");  break;
+      case EOpLogicalXor:
+        mUsesXor = true;
+        outputTriplet(visit, "xor(", ", ", ")");
+        break;
+      case EOpLogicalAnd:        outputTriplet(visit, "(", " && ", ")");  break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
+{
+    TInfoSinkBase &out = mBody;
+
+    switch (node->getOp())
+    {
+      case EOpNegative:         outputTriplet(visit, "(-", "", ")");  break;
+      case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")");  break;
+      case EOpLogicalNot:       outputTriplet(visit, "(!", "", ")");  break;
+      case EOpPostIncrement:    outputTriplet(visit, "(", "", "++)"); break;
+      case EOpPostDecrement:    outputTriplet(visit, "(", "", "--)"); break;
+      case EOpPreIncrement:     outputTriplet(visit, "(++", "", ")"); break;
+      case EOpPreDecrement:     outputTriplet(visit, "(--", "", ")"); break;
+      case EOpConvIntToBool:
+      case EOpConvFloatToBool:
+        switch (node->getOperand()->getType().getNominalSize())
+        {
+          case 1:    outputTriplet(visit, "bool(", "", ")");  break;
+          case 2:    outputTriplet(visit, "bool2(", "", ")"); break;
+          case 3:    outputTriplet(visit, "bool3(", "", ")"); break;
+          case 4:    outputTriplet(visit, "bool4(", "", ")"); break;
+          default: UNREACHABLE();
+        }
+        break;
+      case EOpConvBoolToFloat:
+      case EOpConvIntToFloat:
+        switch (node->getOperand()->getType().getNominalSize())
+        {
+          case 1:    outputTriplet(visit, "float(", "", ")");  break;
+          case 2:    outputTriplet(visit, "float2(", "", ")"); break;
+          case 3:    outputTriplet(visit, "float3(", "", ")"); break;
+          case 4:    outputTriplet(visit, "float4(", "", ")"); break;
+          default: UNREACHABLE();
+        }
+        break;
+      case EOpConvFloatToInt:
+      case EOpConvBoolToInt:
+        switch (node->getOperand()->getType().getNominalSize())
+        {
+          case 1:    outputTriplet(visit, "int(", "", ")");  break;
+          case 2:    outputTriplet(visit, "int2(", "", ")"); break;
+          case 3:    outputTriplet(visit, "int3(", "", ")"); break;
+          case 4:    outputTriplet(visit, "int4(", "", ")"); break;
+          default: UNREACHABLE();
+        }
+        break;
+      case EOpRadians:          outputTriplet(visit, "radians(", "", ")");   break;
+      case EOpDegrees:          outputTriplet(visit, "degrees(", "", ")");   break;
+      case EOpSin:              outputTriplet(visit, "sin(", "", ")");       break;
+      case EOpCos:              outputTriplet(visit, "cos(", "", ")");       break;
+      case EOpTan:              outputTriplet(visit, "tan(", "", ")");       break;
+      case EOpAsin:             outputTriplet(visit, "asin(", "", ")");      break;
+      case EOpAcos:             outputTriplet(visit, "acos(", "", ")");      break;
+      case EOpAtan:             outputTriplet(visit, "atan(", "", ")");      break;
+      case EOpExp:              outputTriplet(visit, "exp(", "", ")");       break;
+      case EOpLog:              outputTriplet(visit, "log(", "", ")");       break;
+      case EOpExp2:             outputTriplet(visit, "exp2(", "", ")");      break;
+      case EOpLog2:             outputTriplet(visit, "log2(", "", ")");      break;
+      case EOpSqrt:             outputTriplet(visit, "sqrt(", "", ")");      break;
+      case EOpInverseSqrt:      outputTriplet(visit, "rsqrt(", "", ")");     break;
+      case EOpAbs:              outputTriplet(visit, "abs(", "", ")");       break;
+      case EOpSign:             outputTriplet(visit, "sign(", "", ")");      break;
+      case EOpFloor:            outputTriplet(visit, "floor(", "", ")");     break;
+      case EOpCeil:             outputTriplet(visit, "ceil(", "", ")");      break;
+      case EOpFract:            outputTriplet(visit, "frac(", "", ")");      break;
+      case EOpLength:           outputTriplet(visit, "length(", "", ")");    break;
+      case EOpNormalize:        outputTriplet(visit, "normalize(", "", ")"); break;
+      case EOpDFdx:             outputTriplet(visit, "ddx(", "", ")");       break;
+      case EOpDFdy:             outputTriplet(visit, "(-ddy(", "", "))");    break;
+      case EOpFwidth:           outputTriplet(visit, "fwidth(", "", ")");    break;        
+      case EOpAny:              outputTriplet(visit, "any(", "", ")");       break;
+      case EOpAll:              outputTriplet(visit, "all(", "", ")");       break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+    ShShaderType shaderType = mContext.shaderType;
+    TInfoSinkBase &out = mBody;
+
+    switch (node->getOp())
+    {
+      case EOpSequence:
+        {
+            if (mInsideFunction)
+            {
+                outputLineDirective(node->getLine());
+                out << "{\n";
+
+                mScopeDepth++;
+
+                if (mScopeBracket.size() < mScopeDepth)
+                {
+                    mScopeBracket.push_back(0);   // New scope level
+                }
+                else
+                {
+                    mScopeBracket[mScopeDepth - 1]++;   // New scope at existing level
+                }
+            }
+
+            for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++)
+            {
+                outputLineDirective((*sit)->getLine());
+
+                if (isSingleStatement(*sit))
+                {
+                    mUnfoldSelect->traverse(*sit);
+                }
+
+                (*sit)->traverse(this);
+
+                out << ";\n";
+            }
+
+            if (mInsideFunction)
+            {
+                outputLineDirective(node->getEndLine());
+                out << "}\n";
+
+                mScopeDepth--;
+            }
+
+            return false;
+        }
+      case EOpDeclaration:
+        if (visit == PreVisit)
+        {
+            TIntermSequence &sequence = node->getSequence();
+            TIntermTyped *variable = sequence[0]->getAsTyped();
+            bool visit = true;
+
+            if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal))
+            {
+                if (variable->getType().getStruct())
+                {
+                    addConstructor(variable->getType(), scopedStruct(variable->getType().getTypeName()), NULL);
+                }
+
+                if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "")   // Variable declaration
+                {
+                    if (!mInsideFunction)
+                    {
+                        out << "static ";
+                    }
+
+                    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());
+                            out << " = " + initializer(variable->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);
+                    }
+                }
+                else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "")   // Type (struct) declaration
+                {
+                    // Already added to constructor map
+                }
+                else UNREACHABLE();
+            }
+            
+            return false;
+        }
+        else if (visit == InVisit)
+        {
+            out << ", ";
+        }
+        break;
+      case EOpPrototype:
+        if (visit == PreVisit)
+        {
+            out << typeString(node->getType()) << " " << decorate(node->getName()) << "(";
+
+            TIntermSequence &arguments = node->getSequence();
+
+            for (unsigned int i = 0; i < arguments.size(); i++)
+            {
+                TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
+
+                if (symbol)
+                {
+                    out << argumentString(symbol);
+
+                    if (i < arguments.size() - 1)
+                    {
+                        out << ", ";
+                    }
+                }
+                else UNREACHABLE();
+            }
+
+            out << ");\n";
+
+            return false;
+        }
+        break;
+      case EOpComma:            outputTriplet(visit, "", ", ", "");                break;
+      case EOpFunction:
+        {
+            TString name = TFunction::unmangleName(node->getName());
+
+            if (visit == PreVisit)
+            {
+                out << typeString(node->getType()) << " ";
+
+                if (name == "main")
+                {
+                    out << "gl_main(";
+                }
+                else
+                {
+                    out << decorate(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)
+                    {
+                        out << argumentString(symbol);
+
+                        if (i < arguments.size() - 1)
+                        {
+                            out << ", ";
+                        }
+                    }
+                    else UNREACHABLE();
+                }
+
+                sequence.erase(sequence.begin());
+
+                out << ")\n";
+                
+                outputLineDirective(node->getLine());
+                out << "{\n";
+                
+                mInsideFunction = true;
+            }
+            else if (visit == PostVisit)
+            {
+                outputLineDirective(node->getEndLine());
+                out << "}\n";
+
+                mInsideFunction = false;
+            }
+        }
+        break;
+      case EOpFunctionCall:
+        {
+            if (visit == PreVisit)
+            {
+                TString name = TFunction::unmangleName(node->getName());
+
+                if (node->isUserDefined())
+                {
+                    out << decorate(name) << "(";
+                }
+                else
+                {
+                    if (name == "texture2D")
+                    {
+                        if (node->getSequence().size() == 2)
+                        {
+                            mUsesTexture2D = true;
+                        }
+                        else if (node->getSequence().size() == 3)
+                        {
+                            mUsesTexture2D_bias = true;
+                        }
+                        else UNREACHABLE();
+
+                        out << "gl_texture2D(";
+                    }
+                    else if (name == "texture2DProj")
+                    {
+                        if (node->getSequence().size() == 2)
+                        {
+                            mUsesTexture2DProj = true;
+                        }
+                        else if (node->getSequence().size() == 3)
+                        {
+                            mUsesTexture2DProj_bias = true;
+                        }
+                        else UNREACHABLE();
+
+                        out << "gl_texture2DProj(";
+                    }
+                    else if (name == "textureCube")
+                    {
+                        if (node->getSequence().size() == 2)
+                        {
+                            mUsesTextureCube = true;
+                        }
+                        else if (node->getSequence().size() == 3)
+                        {
+                            mUsesTextureCube_bias = true;
+                        }
+                        else UNREACHABLE();
+
+                        out << "gl_textureCube(";
+                    }
+                    else if (name == "texture2DLod")
+                    {
+                        if (node->getSequence().size() == 3)
+                        {
+                            mUsesTexture2DLod = true;
+                        }
+                        else UNREACHABLE();
+
+                        out << "gl_texture2DLod(";
+                    }
+                    else if (name == "texture2DProjLod")
+                    {
+                        if (node->getSequence().size() == 3)
+                        {
+                            mUsesTexture2DProjLod = true;
+                        }
+                        else UNREACHABLE();
+
+                        out << "gl_texture2DProjLod(";
+                    }
+                    else if (name == "textureCubeLod")
+                    {
+                        if (node->getSequence().size() == 3)
+                        {
+                            mUsesTextureCubeLod = true;
+                        }
+                        else UNREACHABLE();
+
+                        out << "gl_textureCubeLod(";
+                    }
+                    else UNREACHABLE();
+                }
+            }
+            else if (visit == InVisit)
+            {
+                out << ", ";
+            }
+            else
+            {
+                out << ")";
+            }
+        }
+        break;
+      case EOpParameters:       outputTriplet(visit, "(", ", ", ")\n{\n");             break;
+      case EOpConstructFloat:
+        addConstructor(node->getType(), "vec1", &node->getSequence());
+        outputTriplet(visit, "vec1(", "", ")");
+        break;
+      case EOpConstructVec2:
+        addConstructor(node->getType(), "vec2", &node->getSequence());
+        outputTriplet(visit, "vec2(", ", ", ")");
+        break;
+      case EOpConstructVec3:
+        addConstructor(node->getType(), "vec3", &node->getSequence());
+        outputTriplet(visit, "vec3(", ", ", ")");
+        break;
+      case EOpConstructVec4:
+        addConstructor(node->getType(), "vec4", &node->getSequence());
+        outputTriplet(visit, "vec4(", ", ", ")");
+        break;
+      case EOpConstructBool:
+        addConstructor(node->getType(), "bvec1", &node->getSequence());
+        outputTriplet(visit, "bvec1(", "", ")");
+        break;
+      case EOpConstructBVec2:
+        addConstructor(node->getType(), "bvec2", &node->getSequence());
+        outputTriplet(visit, "bvec2(", ", ", ")");
+        break;
+      case EOpConstructBVec3:
+        addConstructor(node->getType(), "bvec3", &node->getSequence());
+        outputTriplet(visit, "bvec3(", ", ", ")");
+        break;
+      case EOpConstructBVec4:
+        addConstructor(node->getType(), "bvec4", &node->getSequence());
+        outputTriplet(visit, "bvec4(", ", ", ")");
+        break;
+      case EOpConstructInt:
+        addConstructor(node->getType(), "ivec1", &node->getSequence());
+        outputTriplet(visit, "ivec1(", "", ")");
+        break;
+      case EOpConstructIVec2:
+        addConstructor(node->getType(), "ivec2", &node->getSequence());
+        outputTriplet(visit, "ivec2(", ", ", ")");
+        break;
+      case EOpConstructIVec3:
+        addConstructor(node->getType(), "ivec3", &node->getSequence());
+        outputTriplet(visit, "ivec3(", ", ", ")");
+        break;
+      case EOpConstructIVec4:
+        addConstructor(node->getType(), "ivec4", &node->getSequence());
+        outputTriplet(visit, "ivec4(", ", ", ")");
+        break;
+      case EOpConstructMat2:
+        addConstructor(node->getType(), "mat2", &node->getSequence());
+        outputTriplet(visit, "mat2(", ", ", ")");
+        break;
+      case EOpConstructMat3:
+        addConstructor(node->getType(), "mat3", &node->getSequence());
+        outputTriplet(visit, "mat3(", ", ", ")");
+        break;
+      case EOpConstructMat4: 
+        addConstructor(node->getType(), "mat4", &node->getSequence());
+        outputTriplet(visit, "mat4(", ", ", ")");
+        break;
+      case EOpConstructStruct:
+        addConstructor(node->getType(), scopedStruct(node->getType().getTypeName()), &node->getSequence());
+        outputTriplet(visit, structLookup(node->getType().getTypeName()) + "_ctor(", ", ", ")");
+        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:
+        {
+            switch (node->getSequence()[0]->getAsTyped()->getNominalSize())   // Number of components in the first argument
+            {
+              case 1: mUsesMod1 = true; break;
+              case 2: mUsesMod2 = true; break;
+              case 3: mUsesMod3 = true; break;
+              case 4: mUsesMod4 = true; break;
+              default: UNREACHABLE();
+            }
+
+            outputTriplet(visit, "mod(", ", ", ")");
+        }
+        break;
+      case EOpPow:              outputTriplet(visit, "pow(", ", ", ")");               break;
+      case EOpAtan:
+        ASSERT(node->getSequence().size() == 2);   // atan(x) is a unary operator
+        mUsesAtan2 = true;
+        outputTriplet(visit, "atanyx(", ", ", ")");
+        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:
+        {
+            switch (node->getSequence()[0]->getAsTyped()->getNominalSize())   // Number of components in the first argument
+            {
+            case 1: mUsesFaceforward1 = true; break;
+            case 2: mUsesFaceforward2 = true; break;
+            case 3: mUsesFaceforward3 = true; break;
+            case 4: mUsesFaceforward4 = true; break;
+            default: UNREACHABLE();
+            }
+            
+            outputTriplet(visit, "faceforward(", ", ", ")");
+        }
+        break;
+      case EOpReflect:       outputTriplet(visit, "reflect(", ", ", ")");       break;
+      case EOpRefract:       outputTriplet(visit, "refract(", ", ", ")");       break;
+      case EOpMul:           outputTriplet(visit, "(", " * ", ")");             break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
+{
+    TInfoSinkBase &out = mBody;
+
+    if (node->usesTernaryOperator())
+    {
+        out << "s" << mUnfoldSelect->getNextTemporaryIndex();
+    }
+    else  // if/else statement
+    {
+        mUnfoldSelect->traverse(node->getCondition());
+
+        out << "if(";
+
+        node->getCondition()->traverse(this);
+
+        out << ")\n";
+        
+        outputLineDirective(node->getLine());
+        out << "{\n";
+
+        if (node->getTrueBlock())
+        {
+            node->getTrueBlock()->traverse(this);
+        }
+
+        outputLineDirective(node->getLine());
+        out << ";}\n";
+
+        if (node->getFalseBlock())
+        {
+            out << "else\n";
+
+            outputLineDirective(node->getFalseBlock()->getLine());
+            out << "{\n";
+
+            outputLineDirective(node->getFalseBlock()->getLine());
+            node->getFalseBlock()->traverse(this);
+
+            outputLineDirective(node->getFalseBlock()->getLine());
+            out << ";}\n";
+        }
+    }
+
+    return false;
+}
+
+void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
+{
+    writeConstantUnion(node->getType(), node->getUnionArrayPointer());
+}
+
+bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
+{
+    if (handleExcessiveLoop(node))
+    {
+        return false;
+    }
+
+    TInfoSinkBase &out = mBody;
+
+    if (node->getType() == ELoopDoWhile)
+    {
+        out << "do\n";
+
+        outputLineDirective(node->getLine());
+        out << "{\n";
+    }
+    else
+    {
+        out << "for(";
+        
+        if (node->getInit())
+        {
+            node->getInit()->traverse(this);
+        }
+
+        out << "; ";
+
+        if (node->getCondition())
+        {
+            node->getCondition()->traverse(this);
+        }
+
+        out << "; ";
+
+        if (node->getExpression())
+        {
+            node->getExpression()->traverse(this);
+        }
+
+        out << ")\n";
+        
+        outputLineDirective(node->getLine());
+        out << "{\n";
+    }
+
+    if (node->getBody())
+    {
+        node->getBody()->traverse(this);
+    }
+
+    outputLineDirective(node->getLine());
+    out << ";}\n";
+
+    if (node->getType() == ELoopDoWhile)
+    {
+        outputLineDirective(node->getCondition()->getLine());
+        out << "while(\n";
+
+        node->getCondition()->traverse(this);
+
+        out << ")";
+    }
+
+    out << ";\n";
+
+    return false;
+}
+
+bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
+{
+    TInfoSinkBase &out = mBody;
+
+    switch (node->getFlowOp())
+    {
+      case EOpKill:     outputTriplet(visit, "discard;\n", "", "");  break;
+      case EOpBreak:    outputTriplet(visit, "break;\n", "", "");    break;
+      case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break;
+      case EOpReturn:
+        if (visit == PreVisit)
+        {
+            if (node->getExpression())
+            {
+                out << "return ";
+            }
+            else
+            {
+                out << "return;\n";
+            }
+        }
+        else if (visit == PostVisit)
+        {
+            if (node->getExpression())
+            {
+                out << ";\n";
+            }
+        }
+        break;
+      default: UNREACHABLE();
+    }
+
+    return true;
+}
+
+bool OutputHLSL::isSingleStatement(TIntermNode *node)
+{
+    TIntermAggregate *aggregate = node->getAsAggregate();
+
+    if (aggregate)
+    {
+        if (aggregate->getOp() == EOpSequence)
+        {
+            return false;
+        }
+        else
+        {
+            for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++)
+            {
+                if (!isSingleStatement(*sit))
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+    }
+
+    return true;
+}
+
+// Handle loops with more than 255 iterations (unsupported by D3D9) by splitting them
+bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
+{
+    TInfoSinkBase &out = mBody;
+
+    // Parse loops of the form:
+    // for(int index = initial; index [comparator] limit; index += increment)
+    TIntermSymbol *index = NULL;
+    TOperator comparator = EOpNull;
+    int initial = 0;
+    int limit = 0;
+    int increment = 0;
+
+    // Parse index name and intial value
+    if (node->getInit())
+    {
+        TIntermAggregate *init = node->getInit()->getAsAggregate();
+
+        if (init)
+        {
+            TIntermSequence &sequence = init->getSequence();
+            TIntermTyped *variable = sequence[0]->getAsTyped();
+
+            if (variable && variable->getQualifier() == EvqTemporary)
+            {
+                TIntermBinary *assign = variable->getAsBinaryNode();
+
+                if (assign->getOp() == EOpInitialize)
+                {
+                    TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode();
+                    TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion();
+
+                    if (symbol && constant)
+                    {
+                        if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
+                        {
+                            index = symbol;
+                            initial = constant->getUnionArrayPointer()[0].getIConst();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // Parse comparator and limit value
+    if (index != NULL && node->getCondition())
+    {
+        TIntermBinary *test = node->getCondition()->getAsBinaryNode();
+        
+        if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId())
+        {
+            TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion();
+
+            if (constant)
+            {
+                if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
+                {
+                    comparator = test->getOp();
+                    limit = constant->getUnionArrayPointer()[0].getIConst();
+                }
+            }
+        }
+    }
+
+    // Parse increment
+    if (index != NULL && comparator != EOpNull && node->getExpression())
+    {
+        TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode();
+        TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode();
+        
+        if (binaryTerminal)
+        {
+            TOperator op = binaryTerminal->getOp();
+            TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion();
+
+            if (constant)
+            {
+                if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
+                {
+                    int value = constant->getUnionArrayPointer()[0].getIConst();
+
+                    switch (op)
+                    {
+                      case EOpAddAssign: increment = value;  break;
+                      case EOpSubAssign: increment = -value; break;
+                      default: UNIMPLEMENTED();
+                    }
+                }
+            }
+        }
+        else if (unaryTerminal)
+        {
+            TOperator op = unaryTerminal->getOp();
+
+            switch (op)
+            {
+              case EOpPostIncrement: increment = 1;  break;
+              case EOpPostDecrement: increment = -1; break;
+              case EOpPreIncrement:  increment = 1;  break;
+              case EOpPreDecrement:  increment = -1; break;
+              default: UNIMPLEMENTED();
+            }
+        }
+    }
+
+    if (index != NULL && comparator != EOpNull && increment != 0)
+    {
+        if (comparator == EOpLessThanEqual)
+        {
+            comparator = EOpLessThan;
+            limit += 1;
+        }
+
+        if (comparator == EOpLessThan)
+        {
+            int iterations = (limit - initial) / increment;
+
+            if (iterations <= 255)
+            {
+                return false;   // Not an excessive loop
+            }
+
+            while (iterations > 0)
+            {
+                int remainder = (limit - initial) % increment;
+                int clampedLimit = initial + increment * std::min(255, iterations);
+
+                // for(int index = initial; index < clampedLimit; index += increment)
+
+                out << "for(int ";
+                index->traverse(this);
+                out << " = ";
+                out << initial;
+
+                out << "; ";
+                index->traverse(this);
+                out << " < ";
+                out << clampedLimit;
+
+                out << "; ";
+                index->traverse(this);
+                out << " += ";
+                out << increment;
+                out << ")\n";
+                
+                outputLineDirective(node->getLine());
+                out << "{\n";
+
+                if (node->getBody())
+                {
+                    node->getBody()->traverse(this);
+                }
+
+                outputLineDirective(node->getLine());
+                out << ";}\n";
+
+                initial += 255 * increment;
+                iterations -= 255;
+            }
+
+            return true;
+        }
+        else UNIMPLEMENTED();
+    }
+
+    return false;   // Not handled as an excessive loop
+}
+
+void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString)
+{
+    TInfoSinkBase &out = mBody;
+
+    if (visit == PreVisit)
+    {
+        out << preString;
+    }
+    else if (visit == InVisit)
+    {
+        out << inString;
+    }
+    else if (visit == PostVisit)
+    {
+        out << postString;
+    }
+}
+
+void OutputHLSL::outputLineDirective(int line)
+{
+    if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0))
+    {
+        mBody << "\n";
+        mBody << "#line " << line;
+
+        if (mContext.sourcePath)
+        {
+            mBody << " \"" << mContext.sourcePath << "\"";
+        }
+        
+        mBody << "\n";
+    }
+}
+
+TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
+{
+    TQualifier qualifier = symbol->getQualifier();
+    const TType &type = symbol->getType();
+    TString name = symbol->getSymbol();
+
+    if (name.empty())   // HLSL demands named arguments, also for prototypes
+    {
+        name = "x" + str(mUniqueIndex++);
+    }
+    else
+    {
+        name = decorate(name);
+    }
+
+    return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type);
+}
+
+TString OutputHLSL::qualifierString(TQualifier qualifier)
+{
+    switch(qualifier)
+    {
+      case EvqIn:            return "in";
+      case EvqOut:           return "out";
+      case EvqInOut:         return "inout";
+      case EvqConstReadOnly: return "const";
+      default: UNREACHABLE();
+    }
+
+    return "";
+}
+
+TString OutputHLSL::typeString(const TType &type)
+{
+    if (type.getBasicType() == EbtStruct)
+    {
+        if (type.getTypeName() != "")
+        {
+            return structLookup(type.getTypeName());
+        }
+        else   // Nameless structure, define in place
+        {
+            const TTypeList &fields = *type.getStruct();
+
+            TString string = "struct\n"
+                             "{\n";
+
+            for (unsigned int i = 0; i < fields.size(); i++)
+            {
+                const TType &field = *fields[i].type;
+
+                string += "    " + typeString(field) + " " + field.getFieldName() + arrayString(field) + ";\n";
+            }
+
+            string += "} ";
+
+            return string;
+        }
+    }
+    else 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 "";
+    }
+
+    return "[" + str(type.getArraySize()) + "]";
+}
+
+TString OutputHLSL::initializer(const TType &type)
+{
+    TString string;
+
+    for (int component = 0; component < type.getObjectSize(); component++)
+    {
+        string += "0";
+
+        if (component < type.getObjectSize() - 1)
+        {
+            string += ", ";
+        }
+    }
+
+    return "{" + string + "}";
+}
+
+void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters)
+{
+    if (name == "")
+    {
+        return;   // Nameless structures don't have constructors
+    }
+
+    TType ctorType = type;
+    ctorType.clearArrayness();
+    ctorType.setPrecision(EbpHigh);
+    ctorType.setQualifier(EvqTemporary);
+
+    TString ctorName = type.getStruct() ? decorate(name) : name;
+
+    typedef std::vector<TType> ParameterArray;
+    ParameterArray ctorParameters;
+
+    if (type.getStruct())
+    {
+        mStructNames.insert(decorate(name));
+
+        TString structure;
+        structure += "struct " + decorate(name) + "\n"
+                     "{\n";
+
+        const TTypeList &fields = *type.getStruct();
+
+        for (unsigned int i = 0; i < fields.size(); i++)
+        {
+            const TType &field = *fields[i].type;
+
+            structure += "    " + typeString(field) + " " + field.getFieldName() + arrayString(field) + ";\n";
+        }
+
+        structure += "};\n";
+
+        if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end())
+        {
+            mStructDeclarations.push_back(structure);
+        }
+
+        for (unsigned int i = 0; i < fields.size(); i++)
+        {
+            ctorParameters.push_back(*fields[i].type);
+        }
+    }
+    else if (parameters)
+    {
+        for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++)
+        {
+            ctorParameters.push_back((*parameter)->getAsTyped()->getType());
+        }
+    }
+    else UNREACHABLE();
+
+    TString constructor;
+
+    if (ctorType.getStruct())
+    {
+        constructor += ctorName + " " + ctorName + "_ctor(";
+    }
+    else   // Built-in type
+    {
+        constructor += typeString(ctorType) + " " + ctorName + "(";
+    }
+
+    for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++)
+    {
+        const TType &type = ctorParameters[parameter];
+
+        constructor += typeString(type) + " x" + str(parameter) + arrayString(type);
+
+        if (parameter < ctorParameters.size() - 1)
+        {
+            constructor += ", ";
+        }
+    }
+
+    constructor += ")\n"
+                   "{\n";
+
+    if (ctorType.getStruct())
+    {
+        constructor += "    " + ctorName + " structure = {";
+    }
+    else
+    {
+        constructor += "    return " + typeString(ctorType) + "(";
+    }
+
+    if (ctorType.isMatrix() && ctorParameters.size() == 1)
+    {
+        int dim = ctorType.getNominalSize();
+        const TType &parameter = ctorParameters[0];
+
+        if (parameter.isScalar())
+        {
+            for (int row = 0; row < dim; row++)
+            {
+                for (int col = 0; col < dim; col++)
+                {
+                    constructor += TString((row == col) ? "x0" : "0.0");
+                    
+                    if (row < dim - 1 || col < dim - 1)
+                    {
+                        constructor += ", ";
+                    }
+                }
+            }
+        }
+        else if (parameter.isMatrix())
+        {
+            for (int row = 0; row < dim; row++)
+            {
+                for (int col = 0; col < dim; col++)
+                {
+                    if (row < parameter.getNominalSize() && col < parameter.getNominalSize())
+                    {
+                        constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]";
+                    }
+                    else
+                    {
+                        constructor += TString((row == col) ? "1.0" : "0.0");
+                    }
+
+                    if (row < dim - 1 || col < dim - 1)
+                    {
+                        constructor += ", ";
+                    }
+                }
+            }
+        }
+        else UNREACHABLE();
+    }
+    else
+    {
+        int remainingComponents = ctorType.getObjectSize();
+        int parameterIndex = 0;
+
+        while (remainingComponents > 0)
+        {
+            const TType &parameter = ctorParameters[parameterIndex];
+            bool moreParameters = parameterIndex < (int)ctorParameters.size() - 1;
+
+            constructor += "x" + str(parameterIndex);
+
+            if (parameter.isScalar())
+            {
+                remainingComponents -= parameter.getObjectSize();
+            }
+            else if (parameter.isVector())
+            {
+                if (remainingComponents == parameter.getObjectSize() || moreParameters)
+                {
+                    remainingComponents -= parameter.getObjectSize();
+                }
+                else if (remainingComponents < parameter.getNominalSize())
+                {
+                    switch (remainingComponents)
+                    {
+                      case 1: constructor += ".x";    break;
+                      case 2: constructor += ".xy";   break;
+                      case 3: constructor += ".xyz";  break;
+                      case 4: constructor += ".xyzw"; break;
+                      default: UNREACHABLE();
+                    }
+
+                    remainingComponents = 0;
+                }
+                else UNREACHABLE();
+            }
+            else if (parameter.isMatrix() || parameter.getStruct())
+            {
+                ASSERT(remainingComponents == parameter.getObjectSize() || moreParameters);
+                
+                remainingComponents -= parameter.getObjectSize();
+            }
+            else UNREACHABLE();
+
+            if (moreParameters)
+            {
+                parameterIndex++;
+            }
+
+            if (remainingComponents)
+            {
+                constructor += ", ";
+            }
+        }
+    }
+
+    if (ctorType.getStruct())
+    {
+        constructor += "};\n"
+                       "    return structure;\n"
+                       "}\n";
+    }
+    else
+    {
+        constructor += ");\n"
+                       "}\n";
+    }
+
+    mConstructors.insert(constructor);
+}
+
+const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion)
+{
+    TInfoSinkBase &out = mBody;
+
+    if (type.getBasicType() == EbtStruct)
+    {
+        out << structLookup(type.getTypeName()) + "_ctor(";
+        
+        const TTypeList *structure = type.getStruct();
+
+        for (size_t i = 0; i < structure->size(); i++)
+        {
+            const TType *fieldType = (*structure)[i].type;
+
+            constUnion = writeConstantUnion(*fieldType, constUnion);
+
+            if (i != structure->size() - 1)
+            {
+                out << ", ";
+            }
+        }
+
+        out << ")";
+    }
+    else
+    {
+        int size = type.getObjectSize();
+        bool writeType = size > 1;
+        
+        if (writeType)
+        {
+            out << typeString(type) << "(";
+        }
+
+        for (int i = 0; i < size; i++, constUnion++)
+        {
+            switch (constUnion->getType())
+            {
+              case EbtFloat: out << constUnion->getFConst(); break;
+              case EbtInt:   out << constUnion->getIConst(); break;
+              case EbtBool:  out << constUnion->getBConst(); break;
+              default: UNREACHABLE();
+            }
+
+            if (i != size - 1)
+            {
+                out << ", ";
+            }
+        }
+
+        if (writeType)
+        {
+            out << ")";
+        }
+    }
+
+    return constUnion;
+}
+
+TString OutputHLSL::scopeString(unsigned int depthLimit)
+{
+    TString string;
+
+    for (unsigned int i = 0; i < mScopeBracket.size() && i < depthLimit; i++)
+    {
+        string += "_" + str(i);
+    }
+
+    return string;
+}
+
+TString OutputHLSL::scopedStruct(const TString &typeName)
+{
+    if (typeName == "")
+    {
+        return typeName;
+    }
+
+    return typeName + scopeString(mScopeDepth);
+}
+
+TString OutputHLSL::structLookup(const TString &typeName)
+{
+    for (int depth = mScopeDepth; depth >= 0; depth--)
+    {
+        TString scopedName = decorate(typeName + scopeString(depth));
+
+        for (StructNames::iterator structName = mStructNames.begin(); structName != mStructNames.end(); structName++)
+        {
+            if (*structName == scopedName)
+            {
+                return scopedName;
+            }
+        }
+    }
+
+    UNREACHABLE();   // Should have found a matching constructor
+
+    return typeName;
+}
+
+TString OutputHLSL::decorate(const TString &string)
+{
+    if (string.compare(0, 3, "gl_") != 0 && string.compare(0, 3, "dx_") != 0)
+    {
+        return "_" + string;
+    }
+    
+    return string;
+}
+
+TString OutputHLSL::decorateUniform(const TString &string, bool array)
+{
+    if (array)
+    {
+        return "ar_" + string;   // Allows identifying arrays of size 1
+    }
+    
+    return decorate(string);
+}
+}
diff --git a/src/OpenGL ES 2.0/compiler/OutputHLSL.h b/src/OpenGL ES 2.0/compiler/OutputHLSL.h
new file mode 100644
index 0000000..b1058bd
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/OutputHLSL.h
@@ -0,0 +1,132 @@
+//
+// Copyright (c) 2002-2011 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 <list>
+#include <set>
+
+#include "compiler/intermediate.h"
+#include "compiler/ParseHelper.h"
+
+namespace sh
+{
+class UnfoldSelect;
+
+class OutputHLSL : public TIntermTraverser
+{
+  public:
+    explicit OutputHLSL(TParseContext &context);
+    ~OutputHLSL();
+
+    void output();
+
+    TInfoSinkBase &getBodyStream();
+
+    TString typeString(const TType &type);
+    static TString qualifierString(TQualifier qualifier);
+    static TString arrayString(const TType &type);
+    static TString initializer(const TType &type);
+    static TString decorate(const TString &string);                      // Prepends an underscore to avoid naming clashes
+    static TString decorateUniform(const TString &string, bool array);
+
+  protected:
+    void header();
+
+    // Visit AST nodes and output their code to the body stream
+    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*);
+
+    bool isSingleStatement(TIntermNode *node);
+    bool handleExcessiveLoop(TIntermLoop *node);
+    void outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString);
+    void outputLineDirective(int line);
+    TString argumentString(const TIntermSymbol *symbol);
+    int vectorSize(const TType &type) const;
+
+    void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters);
+    const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion);
+
+    TString scopeString(unsigned int depthLimit);
+    TString scopedStruct(const TString &typeName);
+    TString structLookup(const TString &typeName);
+
+    TParseContext &mContext;
+    UnfoldSelect *mUnfoldSelect;
+    bool mInsideFunction;
+
+    // Output streams
+    TInfoSinkBase mHeader;
+    TInfoSinkBase mBody;
+    TInfoSinkBase mFooter;
+
+    std::set<std::string> mReferencedUniforms;
+    std::set<std::string> mReferencedAttributes;
+    std::set<std::string> mReferencedVaryings;
+
+    // Parameters determining what goes in the header output
+    bool mUsesTexture2D;
+    bool mUsesTexture2D_bias;
+    bool mUsesTexture2DLod;
+    bool mUsesTexture2DProj;
+    bool mUsesTexture2DProj_bias;
+    bool mUsesTexture2DProjLod;
+    bool mUsesTextureCube;
+    bool mUsesTextureCube_bias;
+    bool mUsesTextureCubeLod;
+    bool mUsesDepthRange;
+    bool mUsesFragCoord;
+    bool mUsesPointCoord;
+    bool mUsesFrontFacing;
+    bool mUsesPointSize;
+    bool mUsesXor;
+    bool mUsesMod1;
+    bool mUsesMod2;
+    bool mUsesMod3;
+    bool mUsesMod4;
+    bool mUsesFaceforward1;
+    bool mUsesFaceforward2;
+    bool mUsesFaceforward3;
+    bool mUsesFaceforward4;
+    bool mUsesEqualMat2;
+    bool mUsesEqualMat3;
+    bool mUsesEqualMat4;
+    bool mUsesEqualVec2;
+    bool mUsesEqualVec3;
+    bool mUsesEqualVec4;
+    bool mUsesEqualIVec2;
+    bool mUsesEqualIVec3;
+    bool mUsesEqualIVec4;
+    bool mUsesEqualBVec2;
+    bool mUsesEqualBVec3;
+    bool mUsesEqualBVec4;
+    bool mUsesAtan2;
+
+    typedef std::set<TString> Constructors;
+    Constructors mConstructors;
+
+    typedef std::set<TString> StructNames;
+    StructNames mStructNames;
+
+    typedef std::list<TString> StructDeclarations;
+    StructDeclarations mStructDeclarations;
+
+    typedef std::vector<int> ScopeBracket;
+    ScopeBracket mScopeBracket;
+    unsigned int mScopeDepth;
+
+    int mUniqueIndex;   // For creating unique names
+};
+}
+
+#endif   // COMPILER_OUTPUTHLSL_H_
diff --git a/src/OpenGL ES 2.0/compiler/ParseHelper.cpp b/src/OpenGL ES 2.0/compiler/ParseHelper.cpp
new file mode 100644
index 0000000..ab7c182
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/ParseHelper.cpp
@@ -0,0 +1,1531 @@
+//
+// Copyright (c) 2002-2011 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 "compiler/ParseHelper.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "compiler/glslang.h"
+#include "compiler/osinclude.h"
+#include "compiler/InitializeParseContext.h"
+
+extern "C" {
+extern int InitPreprocessor();
+extern int FinalizePreprocessor();
+extern void PredefineIntMacro(const char *name, int value);
+}
+
+static void ReportInfo(TInfoSinkBase& sink,
+                       TPrefixType type, TSourceLoc loc,
+                       const char* reason, const char* token, 
+                       const char* extraInfo)
+{
+    /* VC++ format: file(linenum) : error #: 'token' : extrainfo */
+    sink.prefix(type);
+    sink.location(loc);
+    sink << "'" << token <<  "' : " << reason << " " << extraInfo << "\n";
+}
+
+static void DefineExtensionMacros(const TExtensionBehavior& extBehavior)
+{
+    for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
+         iter != extBehavior.end(); ++iter) {
+        PredefineIntMacro(iter->first.c_str(), 1);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// 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 TParseContext::error(TSourceLoc loc,
+                          const char* reason, const char* token, 
+                          const char* extraInfoFormat, ...)
+{
+    char extraInfo[512];
+    va_list marker;
+    va_start(marker, extraInfoFormat);
+    vsnprintf(extraInfo, sizeof(extraInfo), extraInfoFormat, marker);
+
+    ReportInfo(infoSink.info, EPrefixError, loc, reason, token, extraInfo);
+
+    va_end(marker);
+    ++numErrors;
+}
+
+void TParseContext::warning(TSourceLoc loc,
+                            const char* reason, const char* token,
+                            const char* extraInfoFormat, ...) {
+    char extraInfo[512];
+    va_list marker;
+    va_start(marker, extraInfoFormat);
+    vsnprintf(extraInfo, sizeof(extraInfo), extraInfoFormat, marker);
+
+    ReportInfo(infoSink.info, EPrefixWarning, loc, reason, token, extraInfo);
+
+    va_end(marker);
+}
+
+//
+// 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());
+}
+
+bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){
+    switch( type ){
+    case EbtFloat:
+        if( precision == EbpUndefined ){
+            error( line, "No precision specified for (float)", "", "" );
+            return true;
+        }
+        break;
+    case EbtInt:
+        if( precision == EbpUndefined ){
+            error( line, "No precision specified (int)", "", "" );
+            return true;
+        }
+        break;
+    default:
+        return false;
+    }
+    return false;
+}
+
+//
+// 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.
+// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
+// webgl shader.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
+{
+    static const char* reservedErrMsg = "reserved built-in name";
+    if (!symbolTable.atBuiltInLevel()) {
+        if (identifier.compare(0, 3, "gl_") == 0) {
+            error(line, reservedErrMsg, "gl_", "");
+            return true;
+        }
+        if (shaderSpec == SH_WEBGL_SPEC) {
+            if (identifier.compare(0, 6, "webgl_") == 0) {
+                error(line, reservedErrMsg, "webgl_", "");
+                return true;
+            }
+            if (identifier.compare(0, 7, "_webgl_") == 0) {
+                error(line, reservedErrMsg, "_webgl_", "");
+                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) {
+        const TParameter& param = function.getParam(i);
+        size += param.type->getObjectSize();
+        
+        if (constructingMatrix && param.type->isMatrix())
+            matrixInMatrix = true;
+        if (full)
+            overFull = true;
+        if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
+            full = true;
+        if (param.type->getQualifier() != EvqConst)
+            constType = false;
+        if (param.type->isArray())
+            arrayArg = true;
+    }
+    
+    if (constType)
+        type->setQualifier(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()) {
+        if (function.getParamCount() != 1) {
+          error(line, "constructing matrix from matrix can only take one argument", "constructor", "");
+          return true;
+        }
+    }
+
+    if (overFull) {
+        error(line, "too many arguments", "constructor", "");
+        return true;
+    }
+    
+    if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) {
+        error(line, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
+        return true;
+    }
+
+    if (!type->isMatrix()) {
+        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 ? node->getAsTyped() : 0;
+    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, getBasicString(pType.type), "(structure contains a sampler)");
+        
+            return true;
+        }
+        
+        return false;
+    } else if (IsSampler(pType.type)) {
+        error(line, reason, 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) || (type.qualifier == EvqConst)) {
+        error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), "");
+        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, TVariable*& variable)
+{
+    if (reservedErrorCheck(line, identifier))
+        recover();
+
+    variable = new TVariable(&identifier, TType(type));
+
+    if (! symbolTable.insert(*variable)) {
+        error(line, "redefinition", variable->getName().c_str(), "");
+        delete variable;
+        variable = 0;
+        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->setQualifier(EvqConstReadOnly);
+    else
+        type->setQualifier(paramQualifier);
+
+    return false;
+}
+
+bool TParseContext::extensionErrorCheck(int line, const TString& extension)
+{
+    TExtensionBehavior::const_iterator iter = extensionBehavior.find(extension);
+    if (iter == extensionBehavior.end()) {
+        error(line, "extension", extension.c_str(), "is not supported");
+        return true;
+    }
+    if (iter->second == EBhDisable) {
+        error(line, "extension", extension.c_str(), "is disabled");
+        return true;
+    }
+    if (iter->second == EBhWarn) {
+        TString msg = "extension " + extension + " is being used";
+        infoSink.info.message(EPrefixWarning, msg.c_str(), line);
+        return false;
+    }
+
+    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)
+{
+    // First find by unmangled name to check whether the function name has been
+    // hidden by a variable name or struct typename.
+    const TSymbol* symbol = symbolTable.find(call->getName(), builtIn);
+    if (symbol == 0) {
+        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;
+    }
+
+    return static_cast<const TFunction*>(symbol);
+}
+
+//
+// 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().setQualifier(EvqTemporary);
+            return true;
+        }
+        if (type != initializer->getType()) {
+            error(line, " non-matching types for const initializer ", 
+                variable->getType().getQualifierString(), "");
+            variable->getType().setQualifier(EvqTemporary);
+            return true;
+        }
+        if (initializer->getAsConstantUnion()) { 
+            ConstantUnion* 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);
+
+            ConstantUnion* constArray = tVar->getConstPointer();
+            variable->shareConstPointer(constArray);
+        } else {
+            error(line, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().c_str());
+            variable->getType().setQualifier(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)
+{
+    ASSERT(aggrNode != NULL);
+    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
+    TIntermSequence &sequence = aggrNode->getSequence() ;
+    for (TIntermSequence::iterator p = sequence.begin(); p != sequence.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::const_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;
+        ConstantUnion* unionArray = new ConstantUnion[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();
+
+    ConstantUnion *unionArray;
+    if (tempConstantNode) {
+        unionArray = tempConstantNode->getUnionArrayPointer();
+
+        if (!unionArray) {  // this error message should never be raised
+            infoSink.info.message(EPrefixInternalError, "ConstantUnion 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;
+    }
+
+    ConstantUnion* constArray = new ConstantUnion[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) {
+         ConstantUnion* 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) {
+         ConstantUnion* 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)
+{
+    const 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) {
+         ConstantUnion* 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;
+}
+
+//
+// Parse an array of strings using yyparse.
+//
+// Returns 0 for success.
+//
+int PaParseStrings(int count, const char* const string[], const int length[],
+                   TParseContext* context) {
+    if ((count == 0) || (string == NULL))
+        return 1;
+
+    // setup preprocessor.
+    if (InitPreprocessor())
+        return 1;
+    DefineExtensionMacros(context->extensionBehavior);
+
+    if (glslang_initialize(context))
+        return 1;
+
+    glslang_scan(count, string, length, context);
+    int error = glslang_parse(context);
+
+    glslang_finalize(context);
+    FinalizePreprocessor();
+    return (error == 0) && (context->numErrors == 0) ? 0 : 1;
+}
+
+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 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);
+}
+
+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;
+}
+
+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;
+}
+
+TParseContextPointer& GetGlobalParseContext()
+{
+    //
+    // Minimal error checking for speed
+    //
+
+    TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
+
+    return lpParseContext->lpGlobalParseContext;
+}
+
diff --git a/src/OpenGL ES 2.0/compiler/ParseHelper.h b/src/OpenGL ES 2.0/compiler/ParseHelper.h
new file mode 100644
index 0000000..f5a6c57
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/ParseHelper.h
@@ -0,0 +1,118 @@
+//
+// 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 "compiler/ExtensionBehavior.h"
+#include "compiler/localintermediate.h"
+#include "compiler/ShHandle.h"
+#include "compiler/SymbolTable.h"
+
+struct TMatrixFields {
+    bool wholeRow;
+    bool wholeCol;
+    int row;
+    int col;
+};
+
+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, const TExtensionBehavior& ext, TIntermediate& interm, ShShaderType type, ShShaderSpec spec, int options, const char* sourcePath, TInfoSink& is) :
+            intermediate(interm), symbolTable(symt), extensionBehavior(ext), infoSink(is), shaderType(type), shaderSpec(spec), compileOptions(options), sourcePath(sourcePath), treeRoot(0),
+            recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0),
+            inTypeParen(false), scanner(NULL), contextPragma(true, false) {  }
+    TIntermediate& intermediate; // to hold and build a parse tree
+    TSymbolTable& symbolTable;   // symbol table that goes with the language currently being parsed
+    TExtensionBehavior extensionBehavior;  // mapping between supported extensions and current behavior.
+    TInfoSink& infoSink;
+    ShShaderType shaderType;              // vertex or fragment language (future: pack or unpack)
+    ShShaderSpec shaderSpec;              // The language specification compiler conforms to - GLES2 or WebGL.
+    int compileOptions;
+    const char* sourcePath;      // Path of source file or NULL.
+    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
+
+    void error(TSourceLoc loc, const char *reason, const char* token,
+               const char* extraInfoFormat, ...);
+    void warning(TSourceLoc loc, const char* reason, const char* token,
+                 const char* extraInfoFormat, ...);
+    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 precisionErrorCheck(int line, TPrecision precision, TBasicType type);
+    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, TVariable*& variable);
+    bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
+    bool extensionErrorCheck(int line, const TString&);
+    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);
+    void* scanner;
+    struct TPragma contextPragma;
+    TString HashErrMsg;
+    bool AfterEOF;
+};
+
+int PaParseStrings(int count, const char* const string[], const int length[],
+                   TParseContext* context);
+
+typedef TParseContext* TParseContextPointer;
+extern TParseContextPointer& GetGlobalParseContext();
+#define GlobalParseContext GetGlobalParseContext()
+
+typedef struct TThreadParseContextRec
+{
+    TParseContext *lpGlobalParseContext;
+} TThreadParseContext;
+
+#endif // _PARSER_HELPER_INCLUDED_
diff --git a/src/OpenGL ES 2.0/compiler/PoolAlloc.cpp b/src/OpenGL ES 2.0/compiler/PoolAlloc.cpp
new file mode 100644
index 0000000..e286c7d
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/PoolAlloc.cpp
@@ -0,0 +1,304 @@
+//
+// 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 "compiler/PoolAlloc.h"
+
+#ifndef _MSC_VER
+#include <stdint.h>
+#endif
+#include <stdio.h>
+
+#include "compiler/InitializeGlobals.h"
+#include "compiler/osinclude.h"
+
+OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;
+
+void InitializeGlobalPools()
+{
+    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));    
+    if (globalPools)
+        return;
+
+    TThreadGlobalPools* threadData = new TThreadGlobalPools();
+    threadData->globalPoolAllocator = 0;
+
+    OS_SetTLSValue(PoolIndex, threadData);
+}
+
+void FreeGlobalPools()
+{
+    // Release the allocated memory for this thread.
+    TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));    
+    if (!globalPools)
+        return;
+ 
+    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 SetGlobalPoolAllocator(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(int growthIncrement, int allocationAlignment) : 
+    pageSize(growthIncrement),
+    alignment(allocationAlignment),
+    freeList(0),
+    inUseList(0),
+    numCalls(0),
+    totalBytes(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()
+{
+    while (inUseList) {
+        tHeader* next = inUseList->nextPage;
+        inUseList->~tHeader();
+        delete [] reinterpret_cast<char*>(inUseList);
+        inUseList = next;
+    }
+
+    // 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
+{
+#ifdef GUARD_BLOCKS
+    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");
+        }
+    }
+#endif
+}
+
+
+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<uintptr_t>(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/src/OpenGL ES 2.0/compiler/PoolAlloc.h b/src/OpenGL ES 2.0/compiler/PoolAlloc.h
new file mode 100644
index 0000000..55e09db
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/PoolAlloc.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 _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 <string.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(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) :
+            nextPage(nextPage),
+            pageCount(pageCount)
+#ifdef GUARD_BLOCKS
+          , lastAllocation(0)
+#endif
+            { }
+
+        ~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);
+    }
+
+    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.
+//
+extern TPoolAllocator& GetGlobalPoolAllocator();
+extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator);
+#define GlobalPoolAllocator GetGlobalPoolAllocator()
+
+struct TThreadGlobalPools
+{
+    TPoolAllocator* globalPoolAllocator;
+};
+
+//
+// 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; }
+
+    pool_allocator() : allocator(GlobalPoolAllocator) { }
+    pool_allocator(TPoolAllocator& a) : allocator(a) { }
+    pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
+
+    template<class Other>
+    pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
+
+#if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR)
+    // libCStd on some platforms have a different allocate/deallocate interface.
+    // Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be
+    // allocated, not the number of elements.
+    void* allocate(size_type n) { 
+        return getAllocator().allocate(n);
+    }
+    void* allocate(size_type n, const void*) {
+        return getAllocator().allocate(n);
+    }
+    void deallocate(void*, 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(pointer, size_type) {}
+#endif  // _RWSTD_ALLOCATOR
+
+    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; }
+
+    void setAllocator(TPoolAllocator* a) { allocator = *a; }
+    TPoolAllocator& getAllocator() const { return allocator; }
+
+protected:
+    TPoolAllocator& allocator;
+};
+
+#endif // _POOLALLOC_INCLUDED_
diff --git a/src/OpenGL ES 2.0/compiler/QualifierAlive.cpp b/src/OpenGL ES 2.0/compiler/QualifierAlive.cpp
new file mode 100644
index 0000000..92a6874
--- /dev/null
+++ b/src/OpenGL ES 2.0/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 "compiler/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/src/OpenGL ES 2.0/compiler/QualifierAlive.h b/src/OpenGL ES 2.0/compiler/QualifierAlive.h
new file mode 100644
index 0000000..872a06f
--- /dev/null
+++ b/src/OpenGL ES 2.0/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/src/OpenGL ES 2.0/compiler/RemoveTree.cpp b/src/OpenGL ES 2.0/compiler/RemoveTree.cpp
new file mode 100644
index 0000000..a4b8c1e
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/RemoveTree.cpp
@@ -0,0 +1,77 @@
+//
+// 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 "compiler/intermediate.h"
+#include "compiler/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/src/OpenGL ES 2.0/compiler/RemoveTree.h b/src/OpenGL ES 2.0/compiler/RemoveTree.h
new file mode 100644
index 0000000..97a8216
--- /dev/null
+++ b/src/OpenGL ES 2.0/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/src/OpenGL ES 2.0/compiler/SearchSymbol.cpp b/src/OpenGL ES 2.0/compiler/SearchSymbol.cpp
new file mode 100644
index 0000000..9368f1a
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/SearchSymbol.cpp
@@ -0,0 +1,38 @@
+//
+// 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.
+//
+// SearchSymbol is an AST traverser to detect the use of a given symbol name
+//
+
+#include "compiler/SearchSymbol.h"
+
+#include "compiler/InfoSink.h"
+#include "compiler/OutputHLSL.h"
+
+namespace sh
+{
+SearchSymbol::SearchSymbol(const TString &symbol) : mSymbol(symbol)
+{
+    match = false;
+}
+
+void SearchSymbol::traverse(TIntermNode *node)
+{
+    node->traverse(this);
+}
+
+void SearchSymbol::visitSymbol(TIntermSymbol *symbolNode)
+{
+    if (symbolNode->getSymbol() == mSymbol)
+    {
+        match = true;
+    }
+}
+
+bool SearchSymbol::foundMatch() const
+{
+    return match;
+}
+}
diff --git a/src/OpenGL ES 2.0/compiler/SearchSymbol.h b/src/OpenGL ES 2.0/compiler/SearchSymbol.h
new file mode 100644
index 0000000..6bc0b90
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/SearchSymbol.h
@@ -0,0 +1,33 @@
+//
+// 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.
+//
+// SearchSymbol is an AST traverser to detect the use of a given symbol name
+//
+
+#ifndef COMPILER_SEARCHSYMBOL_H_
+#define COMPILER_SEARCHSYMBOL_H_
+
+#include "compiler/intermediate.h"
+#include "compiler/ParseHelper.h"
+
+namespace sh
+{
+class SearchSymbol : public TIntermTraverser
+{
+  public:
+    SearchSymbol(const TString &symbol);
+
+    void traverse(TIntermNode *node);
+    void visitSymbol(TIntermSymbol *symbolNode);
+
+    bool foundMatch() const;
+
+  protected:
+    const TString &mSymbol;
+    bool match;
+};
+}
+
+#endif   // COMPILER_SEARCHSYMBOL_H_
diff --git a/src/OpenGL ES 2.0/compiler/ShHandle.h b/src/OpenGL ES 2.0/compiler/ShHandle.h
new file mode 100644
index 0000000..17e2fe0
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/ShHandle.h
@@ -0,0 +1,112 @@
+//
+// 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 "GLSLANG/ShaderLang.h"
+
+#include "compiler/ExtensionBehavior.h"
+#include "compiler/InfoSink.h"
+#include "compiler/SymbolTable.h"
+#include "compiler/VariableInfo.h"
+
+class TCompiler;
+
+//
+// The base class used to back handles returned to the driver.
+//
+class TShHandleBase {
+public:
+    TShHandleBase();
+    virtual ~TShHandleBase();
+    virtual TCompiler* getAsCompiler() { return 0; }
+
+protected:
+    // Memory allocator. Allocates and tracks memory required by the compiler.
+    // Deallocates all memory when compiler is destructed.
+    TPoolAllocator allocator;
+};
+
+//
+// The base class for the machine dependent compiler to derive from
+// for managing object code from the compile.
+//
+class TCompiler : public TShHandleBase {
+public:
+    TCompiler(ShShaderType type, ShShaderSpec spec);
+    virtual ~TCompiler();
+    virtual TCompiler* getAsCompiler() { return this; }
+
+    bool Init(const ShBuiltInResources& resources);
+    bool compile(const char* const shaderStrings[],
+                 const int numStrings,
+                 int compileOptions);
+
+    // Get results of the last compilation.
+    TInfoSink& getInfoSink() { return infoSink; }
+    const TVariableInfoList& getAttribs() const { return attribs; }
+    const TVariableInfoList& getUniforms() const { return uniforms; }
+    int getMappedNameMaxLength() const;
+
+protected:
+    ShShaderType getShaderType() const { return shaderType; }
+    ShShaderSpec getShaderSpec() const { return shaderSpec; }
+    // Initialize symbol-table with built-in symbols.
+    bool InitBuiltInSymbolTable(const ShBuiltInResources& resources);
+    // Clears the results from the previous compilation.
+    void clearResults();
+    // Return true if function recursion is detected.
+    bool detectRecursion(TIntermNode* root);
+    // Returns true if the given shader does not exceed the minimum
+    // functionality mandated in GLSL 1.0 spec Appendix A.
+    bool validateLimitations(TIntermNode* root);
+    // Collect info for all attribs and uniforms.
+    void collectAttribsUniforms(TIntermNode* root);
+    // Map long variable names into shorter ones.
+    void mapLongVariableNames(TIntermNode* root);
+    // Translate to object code.
+    virtual void translate(TIntermNode* root) = 0;
+
+private:
+    ShShaderType shaderType;
+    ShShaderSpec shaderSpec;
+
+    // Built-in symbol table for the given language, spec, and resources.
+    // It is preserved from compile-to-compile.
+    TSymbolTable symbolTable;
+    // Built-in extensions with default behavior.
+    TExtensionBehavior extensionBehavior;
+
+    // Results of compilation.
+    TInfoSink infoSink;  // Output sink.
+    TVariableInfoList attribs;  // Active attributes in the compiled shader.
+    TVariableInfoList uniforms;  // Active uniforms in the compiled shader.
+
+    // Pair of long varying varibale name <originalName, mappedName>.
+    std::map<std::string, std::string> varyingLongNameMap;
+};
+
+//
+// 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(ShShaderType type, ShShaderSpec spec);
+void DeleteCompiler(TCompiler*);
+
+#endif // _SHHANDLE_INCLUDED_
diff --git a/src/OpenGL ES 2.0/compiler/ShaderLang.cpp b/src/OpenGL ES 2.0/compiler/ShaderLang.cpp
new file mode 100644
index 0000000..051e4ec
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/ShaderLang.cpp
@@ -0,0 +1,261 @@
+//
+// 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,
+// as defined in ShaderLang.h
+//
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/InitializeDll.h"
+#include "compiler/ShHandle.h"
+
+//
+// This is the platform independent interface between an OGL driver
+// and the shading language compiler.
+//
+
+static int getVariableMaxLength(const TVariableInfoList& varList)
+{
+    TString::size_type maxLen = 0;
+    for (TVariableInfoList::const_iterator i = varList.begin();
+         i != varList.end(); ++i)
+    {
+        maxLen = std::max(maxLen, i->name.size());
+    }
+    // Add 1 to include null-termination character.
+    return static_cast<int>(maxLen) + 1;
+}
+
+static void getVariableInfo(ShShaderInfo varType,
+                            const ShHandle handle,
+                            int index,
+                            int* length,
+                            int* size,
+                            ShDataType* type,
+                            char* name,
+                            char* mappedName)
+{
+    if (!handle || !size || !type || !name)
+        return;
+    ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
+           (varType == SH_ACTIVE_UNIFORMS));
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (compiler == 0)
+        return;
+
+    const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ?
+        compiler->getAttribs() : compiler->getUniforms();
+    if (index < 0 || index >= static_cast<int>(varList.size()))
+        return;
+
+    const TVariableInfo& varInfo = varList[index];
+    if (length) *length = varInfo.name.size();
+    *size = varInfo.size;
+    *type = varInfo.type;
+    strcpy(name, varInfo.name.c_str());
+    if (mappedName)
+        strcpy(mappedName, varInfo.mappedName.c_str());
+}
+
+//
+// Driver must call this first, once, before doing any other
+// compiler operations.
+//
+int ShInitialize()
+{
+    if (!InitProcess())
+        return 0;
+
+    return 1;
+}
+
+//
+// Cleanup symbol tables
+//
+int ShFinalize()
+{
+    if (!DetachProcess())
+        return 0;
+
+    return 1;
+}
+
+//
+// Initialize built-in resources with minimum expected values.
+//
+void ShInitBuiltInResources(ShBuiltInResources* resources)
+{
+    // Constants.
+    resources->MaxVertexAttribs = 8;
+    resources->MaxVertexUniformVectors = 128;
+    resources->MaxVaryingVectors = 8;
+    resources->MaxVertexTextureImageUnits = 0;
+    resources->MaxCombinedTextureImageUnits = 8;
+    resources->MaxTextureImageUnits = 8;
+    resources->MaxFragmentUniformVectors = 16;
+    resources->MaxDrawBuffers = 1;
+
+    // Extensions.
+    resources->OES_standard_derivatives = 0;
+}
+
+//
+// Driver calls these to create and destroy compiler objects.
+//
+ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
+                             const ShBuiltInResources* resources)
+{
+    if (!InitThread())
+        return 0;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec));
+    TCompiler* compiler = base->getAsCompiler();
+    if (compiler == 0)
+        return 0;
+
+    // Generate built-in symbol table.
+    if (!compiler->Init(*resources)) {
+        ShDestruct(base);
+        return 0;
+    }
+
+    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());
+}
+
+//
+// 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,
+    int compileOptions)
+{
+    if (!InitThread())
+        return 0;
+
+    if (handle == 0)
+        return 0;
+
+    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (compiler == 0)
+        return 0;
+
+    bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
+    return success ? 1 : 0;
+}
+
+void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params)
+{
+    if (!handle || !params)
+        return;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (!compiler) return;
+
+    switch(pname)
+    {
+    case SH_INFO_LOG_LENGTH:
+        *params = compiler->getInfoSink().info.size() + 1;
+        break;
+    case SH_OBJECT_CODE_LENGTH:
+        *params = compiler->getInfoSink().obj.size() + 1;
+        break;
+    case SH_ACTIVE_UNIFORMS:
+        *params = compiler->getUniforms().size();
+        break;
+    case SH_ACTIVE_UNIFORM_MAX_LENGTH:
+        *params = getVariableMaxLength(compiler->getUniforms());
+        break;
+    case SH_ACTIVE_ATTRIBUTES:
+        *params = compiler->getAttribs().size();
+        break;
+    case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+        *params = getVariableMaxLength(compiler->getAttribs());
+        break;
+    case SH_MAPPED_NAME_MAX_LENGTH:
+        *params = compiler->getMappedNameMaxLength();
+        break;
+    default: UNREACHABLE();
+    }
+}
+
+//
+// Return any compiler log of messages for the application.
+//
+void ShGetInfoLog(const ShHandle handle, char* infoLog)
+{
+    if (!handle || !infoLog)
+        return;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (!compiler) return;
+
+    TInfoSink& infoSink = compiler->getInfoSink();
+    strcpy(infoLog, infoSink.info.c_str());
+}
+
+//
+// Return any object code.
+//
+void ShGetObjectCode(const ShHandle handle, char* objCode)
+{
+    if (!handle || !objCode)
+        return;
+
+    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+    TCompiler* compiler = base->getAsCompiler();
+    if (!compiler) return;
+
+    TInfoSink& infoSink = compiler->getInfoSink();
+    strcpy(objCode, infoSink.obj.c_str());
+}
+
+void ShGetActiveAttrib(const ShHandle handle,
+                       int index,
+                       int* length,
+                       int* size,
+                       ShDataType* type,
+                       char* name,
+                       char* mappedName)
+{
+    getVariableInfo(SH_ACTIVE_ATTRIBUTES,
+                    handle, index, length, size, type, name, mappedName);
+}
+
+void ShGetActiveUniform(const ShHandle handle,
+                        int index,
+                        int* length,
+                        int* size,
+                        ShDataType* type,
+                        char* name,
+                        char* mappedName)
+{
+    getVariableInfo(SH_ACTIVE_UNIFORMS,
+                    handle, index, length, size, type, name, mappedName);
+}
diff --git a/src/OpenGL ES 2.0/compiler/SymbolTable.cpp b/src/OpenGL ES 2.0/compiler/SymbolTable.cpp
new file mode 100644
index 0000000..02817d4
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/SymbolTable.cpp
@@ -0,0 +1,232 @@
+//
+// 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 "compiler/SymbolTable.h"
+
+#include <stdio.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[20];
+        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::const_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.getPrecisionString() << " " << 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);
+        }
+    }
+}
+
+//
+// Change all function entries in the table with the non-mangled name
+// to be related to the provided built-in extension. This is a low
+// performance operation, and only intended for symbol tables that
+// live across a large number of compiles.
+//
+void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
+{
+    for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
+        if (it->second->isFunction()) {
+            TFunction* function = static_cast<TFunction*>(it->second);
+            if (function->getName() == name)
+                function->relateToExtension(ext);
+        }
+    }
+}
+
+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 ConstantUnion[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));
+    }
+    for( unsigned int i = 0; i < copyOf.precisionStack.size(); i++) {
+        precisionStack.push_back( copyOf.precisionStack[i] );
+    }
+}
diff --git a/src/OpenGL ES 2.0/compiler/SymbolTable.h b/src/OpenGL ES 2.0/compiler/SymbolTable.h
new file mode 100644
index 0000000..38bc657
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/SymbolTable.h
@@ -0,0 +1,348 @@
+//
+// 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 <assert.h>
+
+#include "compiler/InfoSink.h"
+#include "compiler/intermediate.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 setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); }
+    void updateArrayInformationType(TType *t) { arrayInformationType = t; }
+    TType* getArrayInformationType() { return arrayInformationType; }
+
+    virtual void dump(TInfoSink &infoSink) const;
+
+    ConstantUnion* getConstPointer()
+    { 
+        if (!unionArray)
+            unionArray = new ConstantUnion[type.getObjectSize()];
+
+        return unionArray;
+    }
+
+    ConstantUnion* getConstPointer() const { return unionArray; }
+
+    void shareConstPointer( ConstantUnion *constArray)
+    {
+        if (unionArray == constArray)
+            return;
+
+        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
+    ConstantUnion *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, EbpUndefined)),
+        op(o),
+        defined(false) { }
+    TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : 
+        TSymbol(name), 
+        returnType(retType),
+        mangledName(TFunction::mangleName(*name)),
+        op(tOp),
+        defined(false) { }
+    virtual ~TFunction();
+    virtual bool isFunction() const { return true; }    
+
+    static TString mangleName(const TString& name) { return name + '('; }
+    static TString unmangleName(const TString& mangledName)
+    {
+        return TString(mangledName.c_str(), mangledName.find_first_of('('));
+    }
+
+    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 relateToExtension(const TString& ext) { extension = ext; }
+    const TString& getExtension() const { return extension; }
+
+    void setDefined() { defined = true; }
+    bool isDefined() { return defined; }
+
+    int getParamCount() const { return static_cast<int>(parameters.size()); }  
+    const TParameter& getParam(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;
+    TString extension;
+    bool defined;
+};
+
+
+class TSymbolTableLevel {
+public:
+    typedef TMap<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 relateToExtension(const char* name, const TString& ext);
+    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()
+    {
+        // 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 table.size() == 1; }
+    bool atGlobalLevel() { return table.size() <= 2; }
+    void push()
+    {
+        table.push_back(new TSymbolTableLevel);
+        precisionStack.push_back( PrecisionStackLevel() );
+    }
+
+    void pop()
+    { 
+        delete table[currentLevel()]; 
+        table.pop_back(); 
+        precisionStack.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() >= 2);
+        return table[1];
+    }
+    void relateToOperator(const char* name, TOperator op) {
+        table[0]->relateToOperator(name, op);
+    }
+    void relateToExtension(const char* name, const TString& ext) {
+        table[0]->relateToExtension(name, ext);
+    }
+    int getMaxSymbolId() { return uniqueId; }
+    void dump(TInfoSink &infoSink) const;
+    void copyTable(const TSymbolTable& copyOf);
+
+    void setDefaultPrecision( TBasicType type, TPrecision prec ){
+        if( type != EbtFloat && type != EbtInt ) return; // Only set default precision for int/float
+        int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
+        precisionStack[indexOfLastElement][type] = prec; // Uses map operator [], overwrites the current value
+    }
+
+    // Searches down the precisionStack for a precision qualifier for the specified TBasicType
+    TPrecision getDefaultPrecision( TBasicType type){
+        if( type != EbtFloat && type != EbtInt ) return EbpUndefined;
+        int level = static_cast<int>(precisionStack.size()) - 1;
+        assert( level >= 0); // Just to be safe. Should not happen.
+        PrecisionStackLevel::iterator it;
+        TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this?
+        while( level >= 0 ){
+            it = precisionStack[level].find( type );
+            if( it != precisionStack[level].end() ){
+                prec = (*it).second;
+                break;
+            }
+            level--;
+        }
+        return prec;
+    }
+
+protected:    
+    int currentLevel() const { return static_cast<int>(table.size()) - 1; }
+
+    std::vector<TSymbolTableLevel*> table;
+    typedef std::map< TBasicType, TPrecision > PrecisionStackLevel;
+    std::vector< PrecisionStackLevel > precisionStack;
+    int uniqueId;     // for unique identification in code generation
+};
+
+#endif // _SYMBOL_TABLE_INCLUDED_
diff --git a/src/OpenGL ES 2.0/compiler/TranslatorGLSL.cpp b/src/OpenGL ES 2.0/compiler/TranslatorGLSL.cpp
new file mode 100644
index 0000000..7a63ae1
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/TranslatorGLSL.cpp
@@ -0,0 +1,37 @@
+//
+// 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 "compiler/TranslatorGLSL.h"
+
+#include "compiler/OutputGLSL.h"
+#include "compiler/VersionGLSL.h"
+
+static void writeVersion(ShShaderType type, TIntermNode* root,
+                         TInfoSinkBase& sink) {
+    TVersionGLSL versionGLSL(type);
+    root->traverse(&versionGLSL);
+    int version = versionGLSL.getVersion();
+    // We need to write version directive only if it is greater than 110.
+    // If there is no version directive in the shader, 110 is implied.
+    if (version > 110) {
+        sink << "#version " << version << "\n";
+    }
+}
+
+TranslatorGLSL::TranslatorGLSL(ShShaderType type, ShShaderSpec spec)
+    : TCompiler(type, spec) {
+}
+
+void TranslatorGLSL::translate(TIntermNode* root) {
+    TInfoSinkBase& sink = getInfoSink().obj;
+
+    // Write GLSL version.
+    writeVersion(getShaderType(), root, sink);
+
+    // Write translated shader.
+    TOutputGLSL outputGLSL(sink);
+    root->traverse(&outputGLSL);
+}
diff --git a/src/OpenGL ES 2.0/compiler/TranslatorGLSL.h b/src/OpenGL ES 2.0/compiler/TranslatorGLSL.h
new file mode 100644
index 0000000..c2ce06d
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/TranslatorGLSL.h
@@ -0,0 +1,20 @@
+//
+// 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_TRANSLATORGLSL_H_
+#define COMPILER_TRANSLATORGLSL_H_
+
+#include "compiler/ShHandle.h"
+
+class TranslatorGLSL : public TCompiler {
+public:
+    TranslatorGLSL(ShShaderType type, ShShaderSpec spec);
+
+protected:
+    virtual void translate(TIntermNode* root);
+};
+
+#endif  // COMPILER_TRANSLATORGLSL_H_
diff --git a/src/OpenGL ES 2.0/compiler/TranslatorHLSL.cpp b/src/OpenGL ES 2.0/compiler/TranslatorHLSL.cpp
new file mode 100644
index 0000000..96d7f10
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/TranslatorHLSL.cpp
@@ -0,0 +1,22 @@
+//
+// 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 "compiler/TranslatorHLSL.h"
+
+#include "compiler/OutputHLSL.h"
+
+TranslatorHLSL::TranslatorHLSL(ShShaderType type, ShShaderSpec spec)
+    : TCompiler(type, spec)
+{
+}
+
+void TranslatorHLSL::translate(TIntermNode *root)
+{
+    TParseContext& parseContext = *GetGlobalParseContext();
+    sh::OutputHLSL outputHLSL(parseContext);
+
+    outputHLSL.output();
+}
diff --git a/src/OpenGL ES 2.0/compiler/TranslatorHLSL.h b/src/OpenGL ES 2.0/compiler/TranslatorHLSL.h
new file mode 100644
index 0000000..c3f672b
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/TranslatorHLSL.h
@@ -0,0 +1,20 @@
+//
+// 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_TRANSLATORHLSL_H_
+#define COMPILER_TRANSLATORHLSL_H_
+
+#include "compiler/ShHandle.h"
+
+class TranslatorHLSL : public TCompiler {
+public:
+    TranslatorHLSL(ShShaderType type, ShShaderSpec spec);
+
+protected:
+    virtual void translate(TIntermNode* root);
+};
+
+#endif  // COMPILER_TRANSLATORHLSL_H_
diff --git a/src/OpenGL ES 2.0/compiler/Types.h b/src/OpenGL ES 2.0/compiler/Types.h
new file mode 100644
index 0000000..d0fcc08
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/Types.h
@@ -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.
+//
+
+#ifndef _TYPES_INCLUDED
+#define _TYPES_INCLUDED
+
+#include "compiler/BaseTypes.h"
+#include "compiler/Common.h"
+#include "compiler/debug.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 = EbpUndefined;
+        size = 1;
+        matrix = false;
+        array = false;
+        arraySize = 0;
+        userDef = 0;
+        line = ln;
+    }
+
+    void setAggregate(int s, bool m = false)
+    {
+        size = s;
+        matrix = m;
+    }
+
+    void setArray(bool a, int s = 0)
+    {
+        array = a;
+        arraySize = s;
+    }
+};
+
+typedef TMap<TTypeList*, TTypeList*> TStructureMap;
+typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
+//
+// Base class for things that have a type.
+//
+class TType {
+public:
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+    TType() {}
+    TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
+            type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
+            maxArraySize(0), arrayInformationType(0), structure(0), structureSize(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),
+            maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), fieldName(0), mangled(0), typeName(0)
+    {
+        if (p.userDef) {
+            structure = p.userDef->getStruct();
+            typeName = NewPoolTString(p.userDef->getTypeName().c_str());
+        }
+    }
+    TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
+            type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
+            maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), fieldName(0), mangled(0)
+    {
+        typeName = NewPoolTString(n.c_str());
+    }
+
+    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;
+    }
+
+    TBasicType getBasicType() const { return type; }
+    void setBasicType(TBasicType t) { type = t; }
+
+    TPrecision getPrecision() const { return precision; }
+    void setPrecision(TPrecision p) { precision = p; }
+
+    TQualifier getQualifier() const { return qualifier; }
+    void setQualifier(TQualifier q) { qualifier = q; }
+
+    // One-dimensional size of single instance type
+    int getNominalSize() const { return size; }
+    void setNominalSize(int s) { size = s; }
+    // Full size of single instance of type
+    int getObjectSize() const
+    {
+        int totalSize;
+
+        if (getBasicType() == EbtStruct)
+            totalSize = getStructSize();
+        else if (matrix)
+            totalSize = size * size;
+        else
+            totalSize = size;
+
+        if (isArray())
+            totalSize *= std::max(getArraySize(), getMaxArraySize());
+
+        return totalSize;
+    }
+
+    bool isMatrix() const { return matrix ? true : false; }
+    void setMatrix(bool m) { matrix = m; }
+
+    bool isArray() const  { return array ? true : false; }
+    int getArraySize() const { return arraySize; }
+    void setArraySize(int s) { array = true; arraySize = s; }
+    int getMaxArraySize () const { return maxArraySize; }
+    void setMaxArraySize (int s) { maxArraySize = s; }
+    void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; }
+    void setArrayInformationType(TType* t) { arrayInformationType = t; }
+    TType* getArrayInformationType() const { return arrayInformationType; }
+
+    bool isVector() const { return size > 1 && !matrix; }
+    bool isScalar() const { return size == 1 && !matrix && !structure; }
+
+    TTypeList* getStruct() const { return structure; }
+    void setStruct(TTypeList* s) { structure = s; }
+
+    const TString& getTypeName() const
+    {
+        assert(typeName);
+        return *typeName;
+    }
+    void setTypeName(const TString& n)
+    {
+        typeName = NewPoolTString(n.c_str());
+    }
+
+    bool isField() const { return fieldName != 0; }
+    const TString& getFieldName() const
+    {
+        assert(fieldName);
+        return *fieldName;
+    }
+    void setFieldName(const TString& n)
+    {
+        fieldName = NewPoolTString(n.c_str());
+    }
+
+    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);
+    }
+    bool operator<(const TType& right) const {
+        if (type != right.type) return type < right.type;
+        if (size != right.size) return size < right.size;
+        if (matrix != right.matrix) return matrix < right.matrix;
+        if (array != right.array) return array < right.array;
+        if (arraySize != right.arraySize) return arraySize < right.arraySize;
+        if (structure != right.structure) return structure < right.structure;
+
+        return false;
+    }
+
+    const char* getBasicString() const { return ::getBasicString(type); }
+    const char* getPrecisionString() const { return ::getPrecisionString(precision); }
+    const char* getQualifierString() const { return ::getQualifierString(qualifier); }
+    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;
+    int maxArraySize;
+    TType* arrayInformationType;
+
+    TTypeList* structure;      // 0 unless this is a struct
+    mutable int structureSize;
+
+    TString *fieldName;         // for structure field names
+    TString *mangled;
+    TString *typeName;          // for structure field type name
+};
+
+#endif // _TYPES_INCLUDED_
diff --git a/src/OpenGL ES 2.0/compiler/UnfoldSelect.cpp b/src/OpenGL ES 2.0/compiler/UnfoldSelect.cpp
new file mode 100644
index 0000000..d3985e6
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/UnfoldSelect.cpp
@@ -0,0 +1,96 @@
+//
+// 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.
+//
+// UnfoldSelect is an AST traverser to output the select operator ?: as if-else statements
+//
+
+#include "compiler/UnfoldSelect.h"
+
+#include "compiler/InfoSink.h"
+#include "compiler/OutputHLSL.h"
+
+namespace sh
+{
+UnfoldSelect::UnfoldSelect(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL)
+{
+    mTemporaryIndex = 0;
+}
+
+void UnfoldSelect::traverse(TIntermNode *node)
+{
+    int rewindIndex = mTemporaryIndex;
+    node->traverse(this);
+    mTemporaryIndex = rewindIndex;
+}
+
+bool UnfoldSelect::visitSelection(Visit visit, TIntermSelection *node)
+{
+    TInfoSinkBase &out = mOutputHLSL->getBodyStream();
+
+    if (node->usesTernaryOperator())
+    {
+        int i = mTemporaryIndex;
+
+        out << mOutputHLSL->typeString(node->getType()) << " s" << i << ";\n";
+
+        mTemporaryIndex = i + 1;
+        node->getCondition()->traverse(this);
+        out << "if(";
+        mTemporaryIndex = i + 1;
+        node->getCondition()->traverse(mOutputHLSL);
+        out << ")\n"
+               "{\n";
+        mTemporaryIndex = i + 1;
+        node->getTrueBlock()->traverse(this);
+        out << "    s" << i << " = ";
+        mTemporaryIndex = i + 1;
+        node->getTrueBlock()->traverse(mOutputHLSL);
+        out << ";\n"
+               "}\n"
+               "else\n"
+               "{\n";
+        mTemporaryIndex = i + 1;
+        node->getFalseBlock()->traverse(this);
+        out << "    s" << i << " = ";
+        mTemporaryIndex = i + 1;
+        node->getFalseBlock()->traverse(mOutputHLSL);
+        out << ";\n"
+               "}\n";
+
+        mTemporaryIndex = i + 1;
+    }
+
+    return false;
+}
+
+bool UnfoldSelect::visitLoop(Visit visit, TIntermLoop *node)
+{
+    int rewindIndex = mTemporaryIndex;
+
+    if (node->getInit())
+    {
+        node->getInit()->traverse(this);
+    }
+    
+    if (node->getCondition())
+    {
+        node->getCondition()->traverse(this);
+    }
+
+    if (node->getExpression())
+    {
+        node->getExpression()->traverse(this);
+    }
+
+    mTemporaryIndex = rewindIndex;
+
+    return false;
+}
+
+int UnfoldSelect::getNextTemporaryIndex()
+{
+    return mTemporaryIndex++;
+}
+}
diff --git a/src/OpenGL ES 2.0/compiler/UnfoldSelect.h b/src/OpenGL ES 2.0/compiler/UnfoldSelect.h
new file mode 100644
index 0000000..4a3ba5f
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/UnfoldSelect.h
@@ -0,0 +1,38 @@
+//
+// 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.
+//
+// UnfoldSelect is an AST traverser to output the select operator ?: as if-else statements
+//
+
+#ifndef COMPILER_UNFOLDSELECT_H_
+#define COMPILER_UNFOLDSELECT_H_
+
+#include "compiler/intermediate.h"
+#include "compiler/ParseHelper.h"
+
+namespace sh
+{
+class OutputHLSL;
+
+class UnfoldSelect : public TIntermTraverser
+{
+  public:
+    UnfoldSelect(TParseContext &context, OutputHLSL *outputHLSL);
+
+    void traverse(TIntermNode *node);
+    bool visitSelection(Visit visit, TIntermSelection *node);
+    bool visitLoop(Visit visit, TIntermLoop *node);
+
+    int getNextTemporaryIndex();
+
+  protected:
+    TParseContext &mContext;
+    OutputHLSL *const mOutputHLSL;
+
+    int mTemporaryIndex;
+};
+}
+
+#endif   // COMPILER_UNFOLDSELECT_H_
diff --git a/src/OpenGL ES 2.0/compiler/ValidateLimitations.cpp b/src/OpenGL ES 2.0/compiler/ValidateLimitations.cpp
new file mode 100644
index 0000000..767d0bf
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/ValidateLimitations.cpp
@@ -0,0 +1,511 @@
+//
+// 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 "compiler/ValidateLimitations.h"
+#include "compiler/InfoSink.h"
+#include "compiler/ParseHelper.h"
+
+namespace {
+bool IsLoopIndex(const TIntermSymbol* symbol, const TLoopStack& stack) {
+    for (TLoopStack::const_iterator i = stack.begin(); i != stack.end(); ++i) {
+        if (i->index.id == symbol->getId())
+            return true;
+    }
+    return false;
+}
+
+void MarkLoopForUnroll(const TIntermSymbol* symbol, TLoopStack& stack) {
+    for (TLoopStack::iterator i = stack.begin(); i != stack.end(); ++i) {
+        if (i->index.id == symbol->getId()) {
+            ASSERT(i->loop != NULL);
+            i->loop->setUnrollFlag(true);
+            return;
+        }
+    }
+    UNREACHABLE();
+}
+
+// Traverses a node to check if it represents a constant index expression.
+// Definition:
+// constant-index-expressions are a superset of constant-expressions.
+// Constant-index-expressions can include loop indices as defined in
+// GLSL ES 1.0 spec, Appendix A, section 4.
+// The following are constant-index-expressions:
+// - Constant expressions
+// - Loop indices as defined in section 4
+// - Expressions composed of both of the above
+class ValidateConstIndexExpr : public TIntermTraverser {
+public:
+    ValidateConstIndexExpr(const TLoopStack& stack)
+        : mValid(true), mLoopStack(stack) {}
+
+    // Returns true if the parsed node represents a constant index expression.
+    bool isValid() const { return mValid; }
+
+    virtual void visitSymbol(TIntermSymbol* symbol) {
+        // Only constants and loop indices are allowed in a
+        // constant index expression.
+        if (mValid) {
+            mValid = (symbol->getQualifier() == EvqConst) ||
+                     IsLoopIndex(symbol, mLoopStack);
+        }
+    }
+
+private:
+    bool mValid;
+    const TLoopStack& mLoopStack;
+};
+
+// Traverses a node to check if it uses a loop index.
+// If an int loop index is used in its body as a sampler array index,
+// mark the loop for unroll.
+class ValidateLoopIndexExpr : public TIntermTraverser {
+public:
+    ValidateLoopIndexExpr(TLoopStack& stack)
+        : mUsesFloatLoopIndex(false),
+          mUsesIntLoopIndex(false),
+          mLoopStack(stack) {}
+
+    bool usesFloatLoopIndex() const { return mUsesFloatLoopIndex; }
+    bool usesIntLoopIndex() const { return mUsesIntLoopIndex; }
+
+    virtual void visitSymbol(TIntermSymbol* symbol) {
+        if (IsLoopIndex(symbol, mLoopStack)) {
+            switch (symbol->getBasicType()) {
+              case EbtFloat:
+                mUsesFloatLoopIndex = true;
+                break;
+              case EbtInt:
+                mUsesIntLoopIndex = true;
+                MarkLoopForUnroll(symbol, mLoopStack);
+                break;
+              default:
+                UNREACHABLE();
+            }
+        }
+    }
+
+private:
+    bool mUsesFloatLoopIndex;
+    bool mUsesIntLoopIndex;
+    TLoopStack& mLoopStack;
+};
+}  // namespace
+
+ValidateLimitations::ValidateLimitations(ShShaderType shaderType,
+                                         TInfoSinkBase& sink)
+    : mShaderType(shaderType),
+      mSink(sink),
+      mNumErrors(0)
+{
+}
+
+bool ValidateLimitations::visitBinary(Visit, TIntermBinary* node)
+{
+    // Check if loop index is modified in the loop body.
+    validateOperation(node, node->getLeft());
+
+    // Check indexing.
+    switch (node->getOp()) {
+      case EOpIndexDirect:
+        validateIndexing(node);
+        break;
+      case EOpIndexIndirect:
+#if defined(__APPLE__)
+        // Loop unrolling is a work-around for a Mac Cg compiler bug where it
+        // crashes when a sampler array's index is also the loop index.
+        // Once Apple fixes this bug, we should remove the code in this CL.
+        // See http://codereview.appspot.com/4331048/.
+        if ((node->getLeft() != NULL) && (node->getRight() != NULL) &&
+            (node->getLeft()->getAsSymbolNode())) {
+            TIntermSymbol* symbol = node->getLeft()->getAsSymbolNode();
+            if (IsSampler(symbol->getBasicType()) && symbol->isArray()) {
+                ValidateLoopIndexExpr validate(mLoopStack);
+                node->getRight()->traverse(&validate);
+                if (validate.usesFloatLoopIndex()) {
+                    error(node->getLine(),
+                          "sampler array index is float loop index",
+                          "for");
+                }
+            }
+        }
+#endif
+        validateIndexing(node);
+        break;
+      default: break;
+    }
+    return true;
+}
+
+bool ValidateLimitations::visitUnary(Visit, TIntermUnary* node)
+{
+    // Check if loop index is modified in the loop body.
+    validateOperation(node, node->getOperand());
+
+    return true;
+}
+
+bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate* node)
+{
+    switch (node->getOp()) {
+      case EOpFunctionCall:
+        validateFunctionCall(node);
+        break;
+      default:
+        break;
+    }
+    return true;
+}
+
+bool ValidateLimitations::visitLoop(Visit, TIntermLoop* node)
+{
+    if (!validateLoopType(node))
+        return false;
+
+    TLoopInfo info;
+    memset(&info, 0, sizeof(TLoopInfo));
+    info.loop = node;
+    if (!validateForLoopHeader(node, &info))
+        return false;
+
+    TIntermNode* body = node->getBody();
+    if (body != NULL) {
+        mLoopStack.push_back(info);
+        body->traverse(this);
+        mLoopStack.pop_back();
+    }
+
+    // The loop is fully processed - no need to visit children.
+    return false;
+}
+
+void ValidateLimitations::error(TSourceLoc loc,
+                                const char *reason, const char* token)
+{
+    mSink.prefix(EPrefixError);
+    mSink.location(loc);
+    mSink << "'" << token << "' : " << reason << "\n";
+    ++mNumErrors;
+}
+
+bool ValidateLimitations::withinLoopBody() const
+{
+    return !mLoopStack.empty();
+}
+
+bool ValidateLimitations::isLoopIndex(const TIntermSymbol* symbol) const
+{
+    return IsLoopIndex(symbol, mLoopStack);
+}
+
+bool ValidateLimitations::validateLoopType(TIntermLoop* node) {
+    TLoopType type = node->getType();
+    if (type == ELoopFor)
+        return true;
+
+    // Reject while and do-while loops.
+    error(node->getLine(),
+          "This type of loop is not allowed",
+          type == ELoopWhile ? "while" : "do");
+    return false;
+}
+
+bool ValidateLimitations::validateForLoopHeader(TIntermLoop* node,
+                                                TLoopInfo* info)
+{
+    ASSERT(node->getType() == ELoopFor);
+
+    //
+    // The for statement has the form:
+    //    for ( init-declaration ; condition ; expression ) statement
+    //
+    if (!validateForLoopInit(node, info))
+        return false;
+    if (!validateForLoopCond(node, info))
+        return false;
+    if (!validateForLoopExpr(node, info))
+        return false;
+
+    return true;
+}
+
+bool ValidateLimitations::validateForLoopInit(TIntermLoop* node,
+                                              TLoopInfo* info)
+{
+    TIntermNode* init = node->getInit();
+    if (init == NULL) {
+        error(node->getLine(), "Missing init declaration", "for");
+        return false;
+    }
+
+    //
+    // init-declaration has the form:
+    //     type-specifier identifier = constant-expression
+    //
+    TIntermAggregate* decl = init->getAsAggregate();
+    if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) {
+        error(init->getLine(), "Invalid init declaration", "for");
+        return false;
+    }
+    // To keep things simple do not allow declaration list.
+    TIntermSequence& declSeq = decl->getSequence();
+    if (declSeq.size() != 1) {
+        error(decl->getLine(), "Invalid init declaration", "for");
+        return false;
+    }
+    TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
+    if ((declInit == NULL) || (declInit->getOp() != EOpInitialize)) {
+        error(decl->getLine(), "Invalid init declaration", "for");
+        return false;
+    }
+    TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
+    if (symbol == NULL) {
+        error(declInit->getLine(), "Invalid init declaration", "for");
+        return false;
+    }
+    // The loop index has type int or float.
+    TBasicType type = symbol->getBasicType();
+    if ((type != EbtInt) && (type != EbtFloat)) {
+        error(symbol->getLine(),
+              "Invalid type for loop index", getBasicString(type));
+        return false;
+    }
+    // The loop index is initialized with constant expression.
+    if (!isConstExpr(declInit->getRight())) {
+        error(declInit->getLine(),
+              "Loop index cannot be initialized with non-constant expression",
+              symbol->getSymbol().c_str());
+        return false;
+    }
+
+    info->index.id = symbol->getId();
+    return true;
+}
+
+bool ValidateLimitations::validateForLoopCond(TIntermLoop* node,
+                                              TLoopInfo* info)
+{
+    TIntermNode* cond = node->getCondition();
+    if (cond == NULL) {
+        error(node->getLine(), "Missing condition", "for");
+        return false;
+    }
+    //
+    // condition has the form:
+    //     loop_index relational_operator constant_expression
+    //
+    TIntermBinary* binOp = cond->getAsBinaryNode();
+    if (binOp == NULL) {
+        error(node->getLine(), "Invalid condition", "for");
+        return false;
+    }
+    // Loop index should be to the left of relational operator.
+    TIntermSymbol* symbol = binOp->getLeft()->getAsSymbolNode();
+    if (symbol == NULL) {
+        error(binOp->getLine(), "Invalid condition", "for");
+        return false;
+    }
+    if (symbol->getId() != info->index.id) {
+        error(symbol->getLine(),
+              "Expected loop index", symbol->getSymbol().c_str());
+        return false;
+    }
+    // Relational operator is one of: > >= < <= == or !=.
+    switch (binOp->getOp()) {
+      case EOpEqual:
+      case EOpNotEqual:
+      case EOpLessThan:
+      case EOpGreaterThan:
+      case EOpLessThanEqual:
+      case EOpGreaterThanEqual:
+        break;
+      default:
+        error(binOp->getLine(),
+              "Invalid relational operator",
+              getOperatorString(binOp->getOp()));
+        break;
+    }
+    // Loop index must be compared with a constant.
+    if (!isConstExpr(binOp->getRight())) {
+        error(binOp->getLine(),
+              "Loop index cannot be compared with non-constant expression",
+              symbol->getSymbol().c_str());
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateLimitations::validateForLoopExpr(TIntermLoop* node,
+                                              TLoopInfo* info)
+{
+    TIntermNode* expr = node->getExpression();
+    if (expr == NULL) {
+        error(node->getLine(), "Missing expression", "for");
+        return false;
+    }
+
+    // for expression has one of the following forms:
+    //     loop_index++
+    //     loop_index--
+    //     loop_index += constant_expression
+    //     loop_index -= constant_expression
+    //     ++loop_index
+    //     --loop_index
+    // The last two forms are not specified in the spec, but I am assuming
+    // its an oversight.
+    TIntermUnary* unOp = expr->getAsUnaryNode();
+    TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode();
+
+    TOperator op = EOpNull;
+    TIntermSymbol* symbol = NULL;
+    if (unOp != NULL) {
+        op = unOp->getOp();
+        symbol = unOp->getOperand()->getAsSymbolNode();
+    } else if (binOp != NULL) {
+        op = binOp->getOp();
+        symbol = binOp->getLeft()->getAsSymbolNode();
+    }
+
+    // The operand must be loop index.
+    if (symbol == NULL) {
+        error(expr->getLine(), "Invalid expression", "for");
+        return false;
+    }
+    if (symbol->getId() != info->index.id) {
+        error(symbol->getLine(),
+              "Expected loop index", symbol->getSymbol().c_str());
+        return false;
+    }
+
+    // The operator is one of: ++ -- += -=.
+    switch (op) {
+        case EOpPostIncrement:
+        case EOpPostDecrement:
+        case EOpPreIncrement:
+        case EOpPreDecrement:
+            ASSERT((unOp != NULL) && (binOp == NULL));
+            break;
+        case EOpAddAssign:
+        case EOpSubAssign:
+            ASSERT((unOp == NULL) && (binOp != NULL));
+            break;
+        default:
+            error(expr->getLine(), "Invalid operator", getOperatorString(op));
+            return false;
+    }
+
+    // Loop index must be incremented/decremented with a constant.
+    if (binOp != NULL) {
+        if (!isConstExpr(binOp->getRight())) {
+            error(binOp->getLine(),
+                  "Loop index cannot be modified by non-constant expression",
+                  symbol->getSymbol().c_str());
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node)
+{
+    ASSERT(node->getOp() == EOpFunctionCall);
+
+    // If not within loop body, there is nothing to check.
+    if (!withinLoopBody())
+        return true;
+
+    // List of param indices for which loop indices are used as argument.
+    typedef std::vector<int> ParamIndex;
+    ParamIndex pIndex;
+    TIntermSequence& params = node->getSequence();
+    for (TIntermSequence::size_type i = 0; i < params.size(); ++i) {
+        TIntermSymbol* symbol = params[i]->getAsSymbolNode();
+        if (symbol && isLoopIndex(symbol))
+            pIndex.push_back(i);
+    }
+    // If none of the loop indices are used as arguments,
+    // there is nothing to check.
+    if (pIndex.empty())
+        return true;
+
+    bool valid = true;
+    TSymbolTable& symbolTable = GlobalParseContext->symbolTable;
+    TSymbol* symbol = symbolTable.find(node->getName());
+    ASSERT(symbol && symbol->isFunction());
+    TFunction* function = static_cast<TFunction*>(symbol);
+    for (ParamIndex::const_iterator i = pIndex.begin();
+         i != pIndex.end(); ++i) {
+        const TParameter& param = function->getParam(*i);
+        TQualifier qual = param.type->getQualifier();
+        if ((qual == EvqOut) || (qual == EvqInOut)) {
+            error(params[*i]->getLine(),
+                  "Loop index cannot be used as argument to a function out or inout parameter",
+                  params[*i]->getAsSymbolNode()->getSymbol().c_str());
+            valid = false;
+        }
+    }
+
+    return valid;
+}
+
+bool ValidateLimitations::validateOperation(TIntermOperator* node,
+                                            TIntermNode* operand) {
+    // Check if loop index is modified in the loop body.
+    if (!withinLoopBody() || !node->modifiesState())
+        return true;
+
+    const TIntermSymbol* symbol = operand->getAsSymbolNode();
+    if (symbol && isLoopIndex(symbol)) {
+        error(node->getLine(),
+              "Loop index cannot be statically assigned to within the body of the loop",
+              symbol->getSymbol().c_str());
+    }
+    return true;
+}
+
+bool ValidateLimitations::isConstExpr(TIntermNode* node)
+{
+    ASSERT(node != NULL);
+    return node->getAsConstantUnion() != NULL;
+}
+
+bool ValidateLimitations::isConstIndexExpr(TIntermNode* node)
+{
+    ASSERT(node != NULL);
+
+    ValidateConstIndexExpr validate(mLoopStack);
+    node->traverse(&validate);
+    return validate.isValid();
+}
+
+bool ValidateLimitations::validateIndexing(TIntermBinary* node)
+{
+    ASSERT((node->getOp() == EOpIndexDirect) ||
+           (node->getOp() == EOpIndexIndirect));
+
+    bool valid = true;
+    TIntermTyped* index = node->getRight();
+    // The index expression must have integral type.
+    if (!index->isScalar() || (index->getBasicType() != EbtInt)) {
+        error(index->getLine(),
+              "Index expression must have integral type",
+              index->getCompleteString().c_str());
+        valid = false;
+    }
+    // The index expession must be a constant-index-expression unless
+    // the operand is a uniform in a vertex shader.
+    TIntermTyped* operand = node->getLeft();
+    bool skip = (mShaderType == SH_VERTEX_SHADER) &&
+                (operand->getQualifier() == EvqUniform);
+    if (!skip && !isConstIndexExpr(index)) {
+        error(index->getLine(), "Index expression must be constant", "[]");
+        valid = false;
+    }
+    return valid;
+}
+
diff --git a/src/OpenGL ES 2.0/compiler/ValidateLimitations.h b/src/OpenGL ES 2.0/compiler/ValidateLimitations.h
new file mode 100644
index 0000000..a835cb3
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/ValidateLimitations.h
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 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 "GLSLANG/ShaderLang.h"
+#include "compiler/intermediate.h"
+
+class TInfoSinkBase;
+
+struct TLoopInfo {
+    struct TIndex {
+        int id;  // symbol id.
+    } index;
+    TIntermLoop* loop;
+};
+typedef TVector<TLoopInfo> TLoopStack;
+
+// Traverses intermediate tree to ensure that the shader does not exceed the
+// minimum functionality mandated in GLSL 1.0 spec, Appendix A.
+class ValidateLimitations : public TIntermTraverser {
+public:
+    ValidateLimitations(ShShaderType shaderType, TInfoSinkBase& sink);
+
+    int numErrors() const { return mNumErrors; }
+
+    virtual bool visitBinary(Visit, TIntermBinary*);
+    virtual bool visitUnary(Visit, TIntermUnary*);
+    virtual bool visitAggregate(Visit, TIntermAggregate*);
+    virtual bool visitLoop(Visit, TIntermLoop*);
+
+private:
+    void error(TSourceLoc loc, const char *reason, const char* token);
+
+    bool withinLoopBody() const;
+    bool isLoopIndex(const TIntermSymbol* symbol) const;
+    bool validateLoopType(TIntermLoop* node);
+    bool validateForLoopHeader(TIntermLoop* node, TLoopInfo* info);
+    bool validateForLoopInit(TIntermLoop* node, TLoopInfo* info);
+    bool validateForLoopCond(TIntermLoop* node, TLoopInfo* info);
+    bool validateForLoopExpr(TIntermLoop* node, TLoopInfo* info);
+    // Returns true if none of the loop indices is used as the argument to
+    // the given function out or inout parameter.
+    bool validateFunctionCall(TIntermAggregate* node);
+    bool validateOperation(TIntermOperator* node, TIntermNode* operand);
+
+    // Returns true if indexing does not exceed the minimum functionality
+    // mandated in GLSL 1.0 spec, Appendix A, Section 5.
+    bool isConstExpr(TIntermNode* node);
+    bool isConstIndexExpr(TIntermNode* node);
+    bool validateIndexing(TIntermBinary* node);
+
+    ShShaderType mShaderType;
+    TInfoSinkBase& mSink;
+    int mNumErrors;
+    TLoopStack mLoopStack;
+};
+
diff --git a/src/OpenGL ES 2.0/compiler/VariableInfo.cpp b/src/OpenGL ES 2.0/compiler/VariableInfo.cpp
new file mode 100644
index 0000000..a13a896
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/VariableInfo.cpp
@@ -0,0 +1,220 @@
+//
+// 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 "compiler/VariableInfo.h"
+
+static TString arrayBrackets(int index)
+{
+    TStringStream stream;
+    stream << "[" << index << "]";
+    return stream.str();
+}
+
+// Returns the data type for an attribute or uniform.
+static ShDataType getVariableDataType(const TType& type)
+{
+    switch (type.getBasicType()) {
+      case EbtFloat:
+          if (type.isMatrix()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_FLOAT_MAT2;
+                case 3: return SH_FLOAT_MAT3;
+                case 4: return SH_FLOAT_MAT4;
+                default: UNREACHABLE();
+              }
+          } else if (type.isVector()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_FLOAT_VEC2;
+                case 3: return SH_FLOAT_VEC3;
+                case 4: return SH_FLOAT_VEC4;
+                default: UNREACHABLE();
+              }
+          } else {
+              return SH_FLOAT;
+          }
+      case EbtInt:
+          if (type.isMatrix()) {
+              UNREACHABLE();
+          } else if (type.isVector()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_INT_VEC2;
+                case 3: return SH_INT_VEC3;
+                case 4: return SH_INT_VEC4;
+                default: UNREACHABLE();
+              }
+          } else {
+              return SH_INT;
+          }
+      case EbtBool:
+          if (type.isMatrix()) {
+              UNREACHABLE();
+          } else if (type.isVector()) {
+              switch (type.getNominalSize()) {
+                case 2: return SH_BOOL_VEC2;
+                case 3: return SH_BOOL_VEC3;
+                case 4: return SH_BOOL_VEC4;
+                default: UNREACHABLE();
+              }
+          } else {
+              return SH_BOOL;
+          }
+      case EbtSampler2D: return SH_SAMPLER_2D;
+      case EbtSamplerCube: return SH_SAMPLER_CUBE;
+      default: UNREACHABLE();
+    }
+    return SH_NONE;
+}
+
+static void getBuiltInVariableInfo(const TType& type,
+                                   const TString& name,
+                                   const TString& mappedName,
+                                   TVariableInfoList& infoList);
+static void getUserDefinedVariableInfo(const TType& type,
+                                       const TString& name,
+                                       const TString& mappedName,
+                                       TVariableInfoList& infoList);
+
+// Returns info for an attribute or uniform.
+static void getVariableInfo(const TType& type,
+                            const TString& name,
+                            const TString& mappedName,
+                            TVariableInfoList& infoList)
+{
+    if (type.getBasicType() == EbtStruct) {
+        if (type.isArray()) {
+            for (int i = 0; i < type.getArraySize(); ++i) {
+                TString lname = name + arrayBrackets(i);
+                TString lmappedName = mappedName + arrayBrackets(i);
+                getUserDefinedVariableInfo(type, lname, lmappedName, infoList);
+            }
+        } else {
+            getUserDefinedVariableInfo(type, name, mappedName, infoList);
+        }
+    } else {
+        getBuiltInVariableInfo(type, name, mappedName, infoList);
+    }
+}
+
+void getBuiltInVariableInfo(const TType& type,
+                            const TString& name,
+                            const TString& mappedName,
+                            TVariableInfoList& infoList)
+{
+    ASSERT(type.getBasicType() != EbtStruct);
+
+    TVariableInfo varInfo;
+    if (type.isArray()) {
+        varInfo.name = (name + "[0]").c_str();
+        varInfo.mappedName = (mappedName + "[0]").c_str();
+        varInfo.size = type.getArraySize();
+    } else {
+        varInfo.name = name.c_str();
+        varInfo.mappedName = mappedName.c_str();
+        varInfo.size = 1;
+    }
+    varInfo.type = getVariableDataType(type);
+    infoList.push_back(varInfo);
+}
+
+void getUserDefinedVariableInfo(const TType& type,
+                                const TString& name,
+                                const TString& mappedName,
+                                TVariableInfoList& infoList)
+{
+    ASSERT(type.getBasicType() == EbtStruct);
+
+    const TTypeList* structure = type.getStruct();
+    for (size_t i = 0; i < structure->size(); ++i) {
+        const TType* fieldType = (*structure)[i].type;
+        getVariableInfo(*fieldType,
+                        name + "." + fieldType->getFieldName(),
+                        mappedName + "." + fieldType->getFieldName(),
+                        infoList);
+    }
+}
+
+CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs,
+                                               TVariableInfoList& uniforms)
+    : mAttribs(attribs),
+      mUniforms(uniforms)
+{
+}
+
+// We are only interested in attribute and uniform variable declaration.
+void CollectAttribsUniforms::visitSymbol(TIntermSymbol*)
+{
+}
+
+void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*)
+{
+}
+
+bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*)
+{
+    return false;
+}
+
+bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*)
+{
+    return false;
+}
+
+bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*)
+{
+    return false;
+}
+
+bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
+{
+    bool visitChildren = false;
+
+    switch (node->getOp())
+    {
+    case EOpSequence:
+        // We need to visit sequence children to get to variable declarations.
+        visitChildren = true;
+        break;
+    case EOpDeclaration: {
+        const TIntermSequence& sequence = node->getSequence();
+        TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
+        if (qualifier == EvqAttribute || qualifier == EvqUniform)
+        {
+            TVariableInfoList& infoList = qualifier == EvqAttribute ?
+                mAttribs : mUniforms;
+            for (TIntermSequence::const_iterator i = sequence.begin();
+                 i != sequence.end(); ++i)
+            {
+                const TIntermSymbol* variable = (*i)->getAsSymbolNode();
+                // The only case in which the sequence will not contain a
+                // TIntermSymbol node is initialization. It will contain a
+                // TInterBinary node in that case. Since attributes and unifroms
+                // cannot be initialized in a shader, we must have only
+                // TIntermSymbol nodes in the sequence.
+                ASSERT(variable != NULL);
+                getVariableInfo(variable->getType(),
+                                variable->getOriginalSymbol(),
+                                variable->getSymbol(),
+                                infoList);
+            }
+        }
+        break;
+    }
+    default: break;
+    }
+
+    return visitChildren;
+}
+
+bool CollectAttribsUniforms::visitLoop(Visit, TIntermLoop*)
+{
+    return false;
+}
+
+bool CollectAttribsUniforms::visitBranch(Visit, TIntermBranch*)
+{
+    return false;
+}
+
diff --git a/src/OpenGL ES 2.0/compiler/VariableInfo.h b/src/OpenGL ES 2.0/compiler/VariableInfo.h
new file mode 100644
index 0000000..667acaf
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/VariableInfo.h
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2002-2011 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_VARIABLE_INFO_H_
+#define COMPILER_VARIABLE_INFO_H_
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/intermediate.h"
+
+// Provides information about a variable.
+// It is currently being used to store info about active attribs and uniforms.
+struct TVariableInfo {
+    TPersistString name;
+    TPersistString mappedName;
+    ShDataType type;
+    int size;
+};
+typedef std::vector<TVariableInfo> TVariableInfoList;
+
+// Traverses intermediate tree to collect all attributes and uniforms.
+class CollectAttribsUniforms : public TIntermTraverser {
+public:
+    CollectAttribsUniforms(TVariableInfoList& attribs,
+                           TVariableInfoList& uniforms);
+
+    virtual void visitSymbol(TIntermSymbol*);
+    virtual void visitConstantUnion(TIntermConstantUnion*);
+    virtual bool visitBinary(Visit, TIntermBinary*);
+    virtual bool visitUnary(Visit, TIntermUnary*);
+    virtual bool visitSelection(Visit, TIntermSelection*);
+    virtual bool visitAggregate(Visit, TIntermAggregate*);
+    virtual bool visitLoop(Visit, TIntermLoop*);
+    virtual bool visitBranch(Visit, TIntermBranch*);
+
+private:
+    TVariableInfoList& mAttribs;
+    TVariableInfoList& mUniforms;
+};
+
+#endif  // COMPILER_VARIABLE_INFO_H_
diff --git a/src/OpenGL ES 2.0/compiler/VersionGLSL.cpp b/src/OpenGL ES 2.0/compiler/VersionGLSL.cpp
new file mode 100644
index 0000000..26cee05
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/VersionGLSL.cpp
@@ -0,0 +1,115 @@
+//
+// 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 "compiler/VersionGLSL.h"
+
+static const int GLSL_VERSION_110 = 110;
+static const int GLSL_VERSION_120 = 120;
+
+// We need to scan for three things:
+// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders
+//    but only at the global scope.
+// 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader
+//    but inside any scope.
+// 3. Call to a matrix constructor with another matrix as argument.
+//    (These constructors were reserved in GLSL version 1.10.)
+//
+// If it weren't for (3) then we would only need to scan the global
+// scope of the vertex shader. However, we need to scan the entire
+// shader in both cases.
+//
+// TODO(alokp): The following two cases of invariant decalaration get lost
+// during parsing - they do not get carried over to the intermediate tree.
+// Handle these cases:
+// 1. When a pragma is used to force all output variables to be invariant:
+//    - #pragma STDGL invariant(all)
+// 2. When a previously decalared or built-in variable is marked invariant:
+//    - invariant gl_Position;
+//    - varying vec3 color; invariant color;
+//
+TVersionGLSL::TVersionGLSL(ShShaderType type)
+    : mShaderType(type),
+      mVersion(GLSL_VERSION_110)
+{
+}
+
+void TVersionGLSL::visitSymbol(TIntermSymbol* node)
+{
+    if (node->getSymbol() == "gl_PointCoord")
+        updateVersion(GLSL_VERSION_120);
+}
+
+void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*)
+{
+}
+
+bool TVersionGLSL::visitBinary(Visit, TIntermBinary*)
+{
+    return true;
+}
+
+bool TVersionGLSL::visitUnary(Visit, TIntermUnary*)
+{
+    return true;
+}
+
+bool TVersionGLSL::visitSelection(Visit, TIntermSelection*)
+{
+    return true;
+}
+
+bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node)
+{
+    bool visitChildren = true;
+
+    switch (node->getOp()) {
+      case EOpSequence:
+        // We need to visit sequence children to get to global or inner scope.
+        visitChildren = true;
+        break;
+      case EOpDeclaration: {
+        const TIntermSequence& sequence = node->getSequence();
+        TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
+        if ((qualifier == EvqInvariantVaryingIn) ||
+            (qualifier == EvqInvariantVaryingOut)) {
+            updateVersion(GLSL_VERSION_120);
+        }
+        break;
+      }
+      case EOpConstructMat2:
+      case EOpConstructMat3:
+      case EOpConstructMat4: {
+        const TIntermSequence& sequence = node->getSequence();
+        if (sequence.size() == 1) {
+          TIntermTyped* typed = sequence.front()->getAsTyped();
+          if (typed && typed->isMatrix()) {
+            updateVersion(GLSL_VERSION_120);
+          }
+        }
+        break;
+      }
+
+      default: break;
+    }
+
+    return visitChildren;
+}
+
+bool TVersionGLSL::visitLoop(Visit, TIntermLoop*)
+{
+    return true;
+}
+
+bool TVersionGLSL::visitBranch(Visit, TIntermBranch*)
+{
+    return true;
+}
+
+void TVersionGLSL::updateVersion(int version)
+{
+    mVersion = std::max(version, mVersion);
+}
+
diff --git a/src/OpenGL ES 2.0/compiler/VersionGLSL.h b/src/OpenGL ES 2.0/compiler/VersionGLSL.h
new file mode 100644
index 0000000..376fcb8
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/VersionGLSL.h
@@ -0,0 +1,52 @@
+//
+// 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_VERSIONGLSL_H_
+#define COMPILER_VERSIONGLSL_H_
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/intermediate.h"
+
+// Traverses the intermediate tree to return the minimum GLSL version
+// required to legally access all built-in features used in the shader.
+// GLSL 1.1 which is mandated by OpenGL 2.0 provides:
+//   - #version and #extension to declare version and extensions.
+//   - built-in functions refract, exp, and log.
+//   - updated step() to compare x < edge instead of x <= edge.
+// GLSL 1.2 which is mandated by OpenGL 2.1 provides:
+//   - many changes to reduce differences when compared to the ES specification.
+//   - invariant keyword and its support.
+//   - c++ style name hiding rules.
+//   - built-in variable gl_PointCoord for fragment shaders.
+//   - matrix constructors taking matrix as argument.
+//
+class TVersionGLSL : public TIntermTraverser {
+public:
+    TVersionGLSL(ShShaderType type);
+
+    // Returns 120 if "invariant" keyword, "gl_PointCoord", or
+    // matrix/matrix constructors are used in the shader. Else 110 is
+    // returned.
+    int getVersion() { return mVersion; }
+
+    virtual void visitSymbol(TIntermSymbol*);
+    virtual void visitConstantUnion(TIntermConstantUnion*);
+    virtual bool visitBinary(Visit, TIntermBinary*);
+    virtual bool visitUnary(Visit, TIntermUnary*);
+    virtual bool visitSelection(Visit, TIntermSelection*);
+    virtual bool visitAggregate(Visit, TIntermAggregate*);
+    virtual bool visitLoop(Visit, TIntermLoop*);
+    virtual bool visitBranch(Visit, TIntermBranch*);
+
+protected:
+    void updateVersion(int version);
+
+private:
+    ShShaderType mShaderType;
+    int mVersion;
+};
+
+#endif  // COMPILER_VERSIONGLSL_H_
diff --git a/src/OpenGL ES 2.0/compiler/debug.cpp b/src/OpenGL ES 2.0/compiler/debug.cpp
new file mode 100644
index 0000000..9642e1e
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/debug.cpp
@@ -0,0 +1,36 @@
+//
+// 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.
+//
+
+// debug.cpp: Debugging utilities.
+
+#include "compiler/debug.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "compiler/ParseHelper.h"
+
+static const int kTraceBufferLen = 1024;
+
+#ifdef TRACE_ENABLED
+extern "C" {
+void Trace(const char *format, ...) {
+    if (!format) return;
+
+    TParseContext* parseContext = GetGlobalParseContext();
+    if (parseContext) {
+        char buf[kTraceBufferLen];
+        va_list args;
+        va_start(args, format);
+        vsnprintf(buf, kTraceBufferLen, format, args);
+        va_end(args);
+
+        parseContext->infoSink.debug << buf;
+    }
+}
+}  // extern "C"
+#endif  // TRACE_ENABLED
+
diff --git a/src/OpenGL ES 2.0/compiler/debug.h b/src/OpenGL ES 2.0/compiler/debug.h
new file mode 100644
index 0000000..7a37151
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/debug.h
@@ -0,0 +1,53 @@
+//
+// 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.
+//
+
+// debug.h: Debugging utilities.
+
+#ifndef COMPILER_DEBUG_H_
+#define COMPILER_DEBUG_H_
+
+#include <assert.h>
+
+#ifdef _DEBUG
+#define TRACE_ENABLED  // define to enable debug message tracing
+#endif  // _DEBUG
+
+// Outputs text to the debug log
+#ifdef TRACE_ENABLED
+
+#ifdef  __cplusplus
+extern "C" {
+#endif  // __cplusplus
+void Trace(const char* format, ...);
+#ifdef  __cplusplus
+}
+#endif  // __cplusplus
+
+#else   // TRACE_ENABLED
+
+#define Trace(...) ((void)0)
+
+#endif  // TRACE_ENABLED
+
+// A macro asserting a condition and outputting failures to the debug log
+#define ASSERT(expression) do { \
+    if(!(expression)) \
+        Trace("Assert failed: %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
+    assert(expression); \
+} while(0)
+
+#define UNIMPLEMENTED() do { \
+    Trace("Unimplemented invoked: %s(%d)\n", __FUNCTION__, __LINE__); \
+    assert(false); \
+} while(0)
+
+#define UNREACHABLE() do { \
+    Trace("Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \
+    assert(false); \
+} while(0)
+
+#endif   // COMPILER_DEBUG_H_
+
diff --git a/src/OpenGL ES 2.0/compiler/generate_glslang_lexer.sh b/src/OpenGL ES 2.0/compiler/generate_glslang_lexer.sh
new file mode 100644
index 0000000..268479d
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/generate_glslang_lexer.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# Copyright (c) 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.
+
+# Generates GLSL ES lexer - glslang_lex.cpp
+
+script_dir=$(dirname $0)
+input_file=$script_dir/glslang.l
+output_file=$script_dir/glslang_lex.cpp
+flex --noline --nounistd --outfile=$output_file $input_file
diff --git a/src/OpenGL ES 2.0/compiler/generate_glslang_parser.sh b/src/OpenGL ES 2.0/compiler/generate_glslang_parser.sh
new file mode 100644
index 0000000..889f5c0
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/generate_glslang_parser.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+# Copyright (c) 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.
+
+# Generates GLSL ES parser - glslang_tab.h and glslang_tab.cpp
+
+script_dir=$(dirname $0)
+input_file=$script_dir/glslang.y
+output_header=$script_dir/glslang_tab.h
+output_source=$script_dir/glslang_tab.cpp
+bison --no-lines --skeleton=yacc.c --defines=$output_header --output=$output_source $input_file
diff --git a/src/OpenGL ES 2.0/compiler/glslang.h b/src/OpenGL ES 2.0/compiler/glslang.h
new file mode 100644
index 0000000..26f1457
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/glslang.h
@@ -0,0 +1,16 @@
+//
+// Copyright (c) 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.
+//
+
+struct TParseContext;
+extern int glslang_initialize(TParseContext* context);
+extern int glslang_finalize(TParseContext* context);
+
+extern void glslang_scan(int count,
+                         const char* const string[],
+                         const int length[],
+                         TParseContext* context);
+extern int glslang_parse(TParseContext* context);
+
diff --git a/src/OpenGL ES 2.0/compiler/glslang.l b/src/OpenGL ES 2.0/compiler/glslang.l
new file mode 100644
index 0000000..5a7c5d5
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/glslang.l
@@ -0,0 +1,570 @@
+/*
+//
+// 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 file contains the Lex specification for GLSL ES.
+Based on ANSI C grammar, Lex specification:
+http://www.lysator.liu.se/c/ANSI-C-grammar-l.html
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_glslang_lexer.sh,
+WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
+*/
+
+%top{
+//
+// Copyright (c) 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 file is auto-generated by generate_glslang_lexer.sh. DO NOT EDIT!
+}
+
+%{
+#include "compiler/glslang.h"
+#include "compiler/ParseHelper.h"
+#include "compiler/util.h"
+#include "glslang_tab.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+#pragma warning(disable : 4102)
+#endif
+
+#define YY_USER_ACTION yylval->lex.line = yylineno;
+#define YY_INPUT(buf, result, max_size) \
+    result = string_input(buf, max_size, yyscanner);
+
+static int string_input(char* buf, int max_size, yyscan_t yyscanner);
+static int check_type(yyscan_t yyscanner);
+static int reserved_word(yyscan_t yyscanner);
+%}
+
+%option noyywrap nounput never-interactive
+%option yylineno reentrant bison-bridge
+%option stack
+%option extra-type="TParseContext*"
+%x COMMENT FIELDS
+
+D           [0-9]
+L           [a-zA-Z_]
+H           [a-fA-F0-9]
+E           [Ee][+-]?{D}+
+O           [0-7]
+
+%%
+
+%{
+    TParseContext* context = yyextra;
+%}
+
+    /* Single-line comments */
+"//"[^\n]* ;
+
+    /* Multi-line comments */
+"/*"           { yy_push_state(COMMENT, yyscanner); }
+<COMMENT>. |
+<COMMENT>\n ;
+<COMMENT>"*/"  { yy_pop_state(yyscanner); }
+
+"invariant"    { return(INVARIANT); }
+"highp"        { return(HIGH_PRECISION); }
+"mediump"      { return(MEDIUM_PRECISION); }
+"lowp"         { return(LOW_PRECISION); }
+"precision"    { return(PRECISION); }
+
+"attribute"    { return(ATTRIBUTE); }
+"const"        { return(CONST_QUAL); }
+"uniform"      { return(UNIFORM); }
+"varying"      { return(VARYING); }
+
+"break"        { return(BREAK); }
+"continue"     { return(CONTINUE); }
+"do"           { return(DO); }
+"for"          { return(FOR); }
+"while"        { return(WHILE); }
+
+"if"           { return(IF); }
+"else"         { return(ELSE); }
+
+"in"           { return(IN_QUAL); }
+"out"          { return(OUT_QUAL); }
+"inout"        { return(INOUT_QUAL); }
+
+"float"        { context->lexAfterType = true; return(FLOAT_TYPE); }
+"int"          { context->lexAfterType = true; return(INT_TYPE); }
+"void"         { context->lexAfterType = true; return(VOID_TYPE); }
+"bool"         { context->lexAfterType = true; return(BOOL_TYPE); }
+"true"         { yylval->lex.b = true;  return(BOOLCONSTANT); }
+"false"        { yylval->lex.b = false; return(BOOLCONSTANT); }
+
+"discard"      { return(DISCARD); }
+"return"       { return(RETURN); }
+
+"mat2"         { context->lexAfterType = true; return(MATRIX2); }
+"mat3"         { context->lexAfterType = true; return(MATRIX3); }
+"mat4"         { context->lexAfterType = true; return(MATRIX4); }
+
+"vec2"         { context->lexAfterType = true; return (VEC2); }
+"vec3"         { context->lexAfterType = true; return (VEC3); }
+"vec4"         { context->lexAfterType = true; return (VEC4); }
+"ivec2"        { context->lexAfterType = true; return (IVEC2); }
+"ivec3"        { context->lexAfterType = true; return (IVEC3); }
+"ivec4"        { context->lexAfterType = true; return (IVEC4); }
+"bvec2"        { context->lexAfterType = true; return (BVEC2); }
+"bvec3"        { context->lexAfterType = true; return (BVEC3); }
+"bvec4"        { context->lexAfterType = true; return (BVEC4); }
+
+"sampler2D"       { context->lexAfterType = true; return SAMPLER2D; }
+"samplerCube"     { context->lexAfterType = true; return SAMPLERCUBE; }
+
+"struct"       { context->lexAfterType = true; return(STRUCT); }
+
+"asm"          { return reserved_word(yyscanner); }
+
+"class"        { return reserved_word(yyscanner); }
+"union"        { return reserved_word(yyscanner); }
+"enum"         { return reserved_word(yyscanner); }
+"typedef"      { return reserved_word(yyscanner); }
+"template"     { return reserved_word(yyscanner); }
+"this"         { return reserved_word(yyscanner); }
+"packed"       { return reserved_word(yyscanner); }
+
+"goto"         { return reserved_word(yyscanner); }
+"switch"       { return reserved_word(yyscanner); }
+"default"      { return reserved_word(yyscanner); }
+
+"inline"       { return reserved_word(yyscanner); }
+"noinline"     { return reserved_word(yyscanner); }
+"volatile"     { return reserved_word(yyscanner); }
+"public"       { return reserved_word(yyscanner); }
+"static"       { return reserved_word(yyscanner); }
+"extern"       { return reserved_word(yyscanner); }
+"external"     { return reserved_word(yyscanner); }
+"interface"    { return reserved_word(yyscanner); }
+
+"long"         { return reserved_word(yyscanner); }
+"short"        { return reserved_word(yyscanner); }
+"double"       { return reserved_word(yyscanner); }
+"half"         { return reserved_word(yyscanner); }
+"fixed"        { return reserved_word(yyscanner); }
+"unsigned"     { return reserved_word(yyscanner); }
+
+"input"        { return reserved_word(yyscanner); }
+"output"       { return reserved_word(yyscanner); }
+
+"hvec2"        { return reserved_word(yyscanner); }
+"hvec3"        { return reserved_word(yyscanner); }
+"hvec4"        { return reserved_word(yyscanner); }
+"fvec2"        { return reserved_word(yyscanner); }
+"fvec3"        { return reserved_word(yyscanner); }
+"fvec4"        { return reserved_word(yyscanner); }
+"dvec2"        { return reserved_word(yyscanner); }
+"dvec3"        { return reserved_word(yyscanner); }
+"dvec4"        { return reserved_word(yyscanner); }
+
+"sizeof"       { return reserved_word(yyscanner); }
+"cast"         { return reserved_word(yyscanner); }
+
+"namespace"    { return reserved_word(yyscanner); }
+"using"        { return reserved_word(yyscanner); }
+
+{L}({L}|{D})*       {
+   yylval->lex.string = NewPoolTString(yytext); 
+   return check_type(yyscanner);
+}
+
+0[xX]{H}+         { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+0{O}+             { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+0{D}+             { context->error(yylineno, "Invalid Octal number.", yytext, "", ""); context->recover(); return 0;}
+{D}+              { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+
+{D}+{E}           { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+{D}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+"."{D}+({E})?     { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+
+"+="            {  return(ADD_ASSIGN); }
+"-="            {  return(SUB_ASSIGN); }
+"*="            {  return(MUL_ASSIGN); }
+"/="            {  return(DIV_ASSIGN); }
+"%="            {  return(MOD_ASSIGN); }
+"<<="           {  return(LEFT_ASSIGN); }
+">>="           {  return(RIGHT_ASSIGN); }
+"&="            {  return(AND_ASSIGN); }
+"^="            {  return(XOR_ASSIGN); }
+"|="            {  return(OR_ASSIGN); }
+
+"++"            {  return(INC_OP); }
+"--"            {  return(DEC_OP); }
+"&&"            {  return(AND_OP); }
+"||"            {  return(OR_OP); }
+"^^"            {  return(XOR_OP); }
+"<="            {  return(LE_OP); }
+">="            {  return(GE_OP); }
+"=="            {  return(EQ_OP); }
+"!="            {  return(NE_OP); }
+"<<"            {  return(LEFT_OP); }
+">>"            {  return(RIGHT_OP); }
+";"             { context->lexAfterType = false; return(SEMICOLON); }
+("{"|"<%")      { context->lexAfterType = false; return(LEFT_BRACE); }
+("}"|"%>")      { return(RIGHT_BRACE); }
+","         { if (context->inTypeParen) context->lexAfterType = false; return(COMMA); }
+":"         { return(COLON); }
+"="         { context->lexAfterType = false; return(EQUAL); }
+"("         { context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); }
+")"         { context->inTypeParen = false; return(RIGHT_PAREN); }
+("["|"<:")      { return(LEFT_BRACKET); }
+("]"|":>")      { return(RIGHT_BRACKET); }
+"."         { BEGIN(FIELDS);  return(DOT); }
+"!"         { return(BANG); }
+"-"         { return(DASH); }
+"~"         { return(TILDE); }
+"+"         { return(PLUS); }
+"*"         { return(STAR); }
+"/"         { return(SLASH); }
+"%"         { return(PERCENT); }
+"<"         { return(LEFT_ANGLE); }
+">"         { return(RIGHT_ANGLE); }
+"|"         { return(VERTICAL_BAR); }
+"^"         { return(CARET); }
+"&"         { return(AMPERSAND); }
+"?"         { return(QUESTION); }
+
+<FIELDS>{L}({L}|{D})* { 
+    BEGIN(INITIAL);
+    yylval->lex.string = NewPoolTString(yytext); 
+    return FIELD_SELECTION;
+}
+<FIELDS>[ \t\v\f\r] {}
+
+[ \t\v\n\f\r]   {  }
+<*><<EOF>>      { context->AfterEOF = true; yyterminate(); }
+<*>.            { context->warning(yylineno, "Unknown char", yytext, ""); return 0; }
+
+%%
+
+extern "C" {
+// Preprocessor interface.
+#include "compiler/preprocessor/preprocess.h"
+
+#define SETUP_CONTEXT(pp) \
+    TParseContext* context = (TParseContext*) pp->pC; \
+    struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
+
+// Preprocessor callbacks.
+void CPPDebugLogMsg(const char *msg)
+{
+    SETUP_CONTEXT(cpp);
+    context->infoSink.debug.message(EPrefixNone, msg);
+}
+
+void CPPWarningToInfoLog(const char *msg)
+{
+    SETUP_CONTEXT(cpp);
+    context->warning(yylineno, msg, "", "");
+}
+
+void CPPShInfoLogMsg(const char *msg)
+{
+    SETUP_CONTEXT(cpp);
+    context->error(yylineno, msg, "", "");
+    context->recover();
+}
+
+void CPPErrorToInfoLog(char *msg)
+{
+    SETUP_CONTEXT(cpp);
+    context->error(yylineno, msg, "", "");
+    context->recover();
+}
+
+void SetLineNumber(int line)
+{
+    SETUP_CONTEXT(cpp);
+    int string = 0;
+    DecodeSourceLoc(yylineno, &string, NULL);
+    yylineno = EncodeSourceLoc(string, line);
+}
+
+void SetStringNumber(int string)
+{
+    SETUP_CONTEXT(cpp);
+    int line = 0;
+    DecodeSourceLoc(yylineno, NULL, &line);
+    yylineno = EncodeSourceLoc(string, line);
+}
+
+int GetStringNumber()
+{
+    SETUP_CONTEXT(cpp);
+    int string = 0;
+    DecodeSourceLoc(yylineno, &string, NULL);
+    return string;
+}
+
+int GetLineNumber()
+{
+    SETUP_CONTEXT(cpp);
+    int line = 0;
+    DecodeSourceLoc(yylineno, NULL, &line);
+    return line;
+}
+
+void IncLineNumber()
+{
+    SETUP_CONTEXT(cpp);
+    int string = 0, line = 0;
+    DecodeSourceLoc(yylineno, &string, &line);
+    yylineno = EncodeSourceLoc(string, ++line);
+}
+
+void DecLineNumber()
+{
+    SETUP_CONTEXT(cpp);
+    int string = 0, line = 0;
+    DecodeSourceLoc(yylineno, &string, &line);
+    yylineno = EncodeSourceLoc(string, --line);
+}
+
+void HandlePragma(const char **tokens, int numTokens)
+{
+    SETUP_CONTEXT(cpp);
+    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"))
+            context->contextPragma.optimize = true;
+        else if (!strcmp(tokens[2], "off"))
+            context->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"))
+            context->contextPragma.debug = true;
+        else if (!strcmp(tokens[2], "off"))
+            context->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)
+{
+    SETUP_CONTEXT(cpp);
+    TString strSrc;
+    strSrc = TString(string);
+
+    context->HashErrMsg = context->HashErrMsg + " " + strSrc;
+}
+
+const char* GetStrfromTStr(void)
+{
+    SETUP_CONTEXT(cpp);
+    cpp->ErrMsg = context->HashErrMsg.c_str();
+    return cpp->ErrMsg;
+}
+
+void ResetTString(void)
+{
+    SETUP_CONTEXT(cpp);
+    context->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)
+{
+    SETUP_CONTEXT(cpp);
+    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 = context->extensionBehavior.begin(); iter != context->extensionBehavior.end(); ++iter)
+                iter->second = behaviorVal;
+        }        
+    } else {
+        iter = context->extensionBehavior.find(TString(extName));
+        if (iter == context->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";
+                context->infoSink.info.message(EPrefixWarning, msg.c_str(), yylineno); 
+                break;
+            }
+            return;
+        } else
+            iter->second = behaviorVal;
+    }
+}
+}  // extern "C"
+
+int string_input(char* buf, int max_size, yyscan_t yyscanner) {
+    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;
+}
+
+int check_type(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+    
+    int token = IDENTIFIER;
+    TSymbol* symbol = yyextra->symbolTable.find(yytext);
+    if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) {
+        TVariable* variable = static_cast<TVariable*>(symbol);
+        if (variable->isUserType()) {
+            yyextra->lexAfterType = true;
+            token = TYPE_NAME;
+        }
+    }
+    yylval->lex.symbol = symbol;
+    return token;
+}
+
+int reserved_word(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+    yyextra->error(yylineno, "Illegal use of reserved word", yytext, "");
+    yyextra->recover();
+    return 0;
+}
+
+void yyerror(TParseContext* context, const char* reason) {
+    struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
+
+    if (context->AfterEOF) {
+        context->error(yylineno, reason, "unexpected EOF", "");
+    } else {
+        context->error(yylineno, reason, yytext, "");
+    }
+    context->recover();
+}
+
+int glslang_initialize(TParseContext* context) {
+    yyscan_t scanner = NULL;
+    if (yylex_init_extra(context, &scanner))
+        return 1;
+
+    context->scanner = scanner;
+    return 0;
+}
+
+int glslang_finalize(TParseContext* context) {
+    yyscan_t scanner = context->scanner;
+    if (scanner == NULL) return 0;
+    
+    context->scanner = NULL;
+    return yylex_destroy(scanner);
+}
+
+void glslang_scan(int count, const char* const string[], const int length[],
+                  TParseContext* context) {
+    yyrestart(NULL, context->scanner);
+    yyset_lineno(EncodeSourceLoc(0, 1), context->scanner);
+    context->AfterEOF = false;
+    
+    // Init preprocessor.
+    cpp->pC = context;
+    cpp->PaWhichStr = 0;
+    cpp->PaArgv     = string;
+    cpp->PaArgc     = count;
+    cpp->PaStrLen   = length;
+    cpp->pastFirstStatement = 0;
+    ScanFromString(string[0]);
+}
+
diff --git a/src/OpenGL ES 2.0/compiler/glslang.y b/src/OpenGL ES 2.0/compiler/glslang.y
new file mode 100644
index 0000000..b6fa163
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/glslang.y
@@ -0,0 +1,2078 @@
+/*
+//
+// 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 file contains the Yacc grammar for GLSL ES.
+Based on ANSI C Yacc grammar:
+http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_glslang_parser.sh,
+WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
+*/
+
+%{
+//
+// 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 file is auto-generated by generate_glslang_parser.sh. DO NOT EDIT!
+
+#include "compiler/SymbolTable.h"
+#include "compiler/ParseHelper.h"
+#include "GLSLANG/ShaderLang.h"
+
+#define YYLEX_PARAM context->scanner
+%}
+
+%expect 1 /* One shift reduce conflict because of if | else */
+%pure-parser
+%parse-param {TParseContext* context}
+
+%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;
+}
+
+%{
+extern int yylex(YYSTYPE* yylval_param, void* yyscanner);
+extern void yyerror(TParseContext* context, const char* reason);
+
+#define FRAG_VERT_ONLY(S, L) {  \
+    if (context->shaderType != SH_FRAGMENT_SHADER &&  \
+        context->shaderType != SH_VERTEX_SHADER) {  \
+        context->error(L, " supported in vertex/fragment shaders only ", S, "", "");  \
+        context->recover();  \
+    }  \
+}
+
+#define VERTEX_ONLY(S, L) {  \
+    if (context->shaderType != SH_VERTEX_SHADER) {  \
+        context->error(L, " supported in vertex shaders only ", S, "", "");  \
+        context->recover();  \
+    }  \
+}
+
+#define FRAG_ONLY(S, L) {  \
+    if (context->shaderType != SH_FRAGMENT_SHADER) {  \
+        context->error(L, " supported in fragment shaders only ", S, "", "");  \
+        context->recover();  \
+    }  \
+}
+%}
+
+%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) {
+            context->error($1.line, "undeclared identifier", $1.string->c_str(), "");
+            context->recover();
+            TType type(EbtFloat, EbpUndefined);
+            TVariable* fakeVariable = new TVariable($1.string, type);
+            context->symbolTable.insert(*fakeVariable);
+            variable = fakeVariable;
+        } else {
+            // This identifier can only be a variable type symbol
+            if (! symbol->isVariable()) {
+                context->error($1.line, "variable expected", $1.string->c_str(), "");
+                context->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 ) {
+            ConstantUnion* constArray = variable->getConstPointer();
+            TType t(variable->getType());
+            $$ = context->intermediate.addConstantUnion(constArray, t, $1.line);
+        } else
+            $$ = context->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)) {
+            context->error($1.line, " integer constant overflow", "", "");
+            context->recover();
+        }
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setIConst($1.i);
+        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $1.line);
+    }
+    | FLOATCONSTANT {
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setFConst($1.f);
+        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
+    }
+    | BOOLCONSTANT {
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setBConst($1.b);
+        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, 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())
+                context->error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str(), "");
+            else
+                context->error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", "");
+            context->recover();
+        }
+        if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) {
+            if ($1->isArray()) { // constant folding for arrays
+                $$ = context->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
+                $$ = context->addConstVectorNode(fields, $1, $2.line);
+            } else if ($1->isMatrix()) { // constant folding for matrices
+                $$ = context->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() ) {
+                    context->error($2.line, "", "[", "field selection out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
+                    context->recover();
+                } else {
+                    if ($1->isArray()) {
+                        if ($1->getType().getArraySize() == 0) {
+                            if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) {
+                                if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line))
+                                    context->recover();
+                            } else {
+                                if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line))
+                                    context->recover();
+                            }
+                        } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize()) {
+                            context->error($2.line, "", "[", "array index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
+                            context->recover();
+                        }
+                    }
+                    $$ = context->intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line);
+                }
+            } else {
+                if ($1->isArray() && $1->getType().getArraySize() == 0) {
+                    context->error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable");
+                    context->recover();
+                }
+
+                $$ = context->intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line);
+            }
+        }
+        if ($$ == 0) {
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setFConst(0.0f);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), $2.line);
+        } else if ($1->isArray()) {
+            if ($1->getType().getStruct())
+                $$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName()));
+            else
+                $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize(), $1->isMatrix()));
+
+            if ($1->getType().getQualifier() == EvqConst)
+                $$->getTypePointer()->setQualifier(EvqConst);
+        } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst)
+            $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, $1->getNominalSize()));
+        else if ($1->isMatrix())
+            $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize()));
+        else if ($1->isVector() && $1->getType().getQualifier() == EvqConst)
+            $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst));
+        else if ($1->isVector())
+            $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary));
+        else
+            $$->setType($1->getType());
+    }
+    | function_call {
+        $$ = $1;
+    }
+    | postfix_expression DOT FIELD_SELECTION {
+        if ($1->isArray()) {
+            context->error($3.line, "cannot apply dot operator to an array", ".", "");
+            context->recover();
+        }
+
+        if ($1->isVector()) {
+            TVectorFields fields;
+            if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+                fields.num = 1;
+                fields.offsets[0] = 0;
+                context->recover();
+            }
+
+            if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields
+                $$ = context->addConstVectorNode(fields, $1, $3.line);
+                if ($$ == 0) {
+                    context->recover();
+                    $$ = $1;
+                }
+                else
+                    $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size()));
+            } else {
+                if (fields.num == 1) {
+                    ConstantUnion *unionArray = new ConstantUnion[1];
+                    unionArray->setIConst(fields.offsets[0]);
+                    TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
+                    $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+                    $$->setType(TType($1->getBasicType(), $1->getPrecision()));
+                } else {
+                    TString vectorString = *$3.string;
+                    TIntermTyped* index = context->intermediate.addSwizzle(fields, $3.line);
+                    $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);
+                    $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size()));
+                }
+            }
+        } else if ($1->isMatrix()) {
+            TMatrixFields fields;
+            if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
+                fields.wholeRow = false;
+                fields.wholeCol = false;
+                fields.row = 0;
+                fields.col = 0;
+                context->recover();
+            }
+
+            if (fields.wholeRow || fields.wholeCol) {
+                context->error($2.line, " non-scalar fields not implemented yet", ".", "");
+                context->recover();
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setIConst(0);
+                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
+                $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+                $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize()));
+            } else {
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row);
+                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
+                $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
+                $$->setType(TType($1->getBasicType(), $1->getPrecision()));
+            }
+        } else if ($1->getBasicType() == EbtStruct) {
+            bool fieldFound = false;
+            const TTypeList* fields = $1->getType().getStruct();
+            if (fields == 0) {
+                context->error($2.line, "structure has no fields", "Internal Error", "");
+                context->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) {
+                        $$ = context->addConstStruct(*$3.string, $1, $2.line);
+                        if ($$ == 0) {
+                            context->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()->setQualifier(EvqConst);
+                        }
+                    } else {
+                        ConstantUnion *unionArray = new ConstantUnion[1];
+                        unionArray->setIConst(i);
+                        TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, $3.line);
+                        $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line);
+                        $$->setType(*(*fields)[i].type);
+                    }
+                } else {
+                    context->error($2.line, " no such field in structure", $3.string->c_str(), "");
+                    context->recover();
+                    $$ = $1;
+                }
+            }
+        } else {
+            context->error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str(), "");
+            context->recover();
+            $$ = $1;
+        }
+        // don't delete $3.string, it's from the pool
+    }
+    | postfix_expression INC_OP {
+        if (context->lValueErrorCheck($2.line, "++", $1))
+            context->recover();
+        $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->unaryOpError($2.line, "++", $1->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    | postfix_expression DEC_OP {
+        if (context->lValueErrorCheck($2.line, "--", $1))
+            context->recover();
+        $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->unaryOpError($2.line, "--", $1->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+integer_expression
+    : expression {
+        if (context->integerErrorCheck($1, "[]"))
+            context->recover();
+        $$ = $1;
+    }
+    ;
+
+function_call
+    : function_call_or_method {
+        TFunction* fnCall = $1.function;
+        TOperator op = fnCall->getBuiltInOp();
+
+        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, EbpUndefined);  // use this to get the type back
+            if (context->constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) {
+                $$ = 0;
+            } else {
+                //
+                // It's a constructor, of type 'type'.
+                //
+                $$ = context->addConstructor($1.intermNode, &type, op, fnCall, $1.line);
+            }
+
+            if ($$ == 0) {
+                context->recover();
+                $$ = context->intermediate.setAggregateOperator(0, op, $1.line);
+            }
+            $$->setType(type);
+        } else {
+            //
+            // Not a constructor.  Find it in the symbol table.
+            //
+            const TFunction* fnCandidate;
+            bool builtIn;
+            fnCandidate = context->findFunction($1.line, fnCall, &builtIn);
+            if (fnCandidate) {
+                //
+                // A declared function.
+                //
+                if (builtIn && !fnCandidate->getExtension().empty() &&
+                    context->extensionErrorCheck($1.line, fnCandidate->getExtension())) {
+                    context->recover();
+                }
+                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.
+                        //
+                        $$ = context->intermediate.addUnaryMath(op, $1.intermNode, 0, context->symbolTable);
+                        if ($$ == 0)  {
+                            context->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 {
+                        $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, $1.line);
+                    }
+                } else {
+                    // This is a real function call
+
+                    $$ = context->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;
+                    for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
+                        qual = fnCandidate->getParam(i).type->getQualifier();
+                        if (qual == EvqOut || qual == EvqInOut) {
+                            if (context->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {
+                                context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", "");
+                                context->recover();
+                            }
+                        }
+                    }
+                }
+                $$->setType(fnCandidate->getReturnType());
+            } else {
+                // error message was put out by PaFindFunction()
+                // Put on a dummy node for error recovery
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setFConst(0.0f);
+                $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
+                context->recover();
+            }
+        }
+        delete fnCall;
+    }
+    ;
+
+function_call_or_method
+    : function_call_generic {
+        $$ = $1;
+    }
+    | postfix_expression DOT function_call_generic {
+        context->error($3.line, "methods are not supported", "", "");
+        context->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 = context->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) {
+            // Constructors for arrays are not allowed.
+            context->error($1.line, "cannot construct this type", "array", "");
+            context->recover();
+            $1.setArray(false);
+        }
+
+        TOperator op = EOpNull;
+        if ($1.userDef) {
+            op = EOpConstructStruct;
+        } else {
+            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;
+            default: break;
+            }
+            if (op == EOpNull) {
+                context->error($1.line, "cannot construct this type", getBasicString($1.type), "");
+                context->recover();
+                $1.type = EbtFloat;
+                op = EOpConstructFloat;
+            }
+        }
+        TString tempString;
+        TType type($1);
+        TFunction *function = new TFunction(&tempString, type, op);
+        $$ = function;
+    }
+    | IDENTIFIER {
+        if (context->reservedErrorCheck($1.line, *$1.string))
+            context->recover();
+        TType type(EbtVoid, EbpUndefined);
+        TFunction *function = new TFunction($1.string, type);
+        $$ = function;
+    }
+    | FIELD_SELECTION {
+        if (context->reservedErrorCheck($1.line, *$1.string))
+            context->recover();
+        TType type(EbtVoid, EbpUndefined);
+        TFunction *function = new TFunction($1.string, type);
+        $$ = function;
+    }
+    ;
+
+unary_expression
+    : postfix_expression {
+        $$ = $1;
+    }
+    | INC_OP unary_expression {
+        if (context->lValueErrorCheck($1.line, "++", $2))
+            context->recover();
+        $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, context->symbolTable);
+        if ($$ == 0) {
+            context->unaryOpError($1.line, "++", $2->getCompleteString());
+            context->recover();
+            $$ = $2;
+        }
+    }
+    | DEC_OP unary_expression {
+        if (context->lValueErrorCheck($1.line, "--", $2))
+            context->recover();
+        $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, context->symbolTable);
+        if ($$ == 0) {
+            context->unaryOpError($1.line, "--", $2->getCompleteString());
+            context->recover();
+            $$ = $2;
+        }
+    }
+    | unary_operator unary_expression {
+        if ($1.op != EOpNull) {
+            $$ = context->intermediate.addUnaryMath($1.op, $2, $1.line, context->symbolTable);
+            if ($$ == 0) {
+                const char* errorOp = "";
+                switch($1.op) {
+                case EOpNegative:   errorOp = "-"; break;
+                case EOpLogicalNot: errorOp = "!"; break;
+                default: break;
+                }
+                context->unaryOpError($1.line, errorOp, $2->getCompleteString());
+                context->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; }
+    ;
+// 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);
+        $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    | multiplicative_expression SLASH unary_expression {
+        FRAG_VERT_ONLY("/", $2.line);
+        $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+additive_expression
+    : multiplicative_expression { $$ = $1; }
+    | additive_expression PLUS multiplicative_expression {
+        $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    | additive_expression DASH multiplicative_expression {
+        $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+shift_expression
+    : additive_expression { $$ = $1; }
+    ;
+
+relational_expression
+    : shift_expression { $$ = $1; }
+    | relational_expression LEFT_ANGLE shift_expression {
+        $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    | relational_expression RIGHT_ANGLE shift_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    | relational_expression LE_OP shift_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    | relational_expression GE_OP shift_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+equality_expression
+    : relational_expression { $$ = $1; }
+    | equality_expression EQ_OP relational_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    | equality_expression NE_OP relational_expression {
+        $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+and_expression
+    : equality_expression { $$ = $1; }
+    ;
+
+exclusive_or_expression
+    : and_expression { $$ = $1; }
+    ;
+
+inclusive_or_expression
+    : exclusive_or_expression { $$ = $1; }
+    ;
+
+logical_and_expression
+    : inclusive_or_expression { $$ = $1; }
+    | logical_and_expression AND_OP inclusive_or_expression {
+        $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+logical_xor_expression
+    : logical_and_expression { $$ = $1; }
+    | logical_xor_expression XOR_OP logical_and_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+logical_or_expression
+    : logical_xor_expression { $$ = $1; }
+    | logical_or_expression OR_OP logical_xor_expression  {
+        $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, context->symbolTable);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
+        }
+    }
+    ;
+
+conditional_expression
+    : logical_or_expression { $$ = $1; }
+    | logical_or_expression QUESTION expression COLON assignment_expression {
+       if (context->boolErrorCheck($2.line, $1))
+            context->recover();
+
+        $$ = context->intermediate.addSelection($1, $3, $5, $2.line);
+        if ($3->getType() != $5->getType())
+            $$ = 0;
+
+        if ($$ == 0) {
+            context->binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
+            context->recover();
+            $$ = $5;
+        }
+    }
+    ;
+
+assignment_expression
+    : conditional_expression { $$ = $1; }
+    | unary_expression assignment_operator assignment_expression {
+        if (context->lValueErrorCheck($2.line, "assign", $1))
+            context->recover();
+        $$ = context->intermediate.addAssign($2.op, $1, $3, $2.line);
+        if ($$ == 0) {
+            context->assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $1;
+        }
+    }
+    ;
+
+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; }
+    | ADD_ASSIGN   {                                    $$.line = $1.line; $$.op = EOpAddAssign; }
+    | SUB_ASSIGN   {                                    $$.line = $1.line; $$.op = EOpSubAssign; }
+    ;
+
+expression
+    : assignment_expression {
+        $$ = $1;
+    }
+    | expression COMMA assignment_expression {
+        $$ = context->intermediate.addComma($1, $3, $2.line);
+        if ($$ == 0) {
+            context->binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString());
+            context->recover();
+            $$ = $3;
+        }
+    }
+    ;
+
+constant_expression
+    : conditional_expression {
+        if (context->constErrorCheck($1))
+            context->recover();
+        $$ = $1;
+    }
+    ;
+
+declaration
+    : function_prototype SEMICOLON   {
+        TFunction &function = *($1.function);
+        
+        TIntermAggregate *prototype = new TIntermAggregate;
+        prototype->setType(function.getReturnType());
+        prototype->setName(function.getName());
+        
+        for (int i = 0; i < function.getParamCount(); i++)
+        {
+            const TParameter &param = function.getParam(i);
+            if (param.name != 0)
+            {
+                TVariable *variable = new TVariable(param.name, *param.type);
+                
+                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line);
+            }
+            else
+            {
+                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
+            }
+        }
+        
+        prototype->setOp(EOpPrototype);
+        $$ = prototype;
+    }
+    | init_declarator_list SEMICOLON {
+        if ($1.intermAggregate)
+            $1.intermAggregate->setOp(EOpDeclaration);
+        $$ = $1.intermAggregate;
+    }
+    | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
+        context->symbolTable.setDefaultPrecision( $3.type, $2 );
+        $$ = 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*>(context->symbolTable.find($1->getMangledName()));
+        if (prevDec) {
+            if (prevDec->getReturnType() != $1->getReturnType()) {
+                context->error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString(), "");
+                context->recover();
+            }
+            for (int i = 0; i < prevDec->getParamCount(); ++i) {
+                if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) {
+                    context->error($2.line, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString(), "");
+                    context->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;
+
+        context->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
+            //
+            context->error($2.line, "cannot be an argument type except for '(void)'", "void", "");
+            context->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) {
+            context->error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier), "");
+            context->recover();
+        }
+        // make sure a sampler is not involved as well...
+        if (context->structQualifierErrorCheck($2.line, $1))
+            context->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) {
+            context->error($2.line, "illegal use of type 'void'", $2.string->c_str(), "");
+            context->recover();
+        }
+        if (context->reservedErrorCheck($2.line, *$2.string))
+            context->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 (context->arrayTypeErrorCheck($3.line, $1))
+            context->recover();
+
+        if (context->reservedErrorCheck($2.line, *$2.string))
+            context->recover();
+
+        int size;
+        if (context->arraySizeErrorCheck($3.line, $4, size))
+            context->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 (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+            context->recover();
+    }
+    | parameter_qualifier parameter_declarator {
+        $$ = $2;
+        if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+            context->recover();
+        if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+            context->recover();
+    }
+    //
+    // Only type
+    //
+    | type_qualifier parameter_qualifier parameter_type_specifier {
+        $$ = $3;
+        if (context->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
+            context->recover();
+    }
+    | parameter_qualifier parameter_type_specifier {
+        $$ = $2;
+        if (context->parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
+            context->recover();
+        if (context->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
+            context->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;
+        
+        if ($$.type.precision == EbpUndefined) {
+            $$.type.precision = context->symbolTable.getDefaultPrecision($1.type.type);
+            if (context->precisionErrorCheck($1.line, $$.type.precision, $1.type.type)) {
+                context->recover();
+            }
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER {
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line);
+        $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, $3.line);
+        
+        if (context->structQualifierErrorCheck($3.line, $$.type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($3.line, *$3.string, $$.type))
+            context->recover();
+
+        TVariable* variable = 0;
+        if (context->nonInitErrorCheck($3.line, *$3.string, $$.type, variable))
+            context->recover();
+        if (symbol && variable)
+            symbol->setId(variable->getUniqueId());
+    }
+    | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
+        if (context->structQualifierErrorCheck($3.line, $1.type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type))
+            context->recover();
+
+        $$ = $1;
+
+        if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type))
+            context->recover();
+        else {
+            $1.type.setArray(true);
+            TVariable* variable;
+            if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+                context->recover();
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        if (context->structQualifierErrorCheck($3.line, $1.type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type))
+            context->recover();
+
+        $$ = $1;
+
+        if (context->arrayTypeErrorCheck($4.line, $1.type) || context->arrayQualifierErrorCheck($4.line, $1.type))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck($4.line, $5, size))
+                context->recover();
+            $1.type.setArray(true, size);
+            TVariable* variable = 0;
+            if (context->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
+                context->recover();
+            TType type = TType($1.type);
+            type.setArraySize(size);
+            $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, $3.line), $3.line);
+        }
+    }
+    | init_declarator_list COMMA IDENTIFIER EQUAL initializer {
+        if (context->structQualifierErrorCheck($3.line, $1.type))
+            context->recover();
+
+        $$ = $1;
+
+        TIntermNode* intermNode;
+        if (!context->executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) {
+            //
+            // build the intermediate representation
+            //
+            if (intermNode)
+        $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, $4.line);
+            else
+                $$.intermAggregate = $1.intermAggregate;
+        } else {
+            context->recover();
+            $$.intermAggregate = 0;
+        }
+    }
+    ;
+
+single_declaration
+    : fully_specified_type {
+        $$.type = $1;
+        $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line);
+    }
+    | fully_specified_type IDENTIFIER {
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line);
+        $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+        
+        if (context->structQualifierErrorCheck($2.line, $$.type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type))
+            context->recover();
+            
+            $$.type = $1;
+
+        TVariable* variable = 0;
+        if (context->nonInitErrorCheck($2.line, *$2.string, $$.type, variable))
+            context->recover();
+        if (variable && symbol)
+            symbol->setId(variable->getUniqueId());
+    }
+    | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
+        context->error($2.line, "unsized array declarations not supported", $2.string->c_str(), "");
+        context->recover();
+
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line);
+        $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+        $$.type = $1;
+    }
+    | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        TType type = TType($1);
+        int size;
+        if (context->arraySizeErrorCheck($2.line, $4, size))
+            context->recover();
+        type.setArraySize(size);
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, $2.line);
+        $$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
+        
+        if (context->structQualifierErrorCheck($2.line, $1))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck($2.line, *$2.string, $1))
+            context->recover();
+
+        $$.type = $1;
+
+        if (context->arrayTypeErrorCheck($3.line, $1) || context->arrayQualifierErrorCheck($3.line, $1))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck($3.line, $4, size))
+                context->recover();
+
+            $1.setArray(true, size);
+            TVariable* variable = 0;
+            if (context->arrayErrorCheck($3.line, *$2.string, $1, variable))
+                context->recover();
+            if (variable && symbol)
+                symbol->setId(variable->getUniqueId());
+        }
+    }
+    | fully_specified_type IDENTIFIER EQUAL initializer {
+        if (context->structQualifierErrorCheck($2.line, $1))
+            context->recover();
+
+        $$.type = $1;
+
+        TIntermNode* intermNode;
+        if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) {
+        //
+        // Build intermediate representation
+        //
+            if(intermNode)
+                $$.intermAggregate = context->intermediate.makeAggregate(intermNode, $3.line);
+            else
+                $$.intermAggregate = 0;
+        } else {
+            context->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 (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "input"))
+//            context->recover();
+//        UNPACK_ONLY("input", $1.line);
+//        $$.qualifier = EvqInput;
+//    }
+//    | OUTPUT {
+//        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "output"))
+//            context->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 (context->reservedErrorCheck($2.line, *$2.string, context))
+//            context->recover();
+//        $$.variable = new TVariable($2.string, $1);
+//        if (! context->symbolTable.insert(*$$.variable)) {
+//            context->error($2.line, "redefinition", $$.variable->getName().c_str(), "");
+//            context->recover();
+//            // don't have to delete $$.variable, the pool pop will take care of it
+//        }
+//    }
+//    ;
+
+fully_specified_type
+    : type_specifier {
+        $$ = $1;
+
+        if ($1.array) {
+            context->error($1.line, "not supported", "first-class array", "");
+            context->recover();
+            $1.setArray(false);
+        }
+    }
+    | type_qualifier type_specifier  {
+        if ($2.array) {
+            context->error($2.line, "not supported", "first-class array", "");
+            context->recover();
+            $2.setArray(false);
+        }
+
+        if ($1.qualifier == EvqAttribute &&
+            ($2.type == EbtBool || $2.type == EbtInt)) {
+            context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), "");
+            context->recover();
+        }
+        if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&
+            ($2.type == EbtBool || $2.type == EbtInt)) {
+            context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), "");
+            context->recover();
+        }
+        $$ = $2;
+        $$.qualifier = $1.qualifier;
+    }
+    ;
+
+type_qualifier
+    : CONST_QUAL {
+        $$.setBasic(EbtVoid, EvqConst, $1.line);
+    }
+    | ATTRIBUTE {
+        VERTEX_ONLY("attribute", $1.line);
+        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "attribute"))
+            context->recover();
+        $$.setBasic(EbtVoid, EvqAttribute, $1.line);
+    }
+    | VARYING {
+        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "varying"))
+            context->recover();
+        if (context->shaderType == SH_VERTEX_SHADER)
+            $$.setBasic(EbtVoid, EvqVaryingOut, $1.line);
+        else
+            $$.setBasic(EbtVoid, EvqVaryingIn, $1.line);
+    }
+    | INVARIANT VARYING {
+        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "invariant varying"))
+            context->recover();
+        if (context->shaderType == SH_VERTEX_SHADER)
+            $$.setBasic(EbtVoid, EvqInvariantVaryingOut, $1.line);
+        else
+            $$.setBasic(EbtVoid, EvqInvariantVaryingIn, $1.line);
+    }
+    | UNIFORM {
+        if (context->globalErrorCheck($1.line, context->symbolTable.atGlobalLevel(), "uniform"))
+            context->recover();
+        $$.setBasic(EbtVoid, EvqUniform, $1.line);
+    }
+    ;
+
+type_specifier
+    : type_specifier_no_prec {
+        $$ = $1;
+    }
+    | precision_qualifier type_specifier_no_prec {
+        $$ = $2;
+        $$.precision = $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 (context->arrayTypeErrorCheck($2.line, $1))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck($2.line, $3, size))
+                context->recover();
+            $$.setArray(true, size);
+        }
+    }
+    ;
+
+type_specifier_nonarray
+    : VOID_TYPE {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtVoid, qual, $1.line);
+    }
+    | FLOAT_TYPE {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+    }
+    | INT_TYPE {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+    }
+    | BOOL_TYPE {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+    }
+//    | UNSIGNED INT_TYPE {
+//        PACK_UNPACK_ONLY("unsigned", $1.line);
+//        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+//        $$.setBasic(EbtInt, qual, $1.line);
+//    }
+    | VEC2 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | VEC3 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | VEC4 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | BVEC2 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | BVEC3 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | BVEC4 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtBool, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | IVEC2 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(2);
+    }
+    | IVEC3 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(3);
+    }
+    | IVEC4 {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtInt, qual, $1.line);
+        $$.setAggregate(4);
+    }
+    | MATRIX2 {
+        FRAG_VERT_ONLY("mat2", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(2, true);
+    }
+    | MATRIX3 {
+        FRAG_VERT_ONLY("mat3", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(3, true);
+    }
+    | MATRIX4 {
+        FRAG_VERT_ONLY("mat4", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtFloat, qual, $1.line);
+        $$.setAggregate(4, true);
+    }
+    | SAMPLER2D {
+        FRAG_VERT_ONLY("sampler2D", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtSampler2D, qual, $1.line);
+    }
+    | SAMPLERCUBE {
+        FRAG_VERT_ONLY("samplerCube", $1.line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtSamplerCube, qual, $1.line);
+    }
+    | struct_specifier {
+        FRAG_VERT_ONLY("struct", $1.line);
+        $$ = $1;
+        $$.qualifier = context->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 = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        $$.setBasic(EbtStruct, qual, $1.line);
+        $$.userDef = &structure;
+    }
+    ;
+
+struct_specifier
+    : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE {
+        if (context->reservedErrorCheck($2.line, *$2.string))
+            context->recover();
+
+        TType* structure = new TType($4, *$2.string);
+        TVariable* userTypeDef = new TVariable($2.string, *structure, true);
+        if (! context->symbolTable.insert(*userTypeDef)) {
+            context->error($2.line, "redefinition", $2.string->c_str(), "struct");
+            context->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()) {
+                    context->error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str());
+                    context->recover();
+                }
+            }
+            $$->push_back((*$2)[i]);
+        }
+    }
+    ;
+
+struct_declaration
+    : type_specifier struct_declarator_list SEMICOLON {
+        $$ = $2;
+
+        if (context->voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) {
+            context->recover();
+        }
+        for (unsigned int i = 0; i < $$->size(); ++i) {
+            //
+            // Careful not to replace already known aspects of type, like array-ness
+            //
+            TType* type = (*$$)[i].type;
+            type->setBasicType($1.type);
+            type->setNominalSize($1.size);
+            type->setMatrix($1.matrix);
+
+            // don't allow arrays of arrays
+            if (type->isArray()) {
+                if (context->arrayTypeErrorCheck($1.line, $1))
+                    context->recover();
+            }
+            if ($1.array)
+                type->setArraySize($1.arraySize);
+            if ($1.userDef) {
+                type->setStruct($1.userDef->getStruct());
+                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 {
+        if (context->reservedErrorCheck($1.line, *$1.string))
+            context->recover();
+
+        $$.type = new TType(EbtVoid, EbpUndefined);
+        $$.line = $1.line;
+        $$.type->setFieldName(*$1.string);
+    }
+    | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
+        if (context->reservedErrorCheck($1.line, *$1.string))
+            context->recover();
+
+        $$.type = new TType(EbtVoid, EbpUndefined);
+        $$.line = $1.line;
+        $$.type->setFieldName(*$1.string);
+
+        int size;
+        if (context->arraySizeErrorCheck($2.line, $3, size))
+            context->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 { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE {
+        if ($3 != 0) {
+            $3->setOp(EOpSequence);
+            $3->setEndLine($5.line);
+        }
+        $$ = $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->setOp(EOpSequence);
+            $2->setEndLine($3.line);
+        }
+        $$ = $2;
+    }
+    ;
+
+statement_list
+    : statement {
+        $$ = context->intermediate.makeAggregate($1, 0);
+    }
+    | statement_list statement {
+        $$ = context->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 (context->boolErrorCheck($1.line, $3))
+            context->recover();
+        $$ = context->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 (context->boolErrorCheck($1->getLine(), $1))
+            context->recover();
+    }
+    | fully_specified_type IDENTIFIER EQUAL initializer {
+        TIntermNode* intermNode;
+        if (context->structQualifierErrorCheck($2.line, $1))
+            context->recover();
+        if (context->boolErrorCheck($2.line, $1))
+            context->recover();
+
+        if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode))
+            $$ = $4;
+        else {
+            context->recover();
+            $$ = 0;
+        }
+    }
+    ;
+
+iteration_statement
+    : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
+        context->symbolTable.pop();
+        $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, $1.line);
+        --context->loopNestingLevel;
+    }
+    | DO { ++context->loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
+        if (context->boolErrorCheck($8.line, $6))
+            context->recover();
+
+        $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, $4.line);
+        --context->loopNestingLevel;
+    }
+    | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
+        context->symbolTable.pop();
+        $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, $1.line);
+        --context->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 (context->loopNestingLevel <= 0) {
+            context->error($1.line, "continue statement only allowed in loops", "", "");
+            context->recover();
+        }
+        $$ = context->intermediate.addBranch(EOpContinue, $1.line);
+    }
+    | BREAK SEMICOLON {
+        if (context->loopNestingLevel <= 0) {
+            context->error($1.line, "break statement only allowed in loops", "", "");
+            context->recover();
+        }
+        $$ = context->intermediate.addBranch(EOpBreak, $1.line);
+    }
+    | RETURN SEMICOLON {
+        $$ = context->intermediate.addBranch(EOpReturn, $1.line);
+        if (context->currentFunctionType->getBasicType() != EbtVoid) {
+            context->error($1.line, "non-void function must return a value", "return", "");
+            context->recover();
+        }
+    }
+    | RETURN expression SEMICOLON {
+        $$ = context->intermediate.addBranch(EOpReturn, $2, $1.line);
+        context->functionReturnsValue = true;
+        if (context->currentFunctionType->getBasicType() == EbtVoid) {
+            context->error($1.line, "void function cannot return a value", "return", "");
+            context->recover();
+        } else if (*(context->currentFunctionType) != $2->getType()) {
+            context->error($1.line, "function return is not matching type:", "return", "");
+            context->recover();
+        }
+    }
+    | DISCARD SEMICOLON {
+        FRAG_ONLY("discard", $1.line);
+        $$ = context->intermediate.addBranch(EOpKill, $1.line);
+    }
+    ;
+
+// Grammar Note:  No 'goto'.  Gotos are not supported.
+
+translation_unit
+    : external_declaration {
+        $$ = $1;
+        context->treeRoot = $$;
+    }
+    | translation_unit external_declaration {
+        $$ = context->intermediate.growAggregate($1, $2, 0);
+        context->treeRoot = $$;
+    }
+    ;
+
+external_declaration
+    : function_definition {
+        $$ = $1;
+    }
+    | declaration {
+        $$ = $1;
+    }
+    ;
+
+function_definition
+    : function_prototype {
+        TFunction* function = $1.function;
+        TFunction* prevDec = static_cast<TFunction*>(context->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.
+            //
+            context->error($1.line, "function already has a body", function->getName().c_str(), "");
+            context->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) {
+                context->error($1.line, "function cannot take any parameter(s)", function->getName().c_str(), "");
+                context->recover();
+            }
+            if (function->getReturnType().getBasicType() != EbtVoid) {
+                context->error($1.line, "", function->getReturnType().getBasicString(), "main function cannot return a value");
+                context->recover();
+            }
+        }
+
+        //
+        // New symbol table scope for body of function plus its arguments
+        //
+        context->symbolTable.push();
+
+        //
+        // Remember the return type for later checking for RETURN statements.
+        //
+        context->currentFunctionType = &(prevDec->getReturnType());
+        context->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++) {
+            const TParameter& param = function->getParam(i);
+            if (param.name != 0) {
+                TVariable *variable = new TVariable(param.name, *param.type);
+                //
+                // Insert the parameters with name in the symbol table.
+                //
+                if (! context->symbolTable.insert(*variable)) {
+                    context->error($1.line, "redefinition", variable->getName().c_str(), "");
+                    context->recover();
+                    delete variable;
+                }
+
+                //
+                // Add the parameter to the HIL
+                //
+                paramNodes = context->intermediate.growAggregate(
+                                               paramNodes,
+                                               context->intermediate.addSymbol(variable->getUniqueId(),
+                                                                       variable->getName(),
+                                                                       variable->getType(), $1.line),
+                                               $1.line);
+            } else {
+                paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
+            }
+        }
+        context->intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line);
+        $1.intermAggregate = paramNodes;
+        context->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 (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
+            context->error($1.line, "function does not return a value:", "", $1.function->getName().c_str());
+            context->recover();
+        }
+        context->symbolTable.pop();
+        $$ = context->intermediate.growAggregate($1.intermAggregate, $3, 0);
+        context->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(context->contextPragma.optimize);
+        $$->getAsAggregate()->setDebug(context->contextPragma.debug);
+        $$->getAsAggregate()->addToPragmaTable(context->contextPragma.pragmaTable);
+
+        if ($3 && $3->getAsAggregate())
+            $$->getAsAggregate()->setEndLine($3->getAsAggregate()->getEndLine());
+    }
+    ;
+
+%%
+
+int glslang_parse(TParseContext* context) {
+    return yyparse(context);
+}
+
diff --git a/src/OpenGL ES 2.0/compiler/glslang_lex.cpp b/src/OpenGL ES 2.0/compiler/glslang_lex.cpp
new file mode 100644
index 0000000..9d5f53f
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/glslang_lex.cpp
@@ -0,0 +1,3186 @@
+#line 17 "compiler/glslang.l"
+//
+// Copyright (c) 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 file is auto-generated by generate_glslang_lexer.sh. DO NOT EDIT!
+
+
+
+#line 13 "compiler/glslang_lex.cpp"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+     *       access to the local variable yy_act. Since yyless() is a macro, it would break
+     *       existing scanners that call yyless() from OUTSIDE yylex. 
+     *       One obvious solution it to make yy_act a global. I tried that, and saw
+     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+     *       normally declared as a register variable-- so it is not worth it.
+     */
+    #define  YY_LESS_LINENO(n) \
+            do { \
+                int yyl;\
+                for ( yyl = n; yyl < yyleng; ++yyl )\
+                    if ( yytext[yyl] == '\n' )\
+                        --yylineno;\
+            }while(0)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = yyg->yy_hold_char; \
+		YY_RESTORE_YY_MORE_OFFSET \
+		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void yypop_buffer_state (yyscan_t yyscanner );
+
+static void yyensure_buffer_stack (yyscan_t yyscanner );
+static void yy_load_buffer_state (yyscan_t yyscanner );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void yyfree (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	yyg->yytext_ptr = yy_bp; \
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	yyg->yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+	yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 145
+#define YY_END_OF_BUFFER 146
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[411] =
+    {   0,
+        0,    0,    0,    0,    0,    0,  146,  144,  143,  143,
+      128,  134,  139,  123,  124,  132,  131,  120,  129,  127,
+      133,   92,   92,  121,  117,  135,  122,  136,  140,   88,
+      125,  126,  138,   88,   88,   88,   88,   88,   88,   88,
+       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
+       88,   88,   88,  118,  137,  119,  130,    3,    4,    3,
+      142,  145,  141,  114,  100,  119,  108,  103,   98,  106,
+       96,  107,   97,   95,    2,    1,   99,   94,   90,   91,
+        0,    0,   92,  126,  118,  125,  115,  111,  113,  112,
+      116,   88,  104,  110,   88,   88,   88,   88,   88,   88,
+
+       88,   88,   88,   88,   17,   88,   88,   88,   88,   88,
+       88,   88,   88,   88,   88,   88,   88,   88,   20,   22,
+       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
+       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
+       88,   88,   88,   88,   88,   88,  105,  109,    5,  141,
+        0,    1,   94,    0,    0,   93,   89,  101,  102,   48,
+       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
+       88,   88,   88,   88,   88,   88,   88,   18,   88,   88,
+       88,   88,   88,   88,   88,   88,   26,   88,   88,   88,
+       88,   88,   88,   88,   88,   23,   88,   88,   88,   88,
+
+       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
+       88,   88,   88,   88,   88,   88,   88,   88,    0,   95,
+        0,   94,   88,   28,   88,   88,   85,   88,   88,   88,
+       88,   88,   88,   88,   21,   51,   88,   88,   88,   88,
+       88,   56,   70,   88,   88,   88,   88,   88,   88,   88,
+       88,   67,    9,   33,   34,   35,   88,   88,   88,   88,
+       88,   88,   88,   88,   88,   88,   88,   88,   88,   88,
+       88,   54,   29,   88,   88,   88,   88,   88,   88,   36,
+       37,   38,   27,   88,   88,   88,   15,   42,   43,   44,
+       49,   12,   88,   88,   88,   88,   81,   82,   83,   88,
+
+       30,   71,   25,   78,   79,   80,    7,   75,   76,   77,
+       88,   24,   73,   88,   88,   39,   40,   41,   88,   88,
+       88,   88,   88,   88,   88,   88,   88,   68,   88,   88,
+       88,   88,   88,   88,   88,   50,   88,   87,   88,   88,
+       19,   88,   88,   88,   88,   69,   64,   59,   88,   88,
+       88,   88,   88,   74,   55,   88,   62,   32,   88,   84,
+       63,   47,   57,   88,   88,   88,   88,   88,   88,   88,
+       88,   58,   31,   88,   88,   88,    8,   88,   88,   88,
+       88,   88,   52,   13,   88,   14,   88,   88,   16,   65,
+       88,   88,   88,   60,   88,   88,   88,   53,   72,   61,
+
+       11,   66,    6,   86,   10,   45,   88,   88,   46,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        2,    2,    2,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    4,    1,    1,    1,    5,    6,    1,    7,
+        8,    9,   10,   11,   12,   13,   14,   15,   16,   17,
+       18,   19,   16,   16,   16,   20,   20,   21,   22,   23,
+       24,   25,   26,    1,   27,   27,   28,   29,   30,   27,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   32,   31,   31,
+       33,    1,   34,   35,   31,    1,   36,   37,   38,   39,
+
+       40,   41,   42,   43,   44,   31,   45,   46,   47,   48,
+       49,   50,   31,   51,   52,   53,   54,   55,   56,   57,
+       58,   59,   60,   61,   62,   63,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[64] =
+    {   0,
+        1,    1,    2,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    3,    3,    3,    3,    3,    3,
+        1,    1,    1,    1,    1,    1,    3,    3,    3,    3,
+        4,    4,    1,    1,    1,    3,    3,    3,    3,    3,
+        3,    4,    4,    4,    4,    4,    4,    4,    4,    4,
+        4,    4,    4,    4,    4,    4,    4,    4,    4,    1,
+        1,    1,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[416] =
+    {   0,
+        0,    0,   61,   62,   71,    0,  606,  607,  607,  607,
+      581,   42,  129,  607,  607,  580,  126,  607,  125,  123,
+      137,  149,  157,  578,  607,  175,  578,   44,  607,    0,
+      607,  607,  120,   95,  103,  142,  146,  136,  156,  552,
+      168,  162,  551,  120,  158,  545,  173,  558,  172,  178,
+      111,  186,  554,  607,  159,  607,  607,  607,  607,  582,
+      607,  607,    0,  607,  607,  607,  607,  607,  607,  607,
+      607,  607,  607,  222,  607,    0,  607,  228,  254,  262,
+      281,    0,  290,  607,  607,  607,  571,  607,  607,  607,
+      570,    0,  607,  607,  546,  539,  542,  550,  549,  536,
+
+      551,  538,  544,  532,  529,  542,  529,  526,  526,  532,
+      520,  527,  524,  534,  520,  526,  529,  530,    0,  204,
+      529,  207,  515,  528,  519,  521,  511,  525,  522,  524,
+      507,  512,  509,  498,  183,  512,  508,  510,  499,  502,
+      212,  507,  499,  511,  186,  504,  607,  607,  607,    0,
+      306,    0,  316,  332,  270,  342,    0,  607,  607,    0,
+      496,  500,  509,  506,  490,  490,  161,  505,  502,  502,
+      500,  497,  489,  495,  482,  493,  496,    0,  493,  481,
+      488,  485,  489,  482,  471,  470,  483,  486,  483,  478,
+      469,  294,  474,  477,  468,  465,  469,  475,  466,  457,
+
+      460,  458,  468,  454,  452,  452,  454,  451,  462,  461,
+      278,  456,  451,  440,  320,  458,  460,  449,  348,  354,
+      360,  366,  450,    0,  448,  336,    0,  440,  438,  446,
+      435,  452,  441,  370,    0,    0,  435,  445,  445,  430,
+      373,    0,    0,  432,  376,  433,  427,  426,  427,  426,
+      379,    0,    0,    0,    0,    0,  422,  423,  428,  419,
+      432,  427,  426,  418,  422,  414,  417,  421,  426,  425,
+      416,    0,    0,  422,  411,  411,  416,  415,  412,    0,
+        0,    0,    0,  402,  414,  416,    0,    0,    0,    0,
+        0,    0,  404,  405,  399,  409,    0,    0,    0,  400,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+      407,    0,    0,  405,  401,    0,    0,    0,  397,  393,
+      398,  388,  401,  387,  400,  389,  396,    0,  394,  396,
+      380,  389,  395,  390,  378,    0,  380,    0,  379,  382,
+        0,  371,  370,  370,  383,    0,  385,    0,  384,  383,
+      368,  381,  368,    0,    0,  371,    0,    0,  363,    0,
+        0,    0,    0,  360,  371,  364,  368,  303,  297,  288,
+      300,    0,    0,  283,  290,  269,    0,  277,  274,  255,
+      232,  255,    0,    0,  244,    0,  236,  226,    0,    0,
+      225,  208,  211,    0,  185,  202,  131,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,  134,  117,    0,  607,
+      398,  400,  402,  406,  142
+    } ;
+
+static yyconst flex_int16_t yy_def[416] =
+    {   0,
+      410,    1,  411,  411,  410,    5,  410,  410,  410,  410,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  412,
+      410,  410,  410,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  410,  410,  410,  410,  410,  410,  410,
+      410,  410,  413,  410,  410,  410,  410,  410,  410,  410,
+      410,  410,  410,  410,  410,  414,  410,  410,  410,  410,
+      410,  415,  410,  410,  410,  410,  410,  410,  410,  410,
+      410,  412,  410,  410,  412,  412,  412,  412,  412,  412,
+
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  410,  410,  410,  413,
+      410,  414,  410,  410,  410,  410,  415,  410,  410,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  410,  410,
+      410,  410,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+      412,  412,  412,  412,  412,  412,  412,  412,  412,  412,
+
+      412,  412,  412,  412,  412,  412,  412,  412,  412,    0,
+      410,  410,  410,  410,  410
+    } ;
+
+static yyconst flex_int16_t yy_nxt[671] =
+    {   0,
+        8,    9,   10,   11,   12,   13,   14,   15,   16,   17,
+       18,   19,   20,   21,   22,   23,   23,   23,   23,   23,
+       24,   25,   26,   27,   28,   29,   30,   30,   30,   30,
+       30,   30,   31,   32,   33,   34,   35,   36,   37,   38,
+       39,   40,   41,   42,   30,   43,   44,   45,   46,   47,
+       48,   49,   50,   51,   52,   53,   30,   30,   30,   54,
+       55,   56,   57,   59,   59,   65,   66,   90,   91,   60,
+       60,    8,   61,   62,    8,    8,    8,    8,    8,    8,
+        8,    8,    8,    8,    8,    8,    8,    8,    8,    8,
+        8,    8,    8,    8,    8,    8,    8,   63,   63,   63,
+
+       63,   63,   63,    8,    8,    8,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+        8,    8,    8,    8,   67,   70,   72,   74,   74,   74,
+       74,   74,   74,   93,  157,   75,   95,   96,   73,   71,
+       76,   97,   68,   98,   94,  123,  409,   99,  141,  124,
+       77,   78,  142,   79,   79,   79,   79,   79,   80,   78,
+      408,   83,   83,   83,   83,   83,   83,  100,   81,   85,
+       82,  107,  147,  108,  407,  103,   81,  101,   81,  104,
+      102,  110,  109,  125,  105,   86,   81,   87,   88,  111,
+
+      106,  112,  119,  116,  113,   82,  126,  132,  128,  120,
+      114,  117,  229,  230,  133,  134,  121,  137,  204,  148,
+      138,  143,  118,  129,  135,  144,  130,  136,  139,  216,
+      406,  217,  405,  205,  145,  140,   74,   74,   74,   74,
+       74,   74,  153,  153,  153,  153,  153,  153,  396,  184,
+      404,  151,  185,  186,  190,  211,  187,  154,  188,  397,
+      403,  151,  191,  212,  402,  401,   78,  154,   79,   79,
+       79,   79,   79,   80,   78,  400,   80,   80,   80,   80,
+       80,   80,  399,   81,  156,  156,  156,  156,  156,  156,
+      155,   81,  155,   81,  398,  156,  156,  156,  156,  156,
+
+      156,   81,   78,  395,   83,   83,   83,   83,   83,   83,
+      254,  255,  256,  394,  393,  219,  392,  219,  275,   81,
+      220,  220,  220,  220,  220,  220,  276,  391,  390,   81,
+      153,  153,  153,  153,  153,  153,  280,  281,  282,  389,
+      388,  221,  387,  221,  386,  154,  222,  222,  222,  222,
+      222,  222,  288,  289,  290,  154,  156,  156,  156,  156,
+      156,  156,  220,  220,  220,  220,  220,  220,  220,  220,
+      220,  220,  220,  220,  222,  222,  222,  222,  222,  222,
+      222,  222,  222,  222,  222,  222,  297,  298,  299,  304,
+      305,  306,  308,  309,  310,  316,  317,  318,   58,   58,
+
+       58,   58,   92,   92,  150,  150,  152,  385,  152,  152,
+      384,  383,  382,  381,  380,  379,  378,  377,  376,  375,
+      374,  373,  372,  371,  370,  369,  368,  367,  366,  365,
+      364,  363,  362,  361,  360,  359,  358,  357,  356,  355,
+      354,  353,  352,  351,  350,  349,  348,  347,  346,  345,
+      344,  343,  342,  341,  340,  339,  338,  337,  336,  335,
+      334,  333,  332,  331,  330,  329,  328,  327,  326,  325,
+      324,  323,  322,  321,  320,  319,  315,  314,  313,  312,
+      311,  307,  303,  302,  301,  300,  296,  295,  294,  293,
+      292,  291,  287,  286,  285,  284,  283,  279,  278,  277,
+
+      274,  273,  272,  271,  270,  269,  268,  267,  266,  265,
+      264,  263,  262,  261,  260,  259,  258,  257,  253,  252,
+      251,  250,  249,  248,  247,  246,  245,  244,  243,  242,
+      241,  240,  239,  238,  237,  236,  235,  234,  233,  232,
+      231,  228,  227,  226,  225,  224,  223,  218,  215,  214,
+      213,  210,  209,  208,  207,  206,  203,  202,  201,  200,
+      199,  198,  197,  196,  195,  194,  193,  192,  189,  183,
+      182,  181,  180,  179,  178,  177,  176,  175,  174,  173,
+      172,  171,  170,  169,  168,  167,  166,  165,  164,  163,
+      162,  161,  160,  159,  158,  149,  146,  131,  127,  122,
+
+      115,   89,   84,   69,   64,  410,    7,  410,  410,  410,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410
+    } ;
+
+static yyconst flex_int16_t yy_chk[671] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    3,    4,   12,   12,   28,   28,    3,
+        4,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,   13,   17,   19,   20,   20,   20,
+       20,   20,   20,   33,  415,   21,   34,   34,   19,   17,
+       21,   35,   13,   35,   33,   44,  408,   35,   51,   44,
+       21,   22,   51,   22,   22,   22,   22,   22,   22,   23,
+      407,   23,   23,   23,   23,   23,   23,   36,   22,   26,
+       22,   38,   55,   38,  397,   37,   23,   36,   22,   37,
+       36,   39,   38,   45,   37,   26,   23,   26,   26,   39,
+
+       37,   39,   42,   41,   39,   22,   45,   49,   47,   42,
+       39,   41,  167,  167,   49,   49,   42,   50,  135,   55,
+       50,   52,   41,   47,   49,   52,   47,   49,   50,  145,
+      396,  145,  395,  135,   52,   50,   74,   74,   74,   74,
+       74,   74,   78,   78,   78,   78,   78,   78,  381,  120,
+      393,   74,  120,  120,  122,  141,  120,   78,  120,  381,
+      392,   74,  122,  141,  391,  388,   79,   78,   79,   79,
+       79,   79,   79,   79,   80,  387,   80,   80,   80,   80,
+       80,   80,  385,   79,  155,  155,  155,  155,  155,  155,
+       81,   80,   81,   79,  382,   81,   81,   81,   81,   81,
+
+       81,   80,   83,  380,   83,   83,   83,   83,   83,   83,
+      192,  192,  192,  379,  378,  151,  376,  151,  211,   83,
+      151,  151,  151,  151,  151,  151,  211,  375,  374,   83,
+      153,  153,  153,  153,  153,  153,  215,  215,  215,  371,
+      370,  154,  369,  154,  368,  153,  154,  154,  154,  154,
+      154,  154,  226,  226,  226,  153,  156,  156,  156,  156,
+      156,  156,  219,  219,  219,  219,  219,  219,  220,  220,
+      220,  220,  220,  220,  221,  221,  221,  221,  221,  221,
+      222,  222,  222,  222,  222,  222,  234,  234,  234,  241,
+      241,  241,  245,  245,  245,  251,  251,  251,  411,  411,
+
+      411,  411,  412,  412,  413,  413,  414,  367,  414,  414,
+      366,  365,  364,  359,  356,  353,  352,  351,  350,  349,
+      347,  345,  344,  343,  342,  340,  339,  337,  335,  334,
+      333,  332,  331,  330,  329,  327,  326,  325,  324,  323,
+      322,  321,  320,  319,  315,  314,  311,  300,  296,  295,
+      294,  293,  286,  285,  284,  279,  278,  277,  276,  275,
+      274,  271,  270,  269,  268,  267,  266,  265,  264,  263,
+      262,  261,  260,  259,  258,  257,  250,  249,  248,  247,
+      246,  244,  240,  239,  238,  237,  233,  232,  231,  230,
+      229,  228,  225,  223,  218,  217,  216,  214,  213,  212,
+
+      210,  209,  208,  207,  206,  205,  204,  203,  202,  201,
+      200,  199,  198,  197,  196,  195,  194,  193,  191,  190,
+      189,  188,  187,  186,  185,  184,  183,  182,  181,  180,
+      179,  177,  176,  175,  174,  173,  172,  171,  170,  169,
+      168,  166,  165,  164,  163,  162,  161,  146,  144,  143,
+      142,  140,  139,  138,  137,  136,  134,  133,  132,  131,
+      130,  129,  128,  127,  126,  125,  124,  123,  121,  118,
+      117,  116,  115,  114,  113,  112,  111,  110,  109,  108,
+      107,  106,  105,  104,  103,  102,  101,  100,   99,   98,
+       97,   96,   95,   91,   87,   60,   53,   48,   46,   43,
+
+       40,   27,   24,   16,   11,    7,  410,  410,  410,  410,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410
+    } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[146] =
+    {   0,
+0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 1, 0, 0,     };
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+/*
+//
+// 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 file contains the Lex specification for GLSL ES.
+Based on ANSI C grammar, Lex specification:
+http://www.lysator.liu.se/c/ANSI-C-grammar-l.html
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_glslang_lexer.sh,
+WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
+*/
+
+#include "compiler/glslang.h"
+#include "compiler/ParseHelper.h"
+#include "compiler/util.h"
+#include "glslang_tab.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+#pragma warning(disable : 4102)
+#endif
+
+#define YY_USER_ACTION yylval->lex.line = yylineno;
+#define YY_INPUT(buf, result, max_size) \
+    result = string_input(buf, max_size, yyscanner);
+
+static int string_input(char* buf, int max_size, yyscan_t yyscanner);
+static int check_type(yyscan_t yyscanner);
+static int reserved_word(yyscan_t yyscanner);
+
+#define INITIAL 0
+#define COMMENT 1
+#define FIELDS 2
+
+#define YY_EXTRA_TYPE TParseContext*
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+    {
+
+    /* User-defined. Not touched by flex. */
+    YY_EXTRA_TYPE yyextra_r;
+
+    /* The rest are the same as the globals declared in the non-reentrant scanner. */
+    FILE *yyin_r, *yyout_r;
+    size_t yy_buffer_stack_top; /**< index of top of stack. */
+    size_t yy_buffer_stack_max; /**< capacity of stack. */
+    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+    char yy_hold_char;
+    int yy_n_chars;
+    int yyleng_r;
+    char *yy_c_buf_p;
+    int yy_init;
+    int yy_start;
+    int yy_did_buffer_switch_on_eof;
+    int yy_start_stack_ptr;
+    int yy_start_stack_depth;
+    int *yy_start_stack;
+    yy_state_type yy_last_accepting_state;
+    char* yy_last_accepting_cpos;
+
+    int yylineno_r;
+    int yy_flex_debug_r;
+
+    char *yytext_r;
+    int yy_more_flag;
+    int yy_more_len;
+
+    YYSTYPE * yylval_r;
+
+    }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+    /* This must go here because YYSTYPE and YYLTYPE are included
+     * from bison output in section 1.*/
+    #    define yylval yyg->yylval_r
+    
+int yylex_init (yyscan_t* scanner);
+
+int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (yyscan_t yyscanner );
+
+int yyget_debug (yyscan_t yyscanner );
+
+void yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *yyget_in (yyscan_t yyscanner );
+
+void yyset_in  (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *yyget_out (yyscan_t yyscanner );
+
+void yyset_out  (FILE * out_str ,yyscan_t yyscanner );
+
+int yyget_leng (yyscan_t yyscanner );
+
+char *yyget_text (yyscan_t yyscanner );
+
+int yyget_lineno (yyscan_t yyscanner );
+
+void yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+YYSTYPE * yyget_lval (yyscan_t yyscanner );
+
+void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (yyscan_t yyscanner );
+#else
+extern int yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+    static void yy_push_state (int new_state ,yyscan_t yyscanner);
+    
+    static void yy_pop_state (yyscan_t yyscanner );
+    
+    static int yy_top_state (yyscan_t yyscanner );
+    
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		int n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex \
+               (YYSTYPE * yylval_param ,yyscan_t yyscanner);
+
+#define YY_DECL int yylex \
+               (YYSTYPE * yylval_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    TParseContext* context = yyextra;
+
+    /* Single-line comments */
+
+    yylval = yylval_param;
+
+	if ( !yyg->yy_init )
+		{
+		yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! yyg->yy_start )
+			yyg->yy_start = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			yyensure_buffer_stack (yyscanner);
+			YY_CURRENT_BUFFER_LVALUE =
+				yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+		}
+
+		yy_load_buffer_state(yyscanner );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = yyg->yy_c_buf_p;
+
+		/* Support of yytext. */
+		*yy_cp = yyg->yy_hold_char;
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = yyg->yy_start;
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				yyg->yy_last_accepting_state = yy_current_state;
+				yyg->yy_last_accepting_cpos = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 411 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_current_state != 410 );
+		yy_cp = yyg->yy_last_accepting_cpos;
+		yy_current_state = yyg->yy_last_accepting_state;
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+			{
+			int yyl;
+			for ( yyl = 0; yyl < yyleng; ++yyl )
+				if ( yytext[yyl] == '\n' )
+					   
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+			}
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = yyg->yy_hold_char;
+			yy_cp = yyg->yy_last_accepting_cpos;
+			yy_current_state = yyg->yy_last_accepting_state;
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+;
+	YY_BREAK
+/* Multi-line comments */
+case 2:
+YY_RULE_SETUP
+{ yy_push_state(COMMENT, yyscanner); }
+	YY_BREAK
+case 3:
+case 4:
+/* rule 4 can match eol */
+YY_RULE_SETUP
+;
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+{ yy_pop_state(yyscanner); }
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+{ return(INVARIANT); }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+{ return(HIGH_PRECISION); }
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+{ return(MEDIUM_PRECISION); }
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+{ return(LOW_PRECISION); }
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+{ return(PRECISION); }
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+{ return(ATTRIBUTE); }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+{ return(CONST_QUAL); }
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+{ return(UNIFORM); }
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+{ return(VARYING); }
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+{ return(BREAK); }
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+{ return(CONTINUE); }
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+{ return(DO); }
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+{ return(FOR); }
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+{ return(WHILE); }
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+{ return(IF); }
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+{ return(ELSE); }
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+{ return(IN_QUAL); }
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+{ return(OUT_QUAL); }
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+{ return(INOUT_QUAL); }
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(FLOAT_TYPE); }
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(INT_TYPE); }
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(VOID_TYPE); }
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(BOOL_TYPE); }
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+{ yylval->lex.b = true;  return(BOOLCONSTANT); }
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+{ yylval->lex.b = false; return(BOOLCONSTANT); }
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+{ return(DISCARD); }
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+{ return(RETURN); }
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(MATRIX2); }
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(MATRIX3); }
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(MATRIX4); }
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (VEC2); }
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (VEC3); }
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (VEC4); }
+	YY_BREAK
+case 39:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (IVEC2); }
+	YY_BREAK
+case 40:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (IVEC3); }
+	YY_BREAK
+case 41:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (IVEC4); }
+	YY_BREAK
+case 42:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (BVEC2); }
+	YY_BREAK
+case 43:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (BVEC3); }
+	YY_BREAK
+case 44:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return (BVEC4); }
+	YY_BREAK
+case 45:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return SAMPLER2D; }
+	YY_BREAK
+case 46:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return SAMPLERCUBE; }
+	YY_BREAK
+case 47:
+YY_RULE_SETUP
+{ context->lexAfterType = true; return(STRUCT); }
+	YY_BREAK
+case 48:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 49:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 50:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 51:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 52:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 53:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 54:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 55:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 56:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 57:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 58:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 59:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 60:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 61:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 62:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 63:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 64:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 65:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 66:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 67:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 68:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 69:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 70:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 71:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 72:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 73:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 74:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 75:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 76:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 77:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 78:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 79:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 80:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 81:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 82:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 83:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 84:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 85:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 86:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 87:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+	YY_BREAK
+case 88:
+YY_RULE_SETUP
+{
+   yylval->lex.string = NewPoolTString(yytext); 
+   return check_type(yyscanner);
+}
+	YY_BREAK
+case 89:
+YY_RULE_SETUP
+{ yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+	YY_BREAK
+case 90:
+YY_RULE_SETUP
+{ yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+	YY_BREAK
+case 91:
+YY_RULE_SETUP
+{ context->error(yylineno, "Invalid Octal number.", yytext, "", ""); context->recover(); return 0;}
+	YY_BREAK
+case 92:
+YY_RULE_SETUP
+{ yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
+	YY_BREAK
+case 93:
+YY_RULE_SETUP
+{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+	YY_BREAK
+case 94:
+YY_RULE_SETUP
+{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+	YY_BREAK
+case 95:
+YY_RULE_SETUP
+{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
+	YY_BREAK
+case 96:
+YY_RULE_SETUP
+{  return(ADD_ASSIGN); }
+	YY_BREAK
+case 97:
+YY_RULE_SETUP
+{  return(SUB_ASSIGN); }
+	YY_BREAK
+case 98:
+YY_RULE_SETUP
+{  return(MUL_ASSIGN); }
+	YY_BREAK
+case 99:
+YY_RULE_SETUP
+{  return(DIV_ASSIGN); }
+	YY_BREAK
+case 100:
+YY_RULE_SETUP
+{  return(MOD_ASSIGN); }
+	YY_BREAK
+case 101:
+YY_RULE_SETUP
+{  return(LEFT_ASSIGN); }
+	YY_BREAK
+case 102:
+YY_RULE_SETUP
+{  return(RIGHT_ASSIGN); }
+	YY_BREAK
+case 103:
+YY_RULE_SETUP
+{  return(AND_ASSIGN); }
+	YY_BREAK
+case 104:
+YY_RULE_SETUP
+{  return(XOR_ASSIGN); }
+	YY_BREAK
+case 105:
+YY_RULE_SETUP
+{  return(OR_ASSIGN); }
+	YY_BREAK
+case 106:
+YY_RULE_SETUP
+{  return(INC_OP); }
+	YY_BREAK
+case 107:
+YY_RULE_SETUP
+{  return(DEC_OP); }
+	YY_BREAK
+case 108:
+YY_RULE_SETUP
+{  return(AND_OP); }
+	YY_BREAK
+case 109:
+YY_RULE_SETUP
+{  return(OR_OP); }
+	YY_BREAK
+case 110:
+YY_RULE_SETUP
+{  return(XOR_OP); }
+	YY_BREAK
+case 111:
+YY_RULE_SETUP
+{  return(LE_OP); }
+	YY_BREAK
+case 112:
+YY_RULE_SETUP
+{  return(GE_OP); }
+	YY_BREAK
+case 113:
+YY_RULE_SETUP
+{  return(EQ_OP); }
+	YY_BREAK
+case 114:
+YY_RULE_SETUP
+{  return(NE_OP); }
+	YY_BREAK
+case 115:
+YY_RULE_SETUP
+{  return(LEFT_OP); }
+	YY_BREAK
+case 116:
+YY_RULE_SETUP
+{  return(RIGHT_OP); }
+	YY_BREAK
+case 117:
+YY_RULE_SETUP
+{ context->lexAfterType = false; return(SEMICOLON); }
+	YY_BREAK
+case 118:
+YY_RULE_SETUP
+{ context->lexAfterType = false; return(LEFT_BRACE); }
+	YY_BREAK
+case 119:
+YY_RULE_SETUP
+{ return(RIGHT_BRACE); }
+	YY_BREAK
+case 120:
+YY_RULE_SETUP
+{ if (context->inTypeParen) context->lexAfterType = false; return(COMMA); }
+	YY_BREAK
+case 121:
+YY_RULE_SETUP
+{ return(COLON); }
+	YY_BREAK
+case 122:
+YY_RULE_SETUP
+{ context->lexAfterType = false; return(EQUAL); }
+	YY_BREAK
+case 123:
+YY_RULE_SETUP
+{ context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); }
+	YY_BREAK
+case 124:
+YY_RULE_SETUP
+{ context->inTypeParen = false; return(RIGHT_PAREN); }
+	YY_BREAK
+case 125:
+YY_RULE_SETUP
+{ return(LEFT_BRACKET); }
+	YY_BREAK
+case 126:
+YY_RULE_SETUP
+{ return(RIGHT_BRACKET); }
+	YY_BREAK
+case 127:
+YY_RULE_SETUP
+{ BEGIN(FIELDS);  return(DOT); }
+	YY_BREAK
+case 128:
+YY_RULE_SETUP
+{ return(BANG); }
+	YY_BREAK
+case 129:
+YY_RULE_SETUP
+{ return(DASH); }
+	YY_BREAK
+case 130:
+YY_RULE_SETUP
+{ return(TILDE); }
+	YY_BREAK
+case 131:
+YY_RULE_SETUP
+{ return(PLUS); }
+	YY_BREAK
+case 132:
+YY_RULE_SETUP
+{ return(STAR); }
+	YY_BREAK
+case 133:
+YY_RULE_SETUP
+{ return(SLASH); }
+	YY_BREAK
+case 134:
+YY_RULE_SETUP
+{ return(PERCENT); }
+	YY_BREAK
+case 135:
+YY_RULE_SETUP
+{ return(LEFT_ANGLE); }
+	YY_BREAK
+case 136:
+YY_RULE_SETUP
+{ return(RIGHT_ANGLE); }
+	YY_BREAK
+case 137:
+YY_RULE_SETUP
+{ return(VERTICAL_BAR); }
+	YY_BREAK
+case 138:
+YY_RULE_SETUP
+{ return(CARET); }
+	YY_BREAK
+case 139:
+YY_RULE_SETUP
+{ return(AMPERSAND); }
+	YY_BREAK
+case 140:
+YY_RULE_SETUP
+{ return(QUESTION); }
+	YY_BREAK
+case 141:
+YY_RULE_SETUP
+{ 
+    BEGIN(INITIAL);
+    yylval->lex.string = NewPoolTString(yytext); 
+    return FIELD_SELECTION;
+}
+	YY_BREAK
+case 142:
+YY_RULE_SETUP
+{}
+	YY_BREAK
+case 143:
+/* rule 143 can match eol */
+YY_RULE_SETUP
+{  }
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(COMMENT):
+case YY_STATE_EOF(FIELDS):
+{ context->AfterEOF = true; yyterminate(); }
+	YY_BREAK
+case 144:
+YY_RULE_SETUP
+{ context->warning(yylineno, "Unknown char", yytext, ""); return 0; }
+	YY_BREAK
+case 145:
+YY_RULE_SETUP
+ECHO;
+	YY_BREAK
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = yyg->yy_hold_char;
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state( yyscanner );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++yyg->yy_c_buf_p;
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = yyg->yy_last_accepting_cpos;
+				yy_current_state = yyg->yy_last_accepting_state;
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer( yyscanner ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				yyg->yy_did_buffer_switch_on_eof = 0;
+
+				if ( yywrap(yyscanner ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				yyg->yy_c_buf_p =
+					yyg->yytext_ptr + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				yyg->yy_c_buf_p =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = yyg->yytext_ptr;
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			yyg->yy_n_chars, (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	if ( yyg->yy_n_chars == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart(yyin  ,yyscanner);
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	yyg->yy_n_chars += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	yy_current_state = yyg->yy_start;
+
+	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			yyg->yy_last_accepting_state = yy_current_state;
+			yyg->yy_last_accepting_cpos = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 411 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+	register int yy_is_jam;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+	register char *yy_cp = yyg->yy_c_buf_p;
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		yyg->yy_last_accepting_state = yy_current_state;
+		yyg->yy_last_accepting_cpos = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 411 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 410);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (yyscan_t yyscanner)
+#else
+    static int input  (yyscan_t yyscanner)
+#endif
+
+{
+	int c;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	*yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			/* This was really a NUL. */
+			*yyg->yy_c_buf_p = '\0';
+
+		else
+			{ /* need more input */
+			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+			++yyg->yy_c_buf_p;
+
+			switch ( yy_get_next_buffer( yyscanner ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart(yyin ,yyscanner);
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap(yyscanner ) )
+						return EOF;
+
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput(yyscanner);
+#else
+					return input(yyscanner);
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
+	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
+	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+	if ( c == '\n' )
+		   
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack (yyscanner);
+		YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+	}
+
+	yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+	yy_load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
+     */
+	yyensure_buffer_stack (yyscanner);
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	yy_load_buffer_state(yyscanner );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void yy_load_buffer_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ,yyscanner );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer(b,file ,yyscanner);
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+	yyfree((void *) b ,yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
+
+{
+	int oerrno = errno;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	yy_flush_buffer(b ,yyscanner);
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		yy_load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  @param yyscanner The scanner object.
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (new_buffer == NULL)
+		return;
+
+	yyensure_buffer_stack(yyscanner);
+
+	/* This block is copied from yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		yyg->yy_buffer_stack_top++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state(yyscanner );
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  @param yyscanner The scanner object.
+ */
+void yypop_buffer_state (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (!YY_CURRENT_BUFFER)
+		return;
+
+	yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if (yyg->yy_buffer_stack_top > 0)
+		--yyg->yy_buffer_stack_top;
+
+	if (YY_CURRENT_BUFFER) {
+		yy_load_buffer_state(yyscanner );
+		yyg->yy_did_buffer_switch_on_eof = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (yyscan_t yyscanner)
+{
+	int num_to_alloc;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if (!yyg->yy_buffer_stack) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+								  
+		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		yyg->yy_buffer_stack_max = num_to_alloc;
+		yyg->yy_buffer_stack_top = 0;
+		return;
+	}
+
+	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
+								(yyg->yy_buffer_stack,
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+		yyg->yy_buffer_stack_max = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer(b ,yyscanner );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+    
+	return yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) yyalloc(n ,yyscanner );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer(buf,n ,yyscanner);
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+    static void yy_push_state (int  new_state , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( yyg->yy_start_stack_ptr >= yyg->yy_start_stack_depth )
+		{
+		yy_size_t new_size;
+
+		yyg->yy_start_stack_depth += YY_START_STACK_INCR;
+		new_size = yyg->yy_start_stack_depth * sizeof( int );
+
+		if ( ! yyg->yy_start_stack )
+			yyg->yy_start_stack = (int *) yyalloc(new_size ,yyscanner );
+
+		else
+			yyg->yy_start_stack = (int *) yyrealloc((void *) yyg->yy_start_stack,new_size ,yyscanner );
+
+		if ( ! yyg->yy_start_stack )
+			YY_FATAL_ERROR( "out of memory expanding start-condition stack" );
+		}
+
+	yyg->yy_start_stack[yyg->yy_start_stack_ptr++] = YY_START;
+
+	BEGIN(new_state);
+}
+
+    static void yy_pop_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( --yyg->yy_start_stack_ptr < 0 )
+		YY_FATAL_ERROR( "start-condition stack underflow" );
+
+	BEGIN(yyg->yy_start_stack[yyg->yy_start_stack_ptr]);
+}
+
+    static int yy_top_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	return yyg->yy_start_stack[yyg->yy_start_stack_ptr - 1];
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = yyg->yy_hold_char; \
+		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+		*yyg->yy_c_buf_p = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE yyget_extra  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_lineno  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_column  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_in  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_out  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int yyget_leng  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *yyget_text  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void yyset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_lineno (int  line_number , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* lineno is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "yyset_lineno called with no buffer" , yyscanner); 
+    
+    yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_column (int  column_no , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* column is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "yyset_column called with no buffer" , yyscanner); 
+    
+    yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  in_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyin = in_str ;
+}
+
+void yyset_out (FILE *  out_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyout = out_str ;
+}
+
+int yyget_debug  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yy_flex_debug;
+}
+
+void yyset_debug (int  bdebug , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * yyget_lval  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yylval;
+}
+
+void yyset_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yylval = yylval_param;
+}
+
+/* User-visible API */
+
+/* yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int yylex_init(yyscan_t* ptr_yy_globals)
+
+{
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+
+    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+
+    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to yyalloc in
+ * the yyextra field.
+ */
+
+int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+    struct yyguts_t dummy_yyguts;
+
+    yyset_extra (yy_user_defined, &dummy_yyguts);
+
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+	
+    *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+	
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+    
+    /* By setting to 0xAA, we expose bugs in
+    yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+    
+    yyset_extra (yy_user_defined, *ptr_yy_globals);
+    
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    yyg->yy_buffer_stack = 0;
+    yyg->yy_buffer_stack_top = 0;
+    yyg->yy_buffer_stack_max = 0;
+    yyg->yy_c_buf_p = (char *) 0;
+    yyg->yy_init = 0;
+    yyg->yy_start = 0;
+
+    yyg->yy_start_stack_ptr = 0;
+    yyg->yy_start_stack_depth = 0;
+    yyg->yy_start_stack =  NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		yypop_buffer_state(yyscanner);
+	}
+
+	/* Destroy the stack itself. */
+	yyfree(yyg->yy_buffer_stack ,yyscanner);
+	yyg->yy_buffer_stack = NULL;
+
+    /* Destroy the start condition stack. */
+        yyfree(yyg->yy_start_stack ,yyscanner );
+        yyg->yy_start_stack = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( yyscanner);
+
+    /* Destroy the main struct (reentrant only). */
+    yyfree ( yyscanner , yyscanner );
+    yyscanner = NULL;
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size , yyscan_t yyscanner)
+{
+	return (void *) malloc( size );
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr , yyscan_t yyscanner)
+{
+	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+extern "C" {
+// Preprocessor interface.
+#include "compiler/preprocessor/preprocess.h"
+
+#define SETUP_CONTEXT(pp) \
+    TParseContext* context = (TParseContext*) pp->pC; \
+    struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
+
+// Preprocessor callbacks.
+void CPPDebugLogMsg(const char *msg)
+{
+    SETUP_CONTEXT(cpp);
+    context->infoSink.debug.message(EPrefixNone, msg);
+}
+
+void CPPWarningToInfoLog(const char *msg)
+{
+    SETUP_CONTEXT(cpp);
+    context->warning(yylineno, msg, "", "");
+}
+
+void CPPShInfoLogMsg(const char *msg)
+{
+    SETUP_CONTEXT(cpp);
+    context->error(yylineno, msg, "", "");
+    context->recover();
+}
+
+void CPPErrorToInfoLog(char *msg)
+{
+    SETUP_CONTEXT(cpp);
+    context->error(yylineno, msg, "", "");
+    context->recover();
+}
+
+void SetLineNumber(int line)
+{
+    SETUP_CONTEXT(cpp);
+    int string = 0;
+    DecodeSourceLoc(yylineno, &string, NULL);
+    yylineno = EncodeSourceLoc(string, line);
+}
+
+void SetStringNumber(int string)
+{
+    SETUP_CONTEXT(cpp);
+    int line = 0;
+    DecodeSourceLoc(yylineno, NULL, &line);
+    yylineno = EncodeSourceLoc(string, line);
+}
+
+int GetStringNumber()
+{
+    SETUP_CONTEXT(cpp);
+    int string = 0;
+    DecodeSourceLoc(yylineno, &string, NULL);
+    return string;
+}
+
+int GetLineNumber()
+{
+    SETUP_CONTEXT(cpp);
+    int line = 0;
+    DecodeSourceLoc(yylineno, NULL, &line);
+    return line;
+}
+
+void IncLineNumber()
+{
+    SETUP_CONTEXT(cpp);
+    int string = 0, line = 0;
+    DecodeSourceLoc(yylineno, &string, &line);
+    yylineno = EncodeSourceLoc(string, ++line);
+}
+
+void DecLineNumber()
+{
+    SETUP_CONTEXT(cpp);
+    int string = 0, line = 0;
+    DecodeSourceLoc(yylineno, &string, &line);
+    yylineno = EncodeSourceLoc(string, --line);
+}
+
+void HandlePragma(const char **tokens, int numTokens)
+{
+    SETUP_CONTEXT(cpp);
+    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"))
+            context->contextPragma.optimize = true;
+        else if (!strcmp(tokens[2], "off"))
+            context->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"))
+            context->contextPragma.debug = true;
+        else if (!strcmp(tokens[2], "off"))
+            context->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)
+{
+    SETUP_CONTEXT(cpp);
+    TString strSrc;
+    strSrc = TString(string);
+
+    context->HashErrMsg = context->HashErrMsg + " " + strSrc;
+}
+
+const char* GetStrfromTStr(void)
+{
+    SETUP_CONTEXT(cpp);
+    cpp->ErrMsg = context->HashErrMsg.c_str();
+    return cpp->ErrMsg;
+}
+
+void ResetTString(void)
+{
+    SETUP_CONTEXT(cpp);
+    context->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)
+{
+    SETUP_CONTEXT(cpp);
+    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 = context->extensionBehavior.begin(); iter != context->extensionBehavior.end(); ++iter)
+                iter->second = behaviorVal;
+        }        
+    } else {
+        iter = context->extensionBehavior.find(TString(extName));
+        if (iter == context->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";
+                context->infoSink.info.message(EPrefixWarning, msg.c_str(), yylineno); 
+                break;
+            }
+            return;
+        } else
+            iter->second = behaviorVal;
+    }
+}
+}  // extern "C"
+
+int string_input(char* buf, int max_size, yyscan_t yyscanner) {
+    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;
+}
+
+int check_type(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+    
+    int token = IDENTIFIER;
+    TSymbol* symbol = yyextra->symbolTable.find(yytext);
+    if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) {
+        TVariable* variable = static_cast<TVariable*>(symbol);
+        if (variable->isUserType()) {
+            yyextra->lexAfterType = true;
+            token = TYPE_NAME;
+        }
+    }
+    yylval->lex.symbol = symbol;
+    return token;
+}
+
+int reserved_word(yyscan_t yyscanner) {
+    struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+    yyextra->error(yylineno, "Illegal use of reserved word", yytext, "");
+    yyextra->recover();
+    return 0;
+}
+
+void yyerror(TParseContext* context, const char* reason) {
+    struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
+
+    if (context->AfterEOF) {
+        context->error(yylineno, reason, "unexpected EOF", "");
+    } else {
+        context->error(yylineno, reason, yytext, "");
+    }
+    context->recover();
+}
+
+int glslang_initialize(TParseContext* context) {
+    yyscan_t scanner = NULL;
+    if (yylex_init_extra(context,&scanner))
+        return 1;
+
+    context->scanner = scanner;
+    return 0;
+}
+
+int glslang_finalize(TParseContext* context) {
+    yyscan_t scanner = context->scanner;
+    if (scanner == NULL) return 0;
+    
+    context->scanner = NULL;
+    return yylex_destroy(scanner);
+}
+
+void glslang_scan(int count, const char* const string[], const int length[],
+                  TParseContext* context) {
+    yyrestart(NULL,context->scanner);
+    yyset_lineno(EncodeSourceLoc(0, 1),context->scanner);
+    context->AfterEOF = false;
+    
+    // Init preprocessor.
+    cpp->pC = context;
+    cpp->PaWhichStr = 0;
+    cpp->PaArgv     = string;
+    cpp->PaArgc     = count;
+    cpp->PaStrLen   = length;
+    cpp->pastFirstStatement = 0;
+    ScanFromString(string[0]);
+}
+
diff --git a/src/OpenGL ES 2.0/compiler/glslang_tab.cpp b/src/OpenGL ES 2.0/compiler/glslang_tab.cpp
new file mode 100644
index 0000000..83ac524
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/glslang_tab.cpp
@@ -0,0 +1,4716 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   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., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     INVARIANT = 258,
+     HIGH_PRECISION = 259,
+     MEDIUM_PRECISION = 260,
+     LOW_PRECISION = 261,
+     PRECISION = 262,
+     ATTRIBUTE = 263,
+     CONST_QUAL = 264,
+     BOOL_TYPE = 265,
+     FLOAT_TYPE = 266,
+     INT_TYPE = 267,
+     BREAK = 268,
+     CONTINUE = 269,
+     DO = 270,
+     ELSE = 271,
+     FOR = 272,
+     IF = 273,
+     DISCARD = 274,
+     RETURN = 275,
+     BVEC2 = 276,
+     BVEC3 = 277,
+     BVEC4 = 278,
+     IVEC2 = 279,
+     IVEC3 = 280,
+     IVEC4 = 281,
+     VEC2 = 282,
+     VEC3 = 283,
+     VEC4 = 284,
+     MATRIX2 = 285,
+     MATRIX3 = 286,
+     MATRIX4 = 287,
+     IN_QUAL = 288,
+     OUT_QUAL = 289,
+     INOUT_QUAL = 290,
+     UNIFORM = 291,
+     VARYING = 292,
+     STRUCT = 293,
+     VOID_TYPE = 294,
+     WHILE = 295,
+     SAMPLER2D = 296,
+     SAMPLERCUBE = 297,
+     IDENTIFIER = 298,
+     TYPE_NAME = 299,
+     FLOATCONSTANT = 300,
+     INTCONSTANT = 301,
+     BOOLCONSTANT = 302,
+     FIELD_SELECTION = 303,
+     LEFT_OP = 304,
+     RIGHT_OP = 305,
+     INC_OP = 306,
+     DEC_OP = 307,
+     LE_OP = 308,
+     GE_OP = 309,
+     EQ_OP = 310,
+     NE_OP = 311,
+     AND_OP = 312,
+     OR_OP = 313,
+     XOR_OP = 314,
+     MUL_ASSIGN = 315,
+     DIV_ASSIGN = 316,
+     ADD_ASSIGN = 317,
+     MOD_ASSIGN = 318,
+     LEFT_ASSIGN = 319,
+     RIGHT_ASSIGN = 320,
+     AND_ASSIGN = 321,
+     XOR_ASSIGN = 322,
+     OR_ASSIGN = 323,
+     SUB_ASSIGN = 324,
+     LEFT_PAREN = 325,
+     RIGHT_PAREN = 326,
+     LEFT_BRACKET = 327,
+     RIGHT_BRACKET = 328,
+     LEFT_BRACE = 329,
+     RIGHT_BRACE = 330,
+     DOT = 331,
+     COMMA = 332,
+     COLON = 333,
+     EQUAL = 334,
+     SEMICOLON = 335,
+     BANG = 336,
+     DASH = 337,
+     TILDE = 338,
+     PLUS = 339,
+     STAR = 340,
+     SLASH = 341,
+     PERCENT = 342,
+     LEFT_ANGLE = 343,
+     RIGHT_ANGLE = 344,
+     VERTICAL_BAR = 345,
+     CARET = 346,
+     AMPERSAND = 347,
+     QUESTION = 348
+   };
+#endif
+/* Tokens.  */
+#define INVARIANT 258
+#define HIGH_PRECISION 259
+#define MEDIUM_PRECISION 260
+#define LOW_PRECISION 261
+#define PRECISION 262
+#define ATTRIBUTE 263
+#define CONST_QUAL 264
+#define BOOL_TYPE 265
+#define FLOAT_TYPE 266
+#define INT_TYPE 267
+#define BREAK 268
+#define CONTINUE 269
+#define DO 270
+#define ELSE 271
+#define FOR 272
+#define IF 273
+#define DISCARD 274
+#define RETURN 275
+#define BVEC2 276
+#define BVEC3 277
+#define BVEC4 278
+#define IVEC2 279
+#define IVEC3 280
+#define IVEC4 281
+#define VEC2 282
+#define VEC3 283
+#define VEC4 284
+#define MATRIX2 285
+#define MATRIX3 286
+#define MATRIX4 287
+#define IN_QUAL 288
+#define OUT_QUAL 289
+#define INOUT_QUAL 290
+#define UNIFORM 291
+#define VARYING 292
+#define STRUCT 293
+#define VOID_TYPE 294
+#define WHILE 295
+#define SAMPLER2D 296
+#define SAMPLERCUBE 297
+#define IDENTIFIER 298
+#define TYPE_NAME 299
+#define FLOATCONSTANT 300
+#define INTCONSTANT 301
+#define BOOLCONSTANT 302
+#define FIELD_SELECTION 303
+#define LEFT_OP 304
+#define RIGHT_OP 305
+#define INC_OP 306
+#define DEC_OP 307
+#define LE_OP 308
+#define GE_OP 309
+#define EQ_OP 310
+#define NE_OP 311
+#define AND_OP 312
+#define OR_OP 313
+#define XOR_OP 314
+#define MUL_ASSIGN 315
+#define DIV_ASSIGN 316
+#define ADD_ASSIGN 317
+#define MOD_ASSIGN 318
+#define LEFT_ASSIGN 319
+#define RIGHT_ASSIGN 320
+#define AND_ASSIGN 321
+#define XOR_ASSIGN 322
+#define OR_ASSIGN 323
+#define SUB_ASSIGN 324
+#define LEFT_PAREN 325
+#define RIGHT_PAREN 326
+#define LEFT_BRACKET 327
+#define RIGHT_BRACKET 328
+#define LEFT_BRACE 329
+#define RIGHT_BRACE 330
+#define DOT 331
+#define COMMA 332
+#define COLON 333
+#define EQUAL 334
+#define SEMICOLON 335
+#define BANG 336
+#define DASH 337
+#define TILDE 338
+#define PLUS 339
+#define STAR 340
+#define SLASH 341
+#define PERCENT 342
+#define LEFT_ANGLE 343
+#define RIGHT_ANGLE 344
+#define VERTICAL_BAR 345
+#define CARET 346
+#define AMPERSAND 347
+#define QUESTION 348
+
+
+
+
+/* Copy the first part of user declarations.  */
+
+
+//
+// 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 file is auto-generated by generate_glslang_parser.sh. DO NOT EDIT!
+
+#include "compiler/SymbolTable.h"
+#include "compiler/ParseHelper.h"
+#include "GLSLANG/ShaderLang.h"
+
+#define YYLEX_PARAM context->scanner
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+
+{
+    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;
+}
+/* Line 193 of yacc.c.  */
+
+	YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations.  */
+
+
+extern int yylex(YYSTYPE* yylval_param, void* yyscanner);
+extern void yyerror(TParseContext* context, const char* reason);
+
+#define FRAG_VERT_ONLY(S, L) {  \
+    if (context->shaderType != SH_FRAGMENT_SHADER &&  \
+        context->shaderType != SH_VERTEX_SHADER) {  \
+        context->error(L, " supported in vertex/fragment shaders only ", S, "", "");  \
+        context->recover();  \
+    }  \
+}
+
+#define VERTEX_ONLY(S, L) {  \
+    if (context->shaderType != SH_VERTEX_SHADER) {  \
+        context->error(L, " supported in vertex shaders only ", S, "", "");  \
+        context->recover();  \
+    }  \
+}
+
+#define FRAG_ONLY(S, L) {  \
+    if (context->shaderType != SH_FRAGMENT_SHADER) {  \
+        context->error(L, " supported in fragment shaders only ", S, "", "");  \
+        context->recover();  \
+    }  \
+}
+
+
+/* Line 216 of yacc.c.  */
+
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+    int i;
+#endif
+{
+  return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+	     && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss;
+  YYSTYPE yyvs;
+  };
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  YYSIZE_T yyi;				\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (YYID (0))
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  69
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   1334
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  94
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  78
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  193
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  296
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   348
+
+#define YYTRANSLATE(YYX)						\
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+      85,    86,    87,    88,    89,    90,    91,    92,    93
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint16 yyprhs[] =
+{
+       0,     0,     3,     5,     7,     9,    11,    13,    17,    19,
+      24,    26,    30,    33,    36,    38,    40,    42,    46,    49,
+      52,    55,    57,    60,    64,    67,    69,    71,    73,    75,
+      78,    81,    84,    86,    88,    90,    92,    96,   100,   102,
+     106,   110,   112,   114,   118,   122,   126,   130,   132,   136,
+     140,   142,   144,   146,   148,   152,   154,   158,   160,   164,
+     166,   172,   174,   178,   180,   182,   184,   186,   188,   190,
+     194,   196,   199,   202,   207,   210,   212,   214,   217,   221,
+     225,   228,   234,   238,   241,   245,   248,   249,   251,   253,
+     255,   257,   259,   263,   269,   276,   282,   284,   287,   292,
+     298,   303,   306,   308,   311,   313,   315,   317,   320,   322,
+     324,   327,   329,   331,   333,   335,   340,   342,   344,   346,
+     348,   350,   352,   354,   356,   358,   360,   362,   364,   366,
+     368,   370,   372,   374,   376,   378,   380,   386,   391,   393,
+     396,   400,   402,   406,   408,   413,   415,   417,   419,   421,
+     423,   425,   427,   429,   431,   434,   435,   436,   442,   444,
+     446,   449,   453,   455,   458,   460,   463,   469,   473,   475,
+     477,   482,   483,   490,   491,   500,   501,   509,   511,   513,
+     515,   516,   519,   523,   526,   529,   532,   536,   539,   541,
+     544,   546,   548,   549
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int16 yyrhs[] =
+{
+     168,     0,    -1,    43,    -1,    95,    -1,    46,    -1,    45,
+      -1,    47,    -1,    70,   122,    71,    -1,    96,    -1,    97,
+      72,    98,    73,    -1,    99,    -1,    97,    76,    48,    -1,
+      97,    51,    -1,    97,    52,    -1,   122,    -1,   100,    -1,
+     101,    -1,    97,    76,   101,    -1,   103,    71,    -1,   102,
+      71,    -1,   104,    39,    -1,   104,    -1,   104,   120,    -1,
+     103,    77,   120,    -1,   105,    70,    -1,   137,    -1,    43,
+      -1,    48,    -1,    97,    -1,    51,   106,    -1,    52,   106,
+      -1,   107,   106,    -1,    84,    -1,    82,    -1,    81,    -1,
+     106,    -1,   108,    85,   106,    -1,   108,    86,   106,    -1,
+     108,    -1,   109,    84,   108,    -1,   109,    82,   108,    -1,
+     109,    -1,   110,    -1,   111,    88,   110,    -1,   111,    89,
+     110,    -1,   111,    53,   110,    -1,   111,    54,   110,    -1,
+     111,    -1,   112,    55,   111,    -1,   112,    56,   111,    -1,
+     112,    -1,   113,    -1,   114,    -1,   115,    -1,   116,    57,
+     115,    -1,   116,    -1,   117,    59,   116,    -1,   117,    -1,
+     118,    58,   117,    -1,   118,    -1,   118,    93,   122,    78,
+     120,    -1,   119,    -1,   106,   121,   120,    -1,    79,    -1,
+      60,    -1,    61,    -1,    62,    -1,    69,    -1,   120,    -1,
+     122,    77,   120,    -1,   119,    -1,   125,    80,    -1,   133,
+      80,    -1,     7,   138,   139,    80,    -1,   126,    71,    -1,
+     128,    -1,   127,    -1,   128,   130,    -1,   127,    77,   130,
+      -1,   135,    43,    70,    -1,   137,    43,    -1,   137,    43,
+      72,   123,    73,    -1,   136,   131,   129,    -1,   131,   129,
+      -1,   136,   131,   132,    -1,   131,   132,    -1,    -1,    33,
+      -1,    34,    -1,    35,    -1,   137,    -1,   134,    -1,   133,
+      77,    43,    -1,   133,    77,    43,    72,    73,    -1,   133,
+      77,    43,    72,   123,    73,    -1,   133,    77,    43,    79,
+     146,    -1,   135,    -1,   135,    43,    -1,   135,    43,    72,
+      73,    -1,   135,    43,    72,   123,    73,    -1,   135,    43,
+      79,   146,    -1,     3,    43,    -1,   137,    -1,   136,   137,
+      -1,     9,    -1,     8,    -1,    37,    -1,     3,    37,    -1,
+      36,    -1,   139,    -1,   138,   139,    -1,     4,    -1,     5,
+      -1,     6,    -1,   140,    -1,   140,    72,   123,    73,    -1,
+      39,    -1,    11,    -1,    12,    -1,    10,    -1,    27,    -1,
+      28,    -1,    29,    -1,    21,    -1,    22,    -1,    23,    -1,
+      24,    -1,    25,    -1,    26,    -1,    30,    -1,    31,    -1,
+      32,    -1,    41,    -1,    42,    -1,   141,    -1,    44,    -1,
+      38,    43,    74,   142,    75,    -1,    38,    74,   142,    75,
+      -1,   143,    -1,   142,   143,    -1,   137,   144,    80,    -1,
+     145,    -1,   144,    77,   145,    -1,    43,    -1,    43,    72,
+     123,    73,    -1,   120,    -1,   124,    -1,   150,    -1,   149,
+      -1,   147,    -1,   156,    -1,   157,    -1,   160,    -1,   167,
+      -1,    74,    75,    -1,    -1,    -1,    74,   151,   155,   152,
+      75,    -1,   154,    -1,   149,    -1,    74,    75,    -1,    74,
+     155,    75,    -1,   148,    -1,   155,   148,    -1,    80,    -1,
+     122,    80,    -1,    18,    70,   122,    71,   158,    -1,   148,
+      16,   148,    -1,   148,    -1,   122,    -1,   135,    43,    79,
+     146,    -1,    -1,    40,    70,   161,   159,    71,   153,    -1,
+      -1,    15,   162,   148,    40,    70,   122,    71,    80,    -1,
+      -1,    17,    70,   163,   164,   166,    71,   153,    -1,   156,
+      -1,   147,    -1,   159,    -1,    -1,   165,    80,    -1,   165,
+      80,   122,    -1,    14,    80,    -1,    13,    80,    -1,    20,
+      80,    -1,    20,   122,    80,    -1,    19,    80,    -1,   169,
+      -1,   168,   169,    -1,   170,    -1,   124,    -1,    -1,   125,
+     171,   154,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,   153,   153,   188,   191,   204,   209,   214,   220,   223,
+     296,   299,   408,   418,   431,   439,   538,   541,   549,   553,
+     560,   564,   571,   577,   586,   594,   656,   663,   673,   676,
+     686,   696,   717,   718,   719,   724,   725,   734,   746,   747,
+     755,   766,   770,   771,   781,   791,   801,   814,   815,   825,
+     838,   842,   846,   850,   851,   864,   865,   878,   879,   892,
+     893,   910,   911,   924,   925,   926,   927,   928,   932,   935,
+     946,   954,   979,   984,   991,  1027,  1030,  1037,  1045,  1066,
+    1085,  1096,  1125,  1130,  1140,  1145,  1155,  1158,  1161,  1164,
+    1170,  1177,  1187,  1203,  1221,  1245,  1268,  1272,  1290,  1298,
+    1330,  1350,  1426,  1435,  1458,  1461,  1467,  1475,  1483,  1491,
+    1494,  1501,  1504,  1507,  1513,  1516,  1531,  1535,  1539,  1543,
+    1552,  1557,  1562,  1567,  1572,  1577,  1582,  1587,  1592,  1597,
+    1603,  1609,  1615,  1620,  1625,  1630,  1643,  1656,  1664,  1667,
+    1682,  1713,  1717,  1723,  1731,  1747,  1751,  1755,  1756,  1762,
+    1763,  1764,  1765,  1766,  1770,  1771,  1771,  1771,  1781,  1782,
+    1787,  1790,  1800,  1803,  1809,  1810,  1814,  1822,  1826,  1836,
+    1841,  1858,  1858,  1863,  1863,  1870,  1870,  1878,  1881,  1887,
+    1890,  1896,  1900,  1907,  1914,  1921,  1928,  1939,  1948,  1952,
+    1959,  1962,  1968,  1968
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "INVARIANT", "HIGH_PRECISION",
+  "MEDIUM_PRECISION", "LOW_PRECISION", "PRECISION", "ATTRIBUTE",
+  "CONST_QUAL", "BOOL_TYPE", "FLOAT_TYPE", "INT_TYPE", "BREAK", "CONTINUE",
+  "DO", "ELSE", "FOR", "IF", "DISCARD", "RETURN", "BVEC2", "BVEC3",
+  "BVEC4", "IVEC2", "IVEC3", "IVEC4", "VEC2", "VEC3", "VEC4", "MATRIX2",
+  "MATRIX3", "MATRIX4", "IN_QUAL", "OUT_QUAL", "INOUT_QUAL", "UNIFORM",
+  "VARYING", "STRUCT", "VOID_TYPE", "WHILE", "SAMPLER2D", "SAMPLERCUBE",
+  "IDENTIFIER", "TYPE_NAME", "FLOATCONSTANT", "INTCONSTANT",
+  "BOOLCONSTANT", "FIELD_SELECTION", "LEFT_OP", "RIGHT_OP", "INC_OP",
+  "DEC_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP",
+  "XOR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN",
+  "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN",
+  "SUB_ASSIGN", "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACKET",
+  "RIGHT_BRACKET", "LEFT_BRACE", "RIGHT_BRACE", "DOT", "COMMA", "COLON",
+  "EQUAL", "SEMICOLON", "BANG", "DASH", "TILDE", "PLUS", "STAR", "SLASH",
+  "PERCENT", "LEFT_ANGLE", "RIGHT_ANGLE", "VERTICAL_BAR", "CARET",
+  "AMPERSAND", "QUESTION", "$accept", "variable_identifier",
+  "primary_expression", "postfix_expression", "integer_expression",
+  "function_call", "function_call_or_method", "function_call_generic",
+  "function_call_header_no_parameters",
+  "function_call_header_with_parameters", "function_call_header",
+  "function_identifier", "unary_expression", "unary_operator",
+  "multiplicative_expression", "additive_expression", "shift_expression",
+  "relational_expression", "equality_expression", "and_expression",
+  "exclusive_or_expression", "inclusive_or_expression",
+  "logical_and_expression", "logical_xor_expression",
+  "logical_or_expression", "conditional_expression",
+  "assignment_expression", "assignment_operator", "expression",
+  "constant_expression", "declaration", "function_prototype",
+  "function_declarator", "function_header_with_parameters",
+  "function_header", "parameter_declarator", "parameter_declaration",
+  "parameter_qualifier", "parameter_type_specifier",
+  "init_declarator_list", "single_declaration", "fully_specified_type",
+  "type_qualifier", "type_specifier", "precision_qualifier",
+  "type_specifier_no_prec", "type_specifier_nonarray", "struct_specifier",
+  "struct_declaration_list", "struct_declaration",
+  "struct_declarator_list", "struct_declarator", "initializer",
+  "declaration_statement", "statement", "simple_statement",
+  "compound_statement", "@1", "@2", "statement_no_new_scope",
+  "compound_statement_no_new_scope", "statement_list",
+  "expression_statement", "selection_statement",
+  "selection_rest_statement", "condition", "iteration_statement", "@3",
+  "@4", "@5", "for_init_statement", "conditionopt", "for_rest_statement",
+  "jump_statement", "translation_unit", "external_declaration",
+  "function_definition", "@6", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
+     305,   306,   307,   308,   309,   310,   311,   312,   313,   314,
+     315,   316,   317,   318,   319,   320,   321,   322,   323,   324,
+     325,   326,   327,   328,   329,   330,   331,   332,   333,   334,
+     335,   336,   337,   338,   339,   340,   341,   342,   343,   344,
+     345,   346,   347,   348
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    94,    95,    96,    96,    96,    96,    96,    97,    97,
+      97,    97,    97,    97,    98,    99,   100,   100,   101,   101,
+     102,   102,   103,   103,   104,   105,   105,   105,   106,   106,
+     106,   106,   107,   107,   107,   108,   108,   108,   109,   109,
+     109,   110,   111,   111,   111,   111,   111,   112,   112,   112,
+     113,   114,   115,   116,   116,   117,   117,   118,   118,   119,
+     119,   120,   120,   121,   121,   121,   121,   121,   122,   122,
+     123,   124,   124,   124,   125,   126,   126,   127,   127,   128,
+     129,   129,   130,   130,   130,   130,   131,   131,   131,   131,
+     132,   133,   133,   133,   133,   133,   134,   134,   134,   134,
+     134,   134,   135,   135,   136,   136,   136,   136,   136,   137,
+     137,   138,   138,   138,   139,   139,   140,   140,   140,   140,
+     140,   140,   140,   140,   140,   140,   140,   140,   140,   140,
+     140,   140,   140,   140,   140,   140,   141,   141,   142,   142,
+     143,   144,   144,   145,   145,   146,   147,   148,   148,   149,
+     149,   149,   149,   149,   150,   151,   152,   150,   153,   153,
+     154,   154,   155,   155,   156,   156,   157,   158,   158,   159,
+     159,   161,   160,   162,   160,   163,   160,   164,   164,   165,
+     165,   166,   166,   167,   167,   167,   167,   167,   168,   168,
+     169,   169,   171,   170
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     1,     1,     1,     1,     1,     3,     1,     4,
+       1,     3,     2,     2,     1,     1,     1,     3,     2,     2,
+       2,     1,     2,     3,     2,     1,     1,     1,     1,     2,
+       2,     2,     1,     1,     1,     1,     3,     3,     1,     3,
+       3,     1,     1,     3,     3,     3,     3,     1,     3,     3,
+       1,     1,     1,     1,     3,     1,     3,     1,     3,     1,
+       5,     1,     3,     1,     1,     1,     1,     1,     1,     3,
+       1,     2,     2,     4,     2,     1,     1,     2,     3,     3,
+       2,     5,     3,     2,     3,     2,     0,     1,     1,     1,
+       1,     1,     3,     5,     6,     5,     1,     2,     4,     5,
+       4,     2,     1,     2,     1,     1,     1,     2,     1,     1,
+       2,     1,     1,     1,     1,     4,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     5,     4,     1,     2,
+       3,     1,     3,     1,     4,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     2,     0,     0,     5,     1,     1,
+       2,     3,     1,     2,     1,     2,     5,     3,     1,     1,
+       4,     0,     6,     0,     8,     0,     7,     1,     1,     1,
+       0,     2,     3,     2,     2,     2,     3,     2,     1,     2,
+       1,     1,     0,     3
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       0,     0,   111,   112,   113,     0,   105,   104,   119,   117,
+     118,   123,   124,   125,   126,   127,   128,   120,   121,   122,
+     129,   130,   131,   108,   106,     0,   116,   132,   133,   135,
+     191,   192,     0,    76,    86,     0,    91,    96,     0,   102,
+       0,   109,   114,   134,     0,   188,   190,   107,   101,     0,
+       0,     0,    71,     0,    74,    86,     0,    87,    88,    89,
+      77,     0,    86,     0,    72,    97,   103,   110,     0,     1,
+     189,     0,     0,     0,     0,   138,     0,   193,    78,    83,
+      85,    90,     0,    92,    79,     0,     0,     2,     5,     4,
+       6,    27,     0,     0,     0,    34,    33,    32,     3,     8,
+      28,    10,    15,    16,     0,     0,    21,     0,    35,     0,
+      38,    41,    42,    47,    50,    51,    52,    53,    55,    57,
+      59,    70,     0,    25,    73,     0,   143,     0,   141,   137,
+     139,     0,     0,   173,     0,     0,     0,     0,     0,   155,
+     160,   164,    35,    61,    68,     0,   146,     0,   102,   149,
+     162,   148,   147,     0,   150,   151,   152,   153,    80,    82,
+      84,     0,     0,    98,     0,   145,   100,    29,    30,     0,
+      12,    13,     0,     0,    19,    18,     0,   116,    22,    24,
+      31,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   115,   136,     0,     0,   140,
+     184,   183,     0,   175,     0,   187,   185,     0,   171,   154,
+       0,    64,    65,    66,    67,    63,     0,     0,   165,   161,
+     163,     0,    93,     0,    95,    99,     7,     0,    14,    26,
+      11,    17,    23,    36,    37,    40,    39,    45,    46,    43,
+      44,    48,    49,    54,    56,    58,     0,     0,   142,     0,
+       0,     0,   186,     0,   156,    62,    69,     0,    94,     9,
+       0,   144,     0,   178,   177,   180,     0,   169,     0,     0,
+       0,    81,    60,     0,   179,     0,     0,   168,   166,     0,
+       0,   157,     0,   181,     0,     0,     0,   159,   172,   158,
+       0,   182,   176,   167,   170,   174
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
+{
+      -1,    98,    99,   100,   227,   101,   102,   103,   104,   105,
+     106,   107,   142,   109,   110,   111,   112,   113,   114,   115,
+     116,   117,   118,   119,   120,   143,   144,   216,   145,   122,
+     146,   147,    32,    33,    34,    79,    60,    61,    80,    35,
+      36,    37,    38,   123,    40,    41,    42,    43,    74,    75,
+     127,   128,   166,   149,   150,   151,   152,   210,   270,   288,
+     289,   153,   154,   155,   278,   269,   156,   253,   202,   250,
+     265,   275,   276,   157,    44,    45,    46,    53
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -250
+static const yytype_int16 yypact[] =
+{
+    1225,    36,  -250,  -250,  -250,   150,  -250,  -250,  -250,  -250,
+    -250,  -250,  -250,  -250,  -250,  -250,  -250,  -250,  -250,  -250,
+    -250,  -250,  -250,  -250,  -250,   -33,  -250,  -250,  -250,  -250,
+    -250,   -60,   -22,   -17,    21,   -62,  -250,    22,  1266,  -250,
+    1290,  -250,    11,  -250,  1138,  -250,  -250,  -250,  -250,  1290,
+      14,  1266,  -250,    27,  -250,    34,    41,  -250,  -250,  -250,
+    -250,  1266,   129,    61,  -250,    17,  -250,  -250,   908,  -250,
+    -250,    31,  1266,    72,  1042,  -250,   283,  -250,  -250,  -250,
+    -250,    90,  1266,   -46,  -250,   194,   908,    65,  -250,  -250,
+    -250,  -250,   908,   908,   908,  -250,  -250,  -250,  -250,  -250,
+     -40,  -250,  -250,  -250,    80,   -25,   975,    87,  -250,   908,
+      35,    13,  -250,   -26,    68,  -250,  -250,  -250,   110,   109,
+     -54,  -250,    96,  -250,  -250,  1083,    98,    33,  -250,  -250,
+    -250,    91,    92,  -250,   104,   107,    99,   760,   108,   105,
+    -250,  -250,    24,  -250,  -250,    37,  -250,   -60,   112,  -250,
+    -250,  -250,  -250,   365,  -250,  -250,  -250,  -250,   111,  -250,
+    -250,   827,   908,  -250,   113,  -250,  -250,  -250,  -250,     4,
+    -250,  -250,   908,  1179,  -250,  -250,   908,   114,  -250,  -250,
+    -250,   908,   908,   908,   908,   908,   908,   908,   908,   908,
+     908,   908,   908,   908,   908,  -250,  -250,   908,    72,  -250,
+    -250,  -250,   447,  -250,   908,  -250,  -250,    42,  -250,  -250,
+     447,  -250,  -250,  -250,  -250,  -250,   908,   908,  -250,  -250,
+    -250,   908,  -250,   115,  -250,  -250,  -250,   116,   117,  -250,
+     120,  -250,  -250,  -250,  -250,    35,    35,  -250,  -250,  -250,
+    -250,   -26,   -26,  -250,   110,   109,    51,   119,  -250,   144,
+     611,    23,  -250,   693,   447,  -250,  -250,   122,  -250,  -250,
+     908,  -250,   123,  -250,  -250,   693,   447,   117,   153,   126,
+     128,  -250,  -250,   908,  -250,   127,   137,   171,  -250,   130,
+     529,  -250,    28,   908,   529,   447,   908,  -250,  -250,  -250,
+     131,   117,  -250,  -250,  -250,  -250
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int16 yypgoto[] =
+{
+    -250,  -250,  -250,  -250,  -250,  -250,  -250,    39,  -250,  -250,
+    -250,  -250,   -45,  -250,   -18,  -250,   -79,   -30,  -250,  -250,
+    -250,    38,    52,    20,  -250,   -63,   -85,  -250,   -92,   -71,
+       6,     9,  -250,  -250,  -250,   132,   172,   166,   148,  -250,
+    -250,  -246,   -21,     0,   226,   -24,  -250,  -250,   162,   -66,
+    -250,    45,  -159,    -3,  -136,  -249,  -250,  -250,  -250,   -36,
+     196,    46,     1,  -250,  -250,   -13,  -250,  -250,  -250,  -250,
+    -250,  -250,  -250,  -250,  -250,   211,  -250,  -250
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -76
+static const yytype_int16 yytable[] =
+{
+      39,   165,   169,   224,   193,   121,    30,   268,   130,    31,
+      50,   170,   171,    62,   164,    63,    67,   220,    64,   268,
+      52,   178,   121,   108,    56,    71,   161,   185,   186,     6,
+       7,   287,   172,   162,    62,   287,   173,    56,    66,   194,
+     108,    51,     6,     7,    39,   207,   175,   167,   168,    54,
+      30,    73,   176,    31,    57,    58,    59,    23,    24,   130,
+      55,    81,   187,   188,   180,    65,   249,    57,    58,    59,
+      23,    24,    73,    47,    73,   226,   148,   165,    47,    48,
+     228,   217,    81,    68,   211,   212,   213,    84,    72,    85,
+     223,   232,   -75,   214,   266,   183,    86,   184,   121,   290,
+     217,    76,   246,   215,    83,   217,   237,   238,   239,   240,
+     198,   124,   251,   199,   217,   126,   108,   218,   220,   217,
+     181,   182,   252,   189,   190,    73,   247,   294,   217,   260,
+     277,   255,   256,   158,   121,   -26,   233,   234,   108,   108,
+     108,   108,   108,   108,   108,   108,   108,   108,   108,   293,
+     257,   174,   108,   148,     2,     3,     4,   179,   121,   241,
+     242,   267,    57,    58,    59,   235,   236,   191,   192,   195,
+     197,   200,   201,   267,   203,   272,   108,   204,   208,   205,
+     209,   282,   -25,   221,   262,   -20,   225,   285,   258,   259,
+     -27,   291,   261,   273,   217,   271,   279,   280,     2,     3,
+       4,   165,   148,   281,     8,     9,    10,   283,   284,   286,
+     148,   295,   231,   245,   159,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    78,    82,   243,
+     160,    49,    25,    26,   125,    27,    28,    87,    29,    88,
+      89,    90,    91,   248,   244,    92,    93,   263,   292,    77,
+     148,   264,   274,   148,   148,    70,   254,     0,     0,     0,
+       0,     0,     0,     0,    94,   148,   148,   163,     0,     0,
+       0,     0,     0,     0,     0,    95,    96,     0,    97,     0,
+     148,     0,     0,     0,   148,   148,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,   131,   132,   133,     0,
+     134,   135,   136,   137,    11,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,     0,     0,     0,    23,
+      24,    25,    26,   138,    27,    28,    87,    29,    88,    89,
+      90,    91,     0,     0,    92,    93,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    94,     0,     0,     0,   139,   140,     0,
+       0,     0,     0,   141,    95,    96,     0,    97,     1,     2,
+       3,     4,     5,     6,     7,     8,     9,    10,   131,   132,
+     133,     0,   134,   135,   136,   137,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,     0,     0,
+       0,    23,    24,    25,    26,   138,    27,    28,    87,    29,
+      88,    89,    90,    91,     0,     0,    92,    93,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    94,     0,     0,     0,   139,
+     219,     0,     0,     0,     0,   141,    95,    96,     0,    97,
+       1,     2,     3,     4,     5,     6,     7,     8,     9,    10,
+     131,   132,   133,     0,   134,   135,   136,   137,    11,    12,
+      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+       0,     0,     0,    23,    24,    25,    26,   138,    27,    28,
+      87,    29,    88,    89,    90,    91,     0,     0,    92,    93,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    94,     0,     0,
+       0,   139,     0,     0,     0,     0,     0,   141,    95,    96,
+       0,    97,     1,     2,     3,     4,     5,     6,     7,     8,
+       9,    10,   131,   132,   133,     0,   134,   135,   136,   137,
+      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,     0,     0,     0,    23,    24,    25,    26,   138,
+      27,    28,    87,    29,    88,    89,    90,    91,     0,     0,
+      92,    93,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    94,
+       0,     0,     0,    76,     0,     0,     0,     0,     0,   141,
+      95,    96,     0,    97,     1,     2,     3,     4,     5,     6,
+       7,     8,     9,    10,     0,     0,     0,     0,     0,     0,
+       0,     0,    11,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,     0,     0,     0,    23,    24,    25,
+      26,     0,    27,    28,    87,    29,    88,    89,    90,    91,
+       0,     0,    92,    93,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,    94,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   141,    95,    96,     0,    97,    56,     2,     3,     4,
+       0,     6,     7,     8,     9,    10,     0,     0,     0,     0,
+       0,     0,     0,     0,    11,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,     0,     0,     0,    23,
+      24,    25,    26,     0,    27,    28,    87,    29,    88,    89,
+      90,    91,     0,     0,    92,    93,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    94,     2,     3,     4,     0,     0,     0,
+       8,     9,    10,     0,    95,    96,     0,    97,     0,     0,
+       0,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,     0,     0,     0,     0,     0,    25,    26,
+       0,    27,    28,    87,    29,    88,    89,    90,    91,     0,
+       0,    92,    93,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      94,     2,     3,     4,     0,     0,     0,     8,     9,    10,
+     206,    95,    96,     0,    97,     0,     0,     0,    11,    12,
+      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+       0,     0,     0,     0,     0,    25,    26,     0,    27,    28,
+      87,    29,    88,    89,    90,    91,     0,     0,    92,    93,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    94,     0,     0,
+     222,     0,     0,     0,     0,     0,     0,     0,    95,    96,
+       0,    97,     2,     3,     4,     0,     0,     0,     8,     9,
+      10,     0,     0,     0,     0,     0,     0,     0,     0,    11,
+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,     0,     0,     0,     0,     0,    25,    26,     0,    27,
+      28,    87,    29,    88,    89,    90,    91,     0,     0,    92,
+      93,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    94,     2,
+       3,     4,     0,     0,     0,     8,     9,    10,     0,    95,
+      96,     0,    97,     0,     0,     0,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,     0,     0,
+       0,     0,     0,    25,   177,     0,    27,    28,    87,    29,
+      88,    89,    90,    91,     0,     0,    92,    93,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,    94,     2,     3,     4,     0,
+       0,     0,     8,     9,    10,     0,    95,    96,     0,    97,
+       0,     0,     0,    11,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,     0,     0,     0,     0,     0,
+      25,    26,     0,    27,    28,     0,    29,     2,     3,     4,
+       0,     0,     0,     8,     9,    10,     0,     0,     0,     0,
+       0,     0,     0,     0,    11,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,     0,   129,     0,     0,
+       0,    25,    26,     0,    27,    28,     0,    29,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    69,     0,
+       0,     1,     2,     3,     4,     5,     6,     7,     8,     9,
+      10,     0,     0,     0,     0,     0,     0,     0,   196,    11,
+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,     0,     0,     0,    23,    24,    25,    26,     0,    27,
+      28,     0,    29,     2,     3,     4,     0,     0,     0,     8,
+       9,    10,     0,     0,     0,     0,     0,     0,     0,     0,
+      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,     0,     0,     0,     0,     0,    25,    26,     0,
+      27,    28,   229,    29,     0,     0,     0,   230,     1,     2,
+       3,     4,     5,     6,     7,     8,     9,    10,     0,     0,
+       0,     0,     0,     0,     0,     0,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,     0,     0,
+       0,    23,    24,    25,    26,     0,    27,    28,     0,    29,
+       2,     3,     4,     0,     0,     0,     8,     9,    10,     0,
+       0,     0,     0,     0,     0,     0,     0,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,     0,
+       8,     9,    10,     0,    25,    26,     0,    27,    28,     0,
+      29,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,     0,     0,     0,     0,     0,    25,    26,
+       0,    27,    28,     0,    29
+};
+
+static const yytype_int16 yycheck[] =
+{
+       0,    86,    94,   162,    58,    68,     0,   253,    74,     0,
+      43,    51,    52,    34,    85,    77,    40,   153,    80,   265,
+      80,   106,    85,    68,     3,    49,    72,    53,    54,     8,
+       9,   280,    72,    79,    55,   284,    76,     3,    38,    93,
+      85,    74,     8,     9,    44,   137,    71,    92,    93,    71,
+      44,    51,    77,    44,    33,    34,    35,    36,    37,   125,
+      77,    61,    88,    89,   109,    43,   202,    33,    34,    35,
+      36,    37,    72,    37,    74,    71,    76,   162,    37,    43,
+     172,    77,    82,    72,    60,    61,    62,    70,    74,    72,
+     161,   176,    71,    69,    71,    82,    79,    84,   161,    71,
+      77,    74,   194,    79,    43,    77,   185,   186,   187,   188,
+      77,    80,   204,    80,    77,    43,   161,    80,   254,    77,
+      85,    86,    80,    55,    56,   125,   197,   286,    77,    78,
+     266,   216,   217,    43,   197,    70,   181,   182,   183,   184,
+     185,   186,   187,   188,   189,   190,   191,   192,   193,   285,
+     221,    71,   197,   153,     4,     5,     6,    70,   221,   189,
+     190,   253,    33,    34,    35,   183,   184,    57,    59,    73,
+      72,    80,    80,   265,    70,   260,   221,    70,    70,    80,
+      75,   273,    70,    72,    40,    71,    73,    16,    73,    73,
+      70,   283,    73,    70,    77,    73,    43,    71,     4,     5,
+       6,   286,   202,    75,    10,    11,    12,    80,    71,    79,
+     210,    80,   173,   193,    82,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    55,    62,   191,
+      82,     5,    38,    39,    72,    41,    42,    43,    44,    45,
+      46,    47,    48,   198,   192,    51,    52,   250,   284,    53,
+     250,   250,   265,   253,   254,    44,   210,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    70,   265,   266,    73,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    81,    82,    -1,    84,    -1,
+     280,    -1,    -1,    -1,   284,   285,     3,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,    13,    14,    15,    -1,
+      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    31,    32,    -1,    -1,    -1,    36,
+      37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
+      47,    48,    -1,    -1,    51,    52,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    70,    -1,    -1,    -1,    74,    75,    -1,
+      -1,    -1,    -1,    80,    81,    82,    -1,    84,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    -1,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    -1,    -1,
+      -1,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    -1,    -1,    51,    52,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    70,    -1,    -1,    -1,    74,
+      75,    -1,    -1,    -1,    -1,    80,    81,    82,    -1,    84,
+       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+      13,    14,    15,    -1,    17,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+      -1,    -1,    -1,    36,    37,    38,    39,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,    -1,    -1,    51,    52,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    70,    -1,    -1,
+      -1,    74,    -1,    -1,    -1,    -1,    -1,    80,    81,    82,
+      -1,    84,     3,     4,     5,     6,     7,     8,     9,    10,
+      11,    12,    13,    14,    15,    -1,    17,    18,    19,    20,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    32,    -1,    -1,    -1,    36,    37,    38,    39,    40,
+      41,    42,    43,    44,    45,    46,    47,    48,    -1,    -1,
+      51,    52,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    70,
+      -1,    -1,    -1,    74,    -1,    -1,    -1,    -1,    -1,    80,
+      81,    82,    -1,    84,     3,     4,     5,     6,     7,     8,
+       9,    10,    11,    12,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    32,    -1,    -1,    -1,    36,    37,    38,
+      39,    -1,    41,    42,    43,    44,    45,    46,    47,    48,
+      -1,    -1,    51,    52,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    70,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    80,    81,    82,    -1,    84,     3,     4,     5,     6,
+      -1,     8,     9,    10,    11,    12,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    31,    32,    -1,    -1,    -1,    36,
+      37,    38,    39,    -1,    41,    42,    43,    44,    45,    46,
+      47,    48,    -1,    -1,    51,    52,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    70,     4,     5,     6,    -1,    -1,    -1,
+      10,    11,    12,    -1,    81,    82,    -1,    84,    -1,    -1,
+      -1,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    -1,    -1,    -1,    -1,    -1,    38,    39,
+      -1,    41,    42,    43,    44,    45,    46,    47,    48,    -1,
+      -1,    51,    52,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      70,     4,     5,     6,    -1,    -1,    -1,    10,    11,    12,
+      80,    81,    82,    -1,    84,    -1,    -1,    -1,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+      -1,    -1,    -1,    -1,    -1,    38,    39,    -1,    41,    42,
+      43,    44,    45,    46,    47,    48,    -1,    -1,    51,    52,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    70,    -1,    -1,
+      73,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    81,    82,
+      -1,    84,     4,     5,     6,    -1,    -1,    -1,    10,    11,
+      12,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    -1,    -1,    -1,    -1,    -1,    38,    39,    -1,    41,
+      42,    43,    44,    45,    46,    47,    48,    -1,    -1,    51,
+      52,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    70,     4,
+       5,     6,    -1,    -1,    -1,    10,    11,    12,    -1,    81,
+      82,    -1,    84,    -1,    -1,    -1,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    -1,    -1,
+      -1,    -1,    -1,    38,    39,    -1,    41,    42,    43,    44,
+      45,    46,    47,    48,    -1,    -1,    51,    52,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    70,     4,     5,     6,    -1,
+      -1,    -1,    10,    11,    12,    -1,    81,    82,    -1,    84,
+      -1,    -1,    -1,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    -1,    -1,    -1,    -1,    -1,
+      38,    39,    -1,    41,    42,    -1,    44,     4,     5,     6,
+      -1,    -1,    -1,    10,    11,    12,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    31,    32,    -1,    75,    -1,    -1,
+      -1,    38,    39,    -1,    41,    42,    -1,    44,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,     0,    -1,
+      -1,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    75,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    -1,    -1,    -1,    36,    37,    38,    39,    -1,    41,
+      42,    -1,    44,     4,     5,     6,    -1,    -1,    -1,    10,
+      11,    12,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    32,    -1,    -1,    -1,    -1,    -1,    38,    39,    -1,
+      41,    42,    43,    44,    -1,    -1,    -1,    48,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    -1,    -1,
+      -1,    36,    37,    38,    39,    -1,    41,    42,    -1,    44,
+       4,     5,     6,    -1,    -1,    -1,    10,    11,    12,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    -1,
+      10,    11,    12,    -1,    38,    39,    -1,    41,    42,    -1,
+      44,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    -1,    -1,    -1,    -1,    -1,    38,    39,
+      -1,    41,    42,    -1,    44
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    36,    37,    38,    39,    41,    42,    44,
+     124,   125,   126,   127,   128,   133,   134,   135,   136,   137,
+     138,   139,   140,   141,   168,   169,   170,    37,    43,   138,
+      43,    74,    80,   171,    71,    77,     3,    33,    34,    35,
+     130,   131,   136,    77,    80,    43,   137,   139,    72,     0,
+     169,   139,    74,   137,   142,   143,    74,   154,   130,   129,
+     132,   137,   131,    43,    70,    72,    79,    43,    45,    46,
+      47,    48,    51,    52,    70,    81,    82,    84,    95,    96,
+      97,    99,   100,   101,   102,   103,   104,   105,   106,   107,
+     108,   109,   110,   111,   112,   113,   114,   115,   116,   117,
+     118,   119,   123,   137,    80,   142,    43,   144,   145,    75,
+     143,    13,    14,    15,    17,    18,    19,    20,    40,    74,
+      75,    80,   106,   119,   120,   122,   124,   125,   137,   147,
+     148,   149,   150,   155,   156,   157,   160,   167,    43,   129,
+     132,    72,    79,    73,   123,   120,   146,   106,   106,   122,
+      51,    52,    72,    76,    71,    71,    77,    39,   120,    70,
+     106,    85,    86,    82,    84,    53,    54,    88,    89,    55,
+      56,    57,    59,    58,    93,    73,    75,    72,    77,    80,
+      80,    80,   162,    70,    70,    80,    80,   122,    70,    75,
+     151,    60,    61,    62,    69,    79,   121,    77,    80,    75,
+     148,    72,    73,   123,   146,    73,    71,    98,   122,    43,
+      48,   101,   120,   106,   106,   108,   108,   110,   110,   110,
+     110,   111,   111,   115,   116,   117,   122,   123,   145,   148,
+     163,   122,    80,   161,   155,   120,   120,   123,    73,    73,
+      78,    73,    40,   147,   156,   164,    71,   122,   135,   159,
+     152,    73,   120,    70,   159,   165,   166,   148,   158,    43,
+      71,    75,   122,    80,    71,    16,    79,   149,   153,   154,
+      71,   122,   153,   148,   146,    80
+};
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		(-2)
+#define YYEOF		0
+
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT		goto yyabortlab
+#define YYERROR		goto yyerrorlab
+
+
+/* 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);						\
+      yytoken = YYTRANSLATE (yychar);				\
+      YYPOPSTACK (1);						\
+      goto yybackup;						\
+    }								\
+  else								\
+    {								\
+      yyerror (context, YY_("syntax error: cannot back up")); \
+      YYERROR;							\
+    }								\
+while (YYID (0))
+
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)				\
+    do									\
+      if (YYID (N))                                                    \
+	{								\
+	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
+	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
+	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
+	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
+	}								\
+      else								\
+	{								\
+	  (Current).first_line   = (Current).last_line   =		\
+	    YYRHSLOC (Rhs, 0).last_line;				\
+	  (Current).first_column = (Current).last_column =		\
+	    YYRHSLOC (Rhs, 0).last_column;				\
+	}								\
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)			\
+     fprintf (File, "%d.%d-%d.%d",			\
+	      (Loc).first_line, (Loc).first_column,	\
+	      (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval)
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
+do {									  \
+  if (yydebug)								  \
+    {									  \
+      YYFPRINTF (stderr, "%s ", Title);					  \
+      yy_symbol_print (stderr,						  \
+		  Type, Value, context); \
+      YYFPRINTF (stderr, "\n");						  \
+    }									  \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, TParseContext* context)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, context)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    TParseContext* context;
+#endif
+{
+  if (!yyvaluep)
+    return;
+  YYUSE (context);
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+	break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, TParseContext* context)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, context)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    TParseContext* context;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, context);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+    yytype_int16 *bottom;
+    yytype_int16 *top;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)				\
+do {								\
+  if (yydebug)							\
+    yy_stack_print ((Bottom), (Top));				\
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule, TParseContext* context)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule, context)
+    YYSTYPE *yyvsp;
+    int yyrule;
+    TParseContext* context;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+	     yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      fprintf (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+		       &(yyvsp[(yyi + 1) - (yynrhs)])
+		       		       , context);
+      fprintf (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)		\
+do {					\
+  if (yydebug)				\
+    yy_reduce_print (yyvsp, Rule, context); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+	switch (*++yyp)
+	  {
+	  case '\'':
+	  case ',':
+	    goto do_not_strip_quotes;
+
+	  case '\\':
+	    if (*++yyp != '\\')
+	      goto do_not_strip_quotes;
+	    /* Fall through.  */
+	  default:
+	    if (yyres)
+	      yyres[yyn] = *yyp;
+	    yyn++;
+	    break;
+
+	  case '"':
+	    if (yyres)
+	      yyres[yyn] = '\0';
+	    return yyn;
+	  }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
+
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+	 constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+		    + sizeof yyexpecting - 1
+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+		       * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+	 YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	  {
+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+	      {
+		yycount = 1;
+		yysize = yysize0;
+		yyformat[sizeof yyunexpected - 1] = '\0';
+		break;
+	      }
+	    yyarg[yycount++] = yytname[yyx];
+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+	    yysize_overflow |= (yysize1 < yysize);
+	    yysize = yysize1;
+	    yyfmt = yystpcpy (yyfmt, yyprefix);
+	    yyprefix = yyor;
+	  }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+	return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+	{
+	  /* Avoid sprintf, as that infringes on the user's name space.
+	     Don't have undefined behavior even if the translation
+	     produced a string with the wrong number of "%s"s.  */
+	  char *yyp = yyresult;
+	  int yyi = 0;
+	  while ((*yyp = *yyf) != '\0')
+	    {
+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		{
+		  yyp += yytnamerr (yyp, yyarg[yyi++]);
+		  yyf += 2;
+		}
+	      else
+		{
+		  yyp++;
+		  yyf++;
+		}
+	    }
+	}
+      return yysize;
+    }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, TParseContext* context)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, context)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+    TParseContext* context;
+#endif
+{
+  YYUSE (yyvaluep);
+  YYUSE (context);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+	break;
+    }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (TParseContext* context);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (TParseContext* context)
+#else
+int
+yyparse (context)
+    TParseContext* context;
+#endif
+#endif
+{
+  /* The look-ahead symbol.  */
+int yychar;
+
+/* The semantic value of the look-ahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+  int yystate;
+  int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Look-ahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  yytype_int16 yyssa[YYINITDEPTH];
+  yytype_int16 *yyss = yyssa;
+  yytype_int16 *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  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;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* 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;
+	yytype_int16 *yyss1 = yyss;
+
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  This used to be a
+	   conditional around just the two extra args, but that might
+	   be undefined if yyoverflow is a macro.  */
+	yyoverflow (YY_("memory exhausted"),
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+
+		    &yystacksize);
+
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+	goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	yytype_int16 *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyexhaustedlab;
+	YYSTACK_RELOCATE (yyss);
+	YYSTACK_RELOCATE (yyvs);
+
+#  undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     look-ahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to look-ahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a look-ahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the look-ahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 2:
+
+    {
+        // The symbol table search was done in the lexical phase
+        const TSymbol* symbol = (yyvsp[(1) - (1)].lex).symbol;
+        const TVariable* variable;
+        if (symbol == 0) {
+            context->error((yyvsp[(1) - (1)].lex).line, "undeclared identifier", (yyvsp[(1) - (1)].lex).string->c_str(), "");
+            context->recover();
+            TType type(EbtFloat, EbpUndefined);
+            TVariable* fakeVariable = new TVariable((yyvsp[(1) - (1)].lex).string, type);
+            context->symbolTable.insert(*fakeVariable);
+            variable = fakeVariable;
+        } else {
+            // This identifier can only be a variable type symbol
+            if (! symbol->isVariable()) {
+                context->error((yyvsp[(1) - (1)].lex).line, "variable expected", (yyvsp[(1) - (1)].lex).string->c_str(), "");
+                context->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 ) {
+            ConstantUnion* constArray = variable->getConstPointer();
+            TType t(variable->getType());
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(constArray, t, (yyvsp[(1) - (1)].lex).line);
+        } else
+            (yyval.interm.intermTypedNode) = context->intermediate.addSymbol(variable->getUniqueId(),
+                                                     variable->getName(),
+                                                     variable->getType(), (yyvsp[(1) - (1)].lex).line);
+    ;}
+    break;
+
+  case 3:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    ;}
+    break;
+
+  case 4:
+
+    {
+        //
+        // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders,
+        // check for overflow for constants
+        //
+        if (abs((yyvsp[(1) - (1)].lex).i) >= (1 << 16)) {
+            context->error((yyvsp[(1) - (1)].lex).line, " integer constant overflow", "", "");
+            context->recover();
+        }
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setIConst((yyvsp[(1) - (1)].lex).i);
+        (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].lex).line);
+    ;}
+    break;
+
+  case 5:
+
+    {
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setFConst((yyvsp[(1) - (1)].lex).f);
+        (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].lex).line);
+    ;}
+    break;
+
+  case 6:
+
+    {
+        ConstantUnion *unionArray = new ConstantUnion[1];
+        unionArray->setBConst((yyvsp[(1) - (1)].lex).b);
+        (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].lex).line);
+    ;}
+    break;
+
+  case 7:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(2) - (3)].interm.intermTypedNode);
+    ;}
+    break;
+
+  case 8:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    ;}
+    break;
+
+  case 9:
+
+    {
+        if (!(yyvsp[(1) - (4)].interm.intermTypedNode)->isArray() && !(yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix() && !(yyvsp[(1) - (4)].interm.intermTypedNode)->isVector()) {
+            if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode())
+                context->error((yyvsp[(2) - (4)].lex).line, " left of '[' is not of type array, matrix, or vector ", (yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode()->getSymbol().c_str(), "");
+            else
+                context->error((yyvsp[(2) - (4)].lex).line, " left of '[' is not of type array, matrix, or vector ", "expression", "");
+            context->recover();
+        }
+        if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst && (yyvsp[(3) - (4)].interm.intermTypedNode)->getQualifier() == EvqConst) {
+            if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray()) { // constant folding for arrays
+                (yyval.interm.intermTypedNode) = context->addConstArrayNode((yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line);
+            } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector()) {  // constant folding for vectors
+                TVectorFields fields;
+                fields.num = 1;
+                fields.offsets[0] = (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); // need to do it this way because v.xy sends fields integer array
+                (yyval.interm.intermTypedNode) = context->addConstVectorNode(fields, (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line);
+            } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix()) { // constant folding for matrices
+                (yyval.interm.intermTypedNode) = context->addConstMatrixNode((yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line);
+            }
+        } else {
+            if ((yyvsp[(3) - (4)].interm.intermTypedNode)->getQualifier() == EvqConst) {
+                if (((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector() || (yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix()) && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getNominalSize() <= (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst() && !(yyvsp[(1) - (4)].interm.intermTypedNode)->isArray() ) {
+                    context->error((yyvsp[(2) - (4)].lex).line, "", "[", "field selection out of range '%d'", (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
+                    context->recover();
+                } else {
+                    if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray()) {
+                        if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize() == 0) {
+                            if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getMaxArraySize() <= (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) {
+                                if (context->arraySetMaxSize((yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getTypePointer(), (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, (yyvsp[(2) - (4)].lex).line))
+                                    context->recover();
+                            } else {
+                                if (context->arraySetMaxSize((yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getTypePointer(), 0, false, (yyvsp[(2) - (4)].lex).line))
+                                    context->recover();
+                            }
+                        } else if ( (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize()) {
+                            context->error((yyvsp[(2) - (4)].lex).line, "", "[", "array index out of range '%d'", (yyvsp[(3) - (4)].interm.intermTypedNode)->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
+                            context->recover();
+                        }
+                    }
+                    (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(3) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line);
+                }
+            } else {
+                if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize() == 0) {
+                    context->error((yyvsp[(2) - (4)].lex).line, "", "[", "array must be redeclared with a size before being indexed with a variable");
+                    context->recover();
+                }
+
+                (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexIndirect, (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(3) - (4)].interm.intermTypedNode), (yyvsp[(2) - (4)].lex).line);
+            }
+        }
+        if ((yyval.interm.intermTypedNode) == 0) {
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setFConst(0.0f);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), (yyvsp[(2) - (4)].lex).line);
+        } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray()) {
+            if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getStruct())
+                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getStruct(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getTypeName()));
+            else
+                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize(), (yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix()));
+
+            if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst)
+                (yyval.interm.intermTypedNode)->getTypePointer()->setQualifier(EvqConst);
+        } else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst)
+            (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqConst, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize()));
+        else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isMatrix())
+            (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (yyvsp[(1) - (4)].interm.intermTypedNode)->getNominalSize()));
+        else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getQualifier() == EvqConst)
+            (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqConst));
+        else if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isVector())
+            (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (4)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getPrecision(), EvqTemporary));
+        else
+            (yyval.interm.intermTypedNode)->setType((yyvsp[(1) - (4)].interm.intermTypedNode)->getType());
+    ;}
+    break;
+
+  case 10:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    ;}
+    break;
+
+  case 11:
+
+    {
+        if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isArray()) {
+            context->error((yyvsp[(3) - (3)].lex).line, "cannot apply dot operator to an array", ".", "");
+            context->recover();
+        }
+
+        if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isVector()) {
+            TVectorFields fields;
+            if (! context->parseVectorFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yyvsp[(3) - (3)].lex).line)) {
+                fields.num = 1;
+                fields.offsets[0] = 0;
+                context->recover();
+            }
+
+            if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) { // constant folding for vector fields
+                (yyval.interm.intermTypedNode) = context->addConstVectorNode(fields, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].lex).line);
+                if ((yyval.interm.intermTypedNode) == 0) {
+                    context->recover();
+                    (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+                }
+                else
+                    (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqConst, (int) (*(yyvsp[(3) - (3)].lex).string).size()));
+            } else {
+                if (fields.num == 1) {
+                    ConstantUnion *unionArray = new ConstantUnion[1];
+                    unionArray->setIConst(fields.offsets[0]);
+                    TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(3) - (3)].lex).line);
+                    (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line);
+                    (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision()));
+                } else {
+                    TString vectorString = *(yyvsp[(3) - (3)].lex).string;
+                    TIntermTyped* index = context->intermediate.addSwizzle(fields, (yyvsp[(3) - (3)].lex).line);
+                    (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpVectorSwizzle, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line);
+                    (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (int) vectorString.size()));
+                }
+            }
+        } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isMatrix()) {
+            TMatrixFields fields;
+            if (! context->parseMatrixFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yyvsp[(3) - (3)].lex).line)) {
+                fields.wholeRow = false;
+                fields.wholeCol = false;
+                fields.row = 0;
+                fields.col = 0;
+                context->recover();
+            }
+
+            if (fields.wholeRow || fields.wholeCol) {
+                context->error((yyvsp[(2) - (3)].lex).line, " non-scalar fields not implemented yet", ".", "");
+                context->recover();
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setIConst(0);
+                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(3) - (3)].lex).line);
+                (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line);
+                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(),EvqTemporary, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize()));
+            } else {
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setIConst(fields.col * (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize() + fields.row);
+                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yyvsp[(3) - (3)].lex).line);
+                (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line);
+                (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision()));
+            }
+        } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType() == EbtStruct) {
+            bool fieldFound = false;
+            const TTypeList* fields = (yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getStruct();
+            if (fields == 0) {
+                context->error((yyvsp[(2) - (3)].lex).line, "structure has no fields", "Internal Error", "");
+                context->recover();
+                (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+            } else {
+                unsigned int i;
+                for (i = 0; i < fields->size(); ++i) {
+                    if ((*fields)[i].type->getFieldName() == *(yyvsp[(3) - (3)].lex).string) {
+                        fieldFound = true;
+                        break;
+                    }
+                }
+                if (fieldFound) {
+                    if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) {
+                        (yyval.interm.intermTypedNode) = context->addConstStruct(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line);
+                        if ((yyval.interm.intermTypedNode) == 0) {
+                            context->recover();
+                            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+                        }
+                        else {
+                            (yyval.interm.intermTypedNode)->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.
+                            (yyval.interm.intermTypedNode)->getTypePointer()->setQualifier(EvqConst);
+                        }
+                    } else {
+                        ConstantUnion *unionArray = new ConstantUnion[1];
+                        unionArray->setIConst(i);
+                        TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, (yyvsp[(3) - (3)].lex).line);
+                        (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirectStruct, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yyvsp[(2) - (3)].lex).line);
+                        (yyval.interm.intermTypedNode)->setType(*(*fields)[i].type);
+                    }
+                } else {
+                    context->error((yyvsp[(2) - (3)].lex).line, " no such field in structure", (yyvsp[(3) - (3)].lex).string->c_str(), "");
+                    context->recover();
+                    (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+                }
+            }
+        } else {
+            context->error((yyvsp[(2) - (3)].lex).line, " field selection requires structure, vector, or matrix on left hand side", (yyvsp[(3) - (3)].lex).string->c_str(), "");
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+        }
+        // don't delete $3.string, it's from the pool
+    ;}
+    break;
+
+  case 12:
+
+    {
+        if (context->lValueErrorCheck((yyvsp[(2) - (2)].lex).line, "++", (yyvsp[(1) - (2)].interm.intermTypedNode)))
+            context->recover();
+        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostIncrement, (yyvsp[(1) - (2)].interm.intermTypedNode), (yyvsp[(2) - (2)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->unaryOpError((yyvsp[(2) - (2)].lex).line, "++", (yyvsp[(1) - (2)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (2)].interm.intermTypedNode);
+        }
+    ;}
+    break;
+
+  case 13:
+
+    {
+        if (context->lValueErrorCheck((yyvsp[(2) - (2)].lex).line, "--", (yyvsp[(1) - (2)].interm.intermTypedNode)))
+            context->recover();
+        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostDecrement, (yyvsp[(1) - (2)].interm.intermTypedNode), (yyvsp[(2) - (2)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->unaryOpError((yyvsp[(2) - (2)].lex).line, "--", (yyvsp[(1) - (2)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (2)].interm.intermTypedNode);
+        }
+    ;}
+    break;
+
+  case 14:
+
+    {
+        if (context->integerErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode), "[]"))
+            context->recover();
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    ;}
+    break;
+
+  case 15:
+
+    {
+        TFunction* fnCall = (yyvsp[(1) - (1)].interm).function;
+        TOperator op = fnCall->getBuiltInOp();
+
+        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, EbpUndefined);  // use this to get the type back
+            if (context->constructorErrorCheck((yyvsp[(1) - (1)].interm).line, (yyvsp[(1) - (1)].interm).intermNode, *fnCall, op, &type)) {
+                (yyval.interm.intermTypedNode) = 0;
+            } else {
+                //
+                // It's a constructor, of type 'type'.
+                //
+                (yyval.interm.intermTypedNode) = context->addConstructor((yyvsp[(1) - (1)].interm).intermNode, &type, op, fnCall, (yyvsp[(1) - (1)].interm).line);
+            }
+
+            if ((yyval.interm.intermTypedNode) == 0) {
+                context->recover();
+                (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator(0, op, (yyvsp[(1) - (1)].interm).line);
+            }
+            (yyval.interm.intermTypedNode)->setType(type);
+        } else {
+            //
+            // Not a constructor.  Find it in the symbol table.
+            //
+            const TFunction* fnCandidate;
+            bool builtIn;
+            fnCandidate = context->findFunction((yyvsp[(1) - (1)].interm).line, fnCall, &builtIn);
+            if (fnCandidate) {
+                //
+                // A declared function.
+                //
+                if (builtIn && !fnCandidate->getExtension().empty() &&
+                    context->extensionErrorCheck((yyvsp[(1) - (1)].interm).line, fnCandidate->getExtension())) {
+                    context->recover();
+                }
+                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.
+                        //
+                        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(op, (yyvsp[(1) - (1)].interm).intermNode, 0, context->symbolTable);
+                        if ((yyval.interm.intermTypedNode) == 0)  {
+                            context->error((yyvsp[(1) - (1)].interm).intermNode->getLine(), " wrong operand type", "Internal Error",
+                                "built in unary operator function.  Type: %s",
+                                static_cast<TIntermTyped*>((yyvsp[(1) - (1)].interm).intermNode)->getCompleteString().c_str());
+                            YYERROR;
+                        }
+                    } else {
+                        (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, op, (yyvsp[(1) - (1)].interm).line);
+                    }
+                } else {
+                    // This is a real function call
+
+                    (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, EOpFunctionCall, (yyvsp[(1) - (1)].interm).line);
+                    (yyval.interm.intermTypedNode)->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)
+                        (yyval.interm.intermTypedNode)->getAsAggregate()->setUserDefined();
+                    (yyval.interm.intermTypedNode)->getAsAggregate()->setName(fnCandidate->getMangledName());
+
+                    TQualifier qual;
+                    for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
+                        qual = fnCandidate->getParam(i).type->getQualifier();
+                        if (qual == EvqOut || qual == EvqInOut) {
+                            if (context->lValueErrorCheck((yyval.interm.intermTypedNode)->getLine(), "assign", (yyval.interm.intermTypedNode)->getAsAggregate()->getSequence()[i]->getAsTyped())) {
+                                context->error((yyvsp[(1) - (1)].interm).intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", "");
+                                context->recover();
+                            }
+                        }
+                    }
+                }
+                (yyval.interm.intermTypedNode)->setType(fnCandidate->getReturnType());
+            } else {
+                // error message was put out by PaFindFunction()
+                // Put on a dummy node for error recovery
+                ConstantUnion *unionArray = new ConstantUnion[1];
+                unionArray->setFConst(0.0f);
+                (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yyvsp[(1) - (1)].interm).line);
+                context->recover();
+            }
+        }
+        delete fnCall;
+    ;}
+    break;
+
+  case 16:
+
+    {
+        (yyval.interm) = (yyvsp[(1) - (1)].interm);
+    ;}
+    break;
+
+  case 17:
+
+    {
+        context->error((yyvsp[(3) - (3)].interm).line, "methods are not supported", "", "");
+        context->recover();
+        (yyval.interm) = (yyvsp[(3) - (3)].interm);
+    ;}
+    break;
+
+  case 18:
+
+    {
+        (yyval.interm) = (yyvsp[(1) - (2)].interm);
+        (yyval.interm).line = (yyvsp[(2) - (2)].lex).line;
+    ;}
+    break;
+
+  case 19:
+
+    {
+        (yyval.interm) = (yyvsp[(1) - (2)].interm);
+        (yyval.interm).line = (yyvsp[(2) - (2)].lex).line;
+    ;}
+    break;
+
+  case 20:
+
+    {
+        (yyval.interm).function = (yyvsp[(1) - (2)].interm.function);
+        (yyval.interm).intermNode = 0;
+    ;}
+    break;
+
+  case 21:
+
+    {
+        (yyval.interm).function = (yyvsp[(1) - (1)].interm.function);
+        (yyval.interm).intermNode = 0;
+    ;}
+    break;
+
+  case 22:
+
+    {
+        TParameter param = { 0, new TType((yyvsp[(2) - (2)].interm.intermTypedNode)->getType()) };
+        (yyvsp[(1) - (2)].interm.function)->addParameter(param);
+        (yyval.interm).function = (yyvsp[(1) - (2)].interm.function);
+        (yyval.interm).intermNode = (yyvsp[(2) - (2)].interm.intermTypedNode);
+    ;}
+    break;
+
+  case 23:
+
+    {
+        TParameter param = { 0, new TType((yyvsp[(3) - (3)].interm.intermTypedNode)->getType()) };
+        (yyvsp[(1) - (3)].interm).function->addParameter(param);
+        (yyval.interm).function = (yyvsp[(1) - (3)].interm).function;
+        (yyval.interm).intermNode = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line);
+    ;}
+    break;
+
+  case 24:
+
+    {
+        (yyval.interm.function) = (yyvsp[(1) - (2)].interm.function);
+    ;}
+    break;
+
+  case 25:
+
+    {
+        //
+        // Constructor
+        //
+        if ((yyvsp[(1) - (1)].interm.type).array) {
+            // Constructors for arrays are not allowed.
+            context->error((yyvsp[(1) - (1)].interm.type).line, "cannot construct this type", "array", "");
+            context->recover();
+            (yyvsp[(1) - (1)].interm.type).setArray(false);
+        }
+
+        TOperator op = EOpNull;
+        if ((yyvsp[(1) - (1)].interm.type).userDef) {
+            op = EOpConstructStruct;
+        } else {
+            switch ((yyvsp[(1) - (1)].interm.type).type) {
+            case EbtFloat:
+                if ((yyvsp[(1) - (1)].interm.type).matrix) {
+                    switch((yyvsp[(1) - (1)].interm.type).size) {
+                    case 2:                                     op = EOpConstructMat2;  break;
+                    case 3:                                     op = EOpConstructMat3;  break;
+                    case 4:                                     op = EOpConstructMat4;  break;
+                    }
+                } else {
+                    switch((yyvsp[(1) - (1)].interm.type).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((yyvsp[(1) - (1)].interm.type).size) {
+                case 1:                                         op = EOpConstructInt;   break;
+                case 2:       FRAG_VERT_ONLY("ivec2", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructIVec2; break;
+                case 3:       FRAG_VERT_ONLY("ivec3", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructIVec3; break;
+                case 4:       FRAG_VERT_ONLY("ivec4", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructIVec4; break;
+                }
+                break;
+            case EbtBool:
+                switch((yyvsp[(1) - (1)].interm.type).size) {
+                case 1:                                         op = EOpConstructBool;  break;
+                case 2:       FRAG_VERT_ONLY("bvec2", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructBVec2; break;
+                case 3:       FRAG_VERT_ONLY("bvec3", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructBVec3; break;
+                case 4:       FRAG_VERT_ONLY("bvec4", (yyvsp[(1) - (1)].interm.type).line); op = EOpConstructBVec4; break;
+                }
+                break;
+            default: break;
+            }
+            if (op == EOpNull) {
+                context->error((yyvsp[(1) - (1)].interm.type).line, "cannot construct this type", getBasicString((yyvsp[(1) - (1)].interm.type).type), "");
+                context->recover();
+                (yyvsp[(1) - (1)].interm.type).type = EbtFloat;
+                op = EOpConstructFloat;
+            }
+        }
+        TString tempString;
+        TType type((yyvsp[(1) - (1)].interm.type));
+        TFunction *function = new TFunction(&tempString, type, op);
+        (yyval.interm.function) = function;
+    ;}
+    break;
+
+  case 26:
+
+    {
+        if (context->reservedErrorCheck((yyvsp[(1) - (1)].lex).line, *(yyvsp[(1) - (1)].lex).string))
+            context->recover();
+        TType type(EbtVoid, EbpUndefined);
+        TFunction *function = new TFunction((yyvsp[(1) - (1)].lex).string, type);
+        (yyval.interm.function) = function;
+    ;}
+    break;
+
+  case 27:
+
+    {
+        if (context->reservedErrorCheck((yyvsp[(1) - (1)].lex).line, *(yyvsp[(1) - (1)].lex).string))
+            context->recover();
+        TType type(EbtVoid, EbpUndefined);
+        TFunction *function = new TFunction((yyvsp[(1) - (1)].lex).string, type);
+        (yyval.interm.function) = function;
+    ;}
+    break;
+
+  case 28:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    ;}
+    break;
+
+  case 29:
+
+    {
+        if (context->lValueErrorCheck((yyvsp[(1) - (2)].lex).line, "++", (yyvsp[(2) - (2)].interm.intermTypedNode)))
+            context->recover();
+        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreIncrement, (yyvsp[(2) - (2)].interm.intermTypedNode), (yyvsp[(1) - (2)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->unaryOpError((yyvsp[(1) - (2)].lex).line, "++", (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
+        }
+    ;}
+    break;
+
+  case 30:
+
+    {
+        if (context->lValueErrorCheck((yyvsp[(1) - (2)].lex).line, "--", (yyvsp[(2) - (2)].interm.intermTypedNode)))
+            context->recover();
+        (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreDecrement, (yyvsp[(2) - (2)].interm.intermTypedNode), (yyvsp[(1) - (2)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->unaryOpError((yyvsp[(1) - (2)].lex).line, "--", (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
+        }
+    ;}
+    break;
+
+  case 31:
+
+    {
+        if ((yyvsp[(1) - (2)].interm).op != EOpNull) {
+            (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath((yyvsp[(1) - (2)].interm).op, (yyvsp[(2) - (2)].interm.intermTypedNode), (yyvsp[(1) - (2)].interm).line, context->symbolTable);
+            if ((yyval.interm.intermTypedNode) == 0) {
+                const char* errorOp = "";
+                switch((yyvsp[(1) - (2)].interm).op) {
+                case EOpNegative:   errorOp = "-"; break;
+                case EOpLogicalNot: errorOp = "!"; break;
+                default: break;
+                }
+                context->unaryOpError((yyvsp[(1) - (2)].interm).line, errorOp, (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString());
+                context->recover();
+                (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
+            }
+        } else
+            (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
+    ;}
+    break;
+
+  case 32:
+
+    { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpNull; ;}
+    break;
+
+  case 33:
+
+    { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpNegative; ;}
+    break;
+
+  case 34:
+
+    { (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpLogicalNot; ;}
+    break;
+
+  case 35:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;}
+    break;
+
+  case 36:
+
+    {
+        FRAG_VERT_ONLY("*", (yyvsp[(2) - (3)].lex).line);
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpMul, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "*", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+        }
+    ;}
+    break;
+
+  case 37:
+
+    {
+        FRAG_VERT_ONLY("/", (yyvsp[(2) - (3)].lex).line);
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpDiv, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "/", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+        }
+    ;}
+    break;
+
+  case 38:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;}
+    break;
+
+  case 39:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpAdd, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "+", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+        }
+    ;}
+    break;
+
+  case 40:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpSub, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "-", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+        }
+    ;}
+    break;
+
+  case 41:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;}
+    break;
+
+  case 42:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;}
+    break;
+
+  case 43:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThan, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "<", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    ;}
+    break;
+
+  case 44:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThan, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, ">", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    ;}
+    break;
+
+  case 45:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThanEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "<=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    ;}
+    break;
+
+  case 46:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThanEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, ">=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    ;}
+    break;
+
+  case 47:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;}
+    break;
+
+  case 48:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "==", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    ;}
+    break;
+
+  case 49:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpNotEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "!=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    ;}
+    break;
+
+  case 50:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;}
+    break;
+
+  case 51:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;}
+    break;
+
+  case 52:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;}
+    break;
+
+  case 53:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;}
+    break;
+
+  case 54:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalAnd, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "&&", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    ;}
+    break;
+
+  case 55:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;}
+    break;
+
+  case 56:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalXor, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "^^", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    ;}
+    break;
+
+  case 57:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;}
+    break;
+
+  case 58:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalOr, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line, context->symbolTable);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, "||", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            ConstantUnion *unionArray = new ConstantUnion[1];
+            unionArray->setBConst(false);
+            (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yyvsp[(2) - (3)].lex).line);
+        }
+    ;}
+    break;
+
+  case 59:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;}
+    break;
+
+  case 60:
+
+    {
+       if (context->boolErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(1) - (5)].interm.intermTypedNode)))
+            context->recover();
+
+        (yyval.interm.intermTypedNode) = context->intermediate.addSelection((yyvsp[(1) - (5)].interm.intermTypedNode), (yyvsp[(3) - (5)].interm.intermTypedNode), (yyvsp[(5) - (5)].interm.intermTypedNode), (yyvsp[(2) - (5)].lex).line);
+        if ((yyvsp[(3) - (5)].interm.intermTypedNode)->getType() != (yyvsp[(5) - (5)].interm.intermTypedNode)->getType())
+            (yyval.interm.intermTypedNode) = 0;
+
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (5)].lex).line, ":", (yyvsp[(3) - (5)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(5) - (5)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(5) - (5)].interm.intermTypedNode);
+        }
+    ;}
+    break;
+
+  case 61:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;}
+    break;
+
+  case 62:
+
+    {
+        if (context->lValueErrorCheck((yyvsp[(2) - (3)].interm).line, "assign", (yyvsp[(1) - (3)].interm.intermTypedNode)))
+            context->recover();
+        (yyval.interm.intermTypedNode) = context->intermediate.addAssign((yyvsp[(2) - (3)].interm).op, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].interm).line);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->assignError((yyvsp[(2) - (3)].interm).line, "assign", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+        }
+    ;}
+    break;
+
+  case 63:
+
+    {                                    (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpAssign; ;}
+    break;
+
+  case 64:
+
+    { FRAG_VERT_ONLY("*=", (yyvsp[(1) - (1)].lex).line);     (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpMulAssign; ;}
+    break;
+
+  case 65:
+
+    { FRAG_VERT_ONLY("/=", (yyvsp[(1) - (1)].lex).line);     (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpDivAssign; ;}
+    break;
+
+  case 66:
+
+    {                                    (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpAddAssign; ;}
+    break;
+
+  case 67:
+
+    {                                    (yyval.interm).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm).op = EOpSubAssign; ;}
+    break;
+
+  case 68:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    ;}
+    break;
+
+  case 69:
+
+    {
+        (yyval.interm.intermTypedNode) = context->intermediate.addComma((yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yyvsp[(2) - (3)].lex).line);
+        if ((yyval.interm.intermTypedNode) == 0) {
+            context->binaryOpError((yyvsp[(2) - (3)].lex).line, ",", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+            context->recover();
+            (yyval.interm.intermTypedNode) = (yyvsp[(3) - (3)].interm.intermTypedNode);
+        }
+    ;}
+    break;
+
+  case 70:
+
+    {
+        if (context->constErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode)))
+            context->recover();
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    ;}
+    break;
+
+  case 71:
+
+    {
+        TFunction &function = *((yyvsp[(1) - (2)].interm).function);
+        
+        TIntermAggregate *prototype = new TIntermAggregate;
+        prototype->setType(function.getReturnType());
+        prototype->setName(function.getName());
+        
+        for (int i = 0; i < function.getParamCount(); i++)
+        {
+            const TParameter &param = function.getParam(i);
+            if (param.name != 0)
+            {
+                TVariable *variable = new TVariable(param.name, *param.type);
+                
+                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), (yyvsp[(1) - (2)].interm).line), (yyvsp[(1) - (2)].interm).line);
+            }
+            else
+            {
+                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, (yyvsp[(1) - (2)].interm).line), (yyvsp[(1) - (2)].interm).line);
+            }
+        }
+        
+        prototype->setOp(EOpPrototype);
+        (yyval.interm.intermNode) = prototype;
+    ;}
+    break;
+
+  case 72:
+
+    {
+        if ((yyvsp[(1) - (2)].interm).intermAggregate)
+            (yyvsp[(1) - (2)].interm).intermAggregate->setOp(EOpDeclaration);
+        (yyval.interm.intermNode) = (yyvsp[(1) - (2)].interm).intermAggregate;
+    ;}
+    break;
+
+  case 73:
+
+    {
+        context->symbolTable.setDefaultPrecision( (yyvsp[(3) - (4)].interm.type).type, (yyvsp[(2) - (4)].interm.precision) );
+        (yyval.interm.intermNode) = 0;
+    ;}
+    break;
+
+  case 74:
+
+    {
+        //
+        // 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*>(context->symbolTable.find((yyvsp[(1) - (2)].interm.function)->getMangledName()));
+        if (prevDec) {
+            if (prevDec->getReturnType() != (yyvsp[(1) - (2)].interm.function)->getReturnType()) {
+                context->error((yyvsp[(2) - (2)].lex).line, "overloaded functions must have the same return type", (yyvsp[(1) - (2)].interm.function)->getReturnType().getBasicString(), "");
+                context->recover();
+            }
+            for (int i = 0; i < prevDec->getParamCount(); ++i) {
+                if (prevDec->getParam(i).type->getQualifier() != (yyvsp[(1) - (2)].interm.function)->getParam(i).type->getQualifier()) {
+                    context->error((yyvsp[(2) - (2)].lex).line, "overloaded functions must have the same parameter qualifiers", (yyvsp[(1) - (2)].interm.function)->getParam(i).type->getQualifierString(), "");
+                    context->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.
+        //
+        (yyval.interm).function = (yyvsp[(1) - (2)].interm.function);
+        (yyval.interm).line = (yyvsp[(2) - (2)].lex).line;
+
+        context->symbolTable.insert(*(yyval.interm).function);
+    ;}
+    break;
+
+  case 75:
+
+    {
+        (yyval.interm.function) = (yyvsp[(1) - (1)].interm.function);
+    ;}
+    break;
+
+  case 76:
+
+    {
+        (yyval.interm.function) = (yyvsp[(1) - (1)].interm.function);
+    ;}
+    break;
+
+  case 77:
+
+    {
+        // Add the parameter
+        (yyval.interm.function) = (yyvsp[(1) - (2)].interm.function);
+        if ((yyvsp[(2) - (2)].interm).param.type->getBasicType() != EbtVoid)
+            (yyvsp[(1) - (2)].interm.function)->addParameter((yyvsp[(2) - (2)].interm).param);
+        else
+            delete (yyvsp[(2) - (2)].interm).param.type;
+    ;}
+    break;
+
+  case 78:
+
+    {
+        //
+        // Only first parameter of one-parameter functions can be void
+        // The check for named parameters not being void is done in parameter_declarator
+        //
+        if ((yyvsp[(3) - (3)].interm).param.type->getBasicType() == EbtVoid) {
+            //
+            // This parameter > first is void
+            //
+            context->error((yyvsp[(2) - (3)].lex).line, "cannot be an argument type except for '(void)'", "void", "");
+            context->recover();
+            delete (yyvsp[(3) - (3)].interm).param.type;
+        } else {
+            // Add the parameter
+            (yyval.interm.function) = (yyvsp[(1) - (3)].interm.function);
+            (yyvsp[(1) - (3)].interm.function)->addParameter((yyvsp[(3) - (3)].interm).param);
+        }
+    ;}
+    break;
+
+  case 79:
+
+    {
+        if ((yyvsp[(1) - (3)].interm.type).qualifier != EvqGlobal && (yyvsp[(1) - (3)].interm.type).qualifier != EvqTemporary) {
+            context->error((yyvsp[(2) - (3)].lex).line, "no qualifiers allowed for function return", getQualifierString((yyvsp[(1) - (3)].interm.type).qualifier), "");
+            context->recover();
+        }
+        // make sure a sampler is not involved as well...
+        if (context->structQualifierErrorCheck((yyvsp[(2) - (3)].lex).line, (yyvsp[(1) - (3)].interm.type)))
+            context->recover();
+
+        // Add the function as a prototype after parsing it (we do not support recursion)
+        TFunction *function;
+        TType type((yyvsp[(1) - (3)].interm.type));
+        function = new TFunction((yyvsp[(2) - (3)].lex).string, type);
+        (yyval.interm.function) = function;
+    ;}
+    break;
+
+  case 80:
+
+    {
+        if ((yyvsp[(1) - (2)].interm.type).type == EbtVoid) {
+            context->error((yyvsp[(2) - (2)].lex).line, "illegal use of type 'void'", (yyvsp[(2) - (2)].lex).string->c_str(), "");
+            context->recover();
+        }
+        if (context->reservedErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string))
+            context->recover();
+        TParameter param = {(yyvsp[(2) - (2)].lex).string, new TType((yyvsp[(1) - (2)].interm.type))};
+        (yyval.interm).line = (yyvsp[(2) - (2)].lex).line;
+        (yyval.interm).param = param;
+    ;}
+    break;
+
+  case 81:
+
+    {
+        // Check that we can make an array out of this type
+        if (context->arrayTypeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)))
+            context->recover();
+
+        if (context->reservedErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string))
+            context->recover();
+
+        int size;
+        if (context->arraySizeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size))
+            context->recover();
+        (yyvsp[(1) - (5)].interm.type).setArray(true, size);
+
+        TType* type = new TType((yyvsp[(1) - (5)].interm.type));
+        TParameter param = { (yyvsp[(2) - (5)].lex).string, type };
+        (yyval.interm).line = (yyvsp[(2) - (5)].lex).line;
+        (yyval.interm).param = param;
+    ;}
+    break;
+
+  case 82:
+
+    {
+        (yyval.interm) = (yyvsp[(3) - (3)].interm);
+        if (context->paramErrorCheck((yyvsp[(3) - (3)].interm).line, (yyvsp[(1) - (3)].interm.type).qualifier, (yyvsp[(2) - (3)].interm.qualifier), (yyval.interm).param.type))
+            context->recover();
+    ;}
+    break;
+
+  case 83:
+
+    {
+        (yyval.interm) = (yyvsp[(2) - (2)].interm);
+        if (context->parameterSamplerErrorCheck((yyvsp[(2) - (2)].interm).line, (yyvsp[(1) - (2)].interm.qualifier), *(yyvsp[(2) - (2)].interm).param.type))
+            context->recover();
+        if (context->paramErrorCheck((yyvsp[(2) - (2)].interm).line, EvqTemporary, (yyvsp[(1) - (2)].interm.qualifier), (yyval.interm).param.type))
+            context->recover();
+    ;}
+    break;
+
+  case 84:
+
+    {
+        (yyval.interm) = (yyvsp[(3) - (3)].interm);
+        if (context->paramErrorCheck((yyvsp[(3) - (3)].interm).line, (yyvsp[(1) - (3)].interm.type).qualifier, (yyvsp[(2) - (3)].interm.qualifier), (yyval.interm).param.type))
+            context->recover();
+    ;}
+    break;
+
+  case 85:
+
+    {
+        (yyval.interm) = (yyvsp[(2) - (2)].interm);
+        if (context->parameterSamplerErrorCheck((yyvsp[(2) - (2)].interm).line, (yyvsp[(1) - (2)].interm.qualifier), *(yyvsp[(2) - (2)].interm).param.type))
+            context->recover();
+        if (context->paramErrorCheck((yyvsp[(2) - (2)].interm).line, EvqTemporary, (yyvsp[(1) - (2)].interm.qualifier), (yyval.interm).param.type))
+            context->recover();
+    ;}
+    break;
+
+  case 86:
+
+    {
+        (yyval.interm.qualifier) = EvqIn;
+    ;}
+    break;
+
+  case 87:
+
+    {
+        (yyval.interm.qualifier) = EvqIn;
+    ;}
+    break;
+
+  case 88:
+
+    {
+        (yyval.interm.qualifier) = EvqOut;
+    ;}
+    break;
+
+  case 89:
+
+    {
+        (yyval.interm.qualifier) = EvqInOut;
+    ;}
+    break;
+
+  case 90:
+
+    {
+        TParameter param = { 0, new TType((yyvsp[(1) - (1)].interm.type)) };
+        (yyval.interm).param = param;
+    ;}
+    break;
+
+  case 91:
+
+    {
+        (yyval.interm) = (yyvsp[(1) - (1)].interm);
+        
+        if ((yyval.interm).type.precision == EbpUndefined) {
+            (yyval.interm).type.precision = context->symbolTable.getDefaultPrecision((yyvsp[(1) - (1)].interm).type.type);
+            if (context->precisionErrorCheck((yyvsp[(1) - (1)].interm).line, (yyval.interm).type.precision, (yyvsp[(1) - (1)].interm).type.type)) {
+                context->recover();
+            }
+        }
+    ;}
+    break;
+
+  case 92:
+
+    {
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(3) - (3)].lex).string, TType((yyvsp[(1) - (3)].interm).type), (yyvsp[(3) - (3)].lex).line);
+        (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, symbol, (yyvsp[(3) - (3)].lex).line);
+        
+        if (context->structQualifierErrorCheck((yyvsp[(3) - (3)].lex).line, (yyval.interm).type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck((yyvsp[(3) - (3)].lex).line, *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type))
+            context->recover();
+
+        TVariable* variable = 0;
+        if (context->nonInitErrorCheck((yyvsp[(3) - (3)].lex).line, *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type, variable))
+            context->recover();
+        if (symbol && variable)
+            symbol->setId(variable->getUniqueId());
+    ;}
+    break;
+
+  case 93:
+
+    {
+        if (context->structQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck((yyvsp[(3) - (5)].lex).line, *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type))
+            context->recover();
+
+        (yyval.interm) = (yyvsp[(1) - (5)].interm);
+
+        if (context->arrayTypeErrorCheck((yyvsp[(4) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type) || context->arrayQualifierErrorCheck((yyvsp[(4) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type))
+            context->recover();
+        else {
+            (yyvsp[(1) - (5)].interm).type.setArray(true);
+            TVariable* variable;
+            if (context->arrayErrorCheck((yyvsp[(4) - (5)].lex).line, *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, variable))
+                context->recover();
+        }
+    ;}
+    break;
+
+  case 94:
+
+    {
+        if (context->structQualifierErrorCheck((yyvsp[(3) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck((yyvsp[(3) - (6)].lex).line, *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type))
+            context->recover();
+
+        (yyval.interm) = (yyvsp[(1) - (6)].interm);
+
+        if (context->arrayTypeErrorCheck((yyvsp[(4) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type) || context->arrayQualifierErrorCheck((yyvsp[(4) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck((yyvsp[(4) - (6)].lex).line, (yyvsp[(5) - (6)].interm.intermTypedNode), size))
+                context->recover();
+            (yyvsp[(1) - (6)].interm).type.setArray(true, size);
+            TVariable* variable = 0;
+            if (context->arrayErrorCheck((yyvsp[(4) - (6)].lex).line, *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type, variable))
+                context->recover();
+            TType type = TType((yyvsp[(1) - (6)].interm).type);
+            type.setArraySize(size);
+            (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (6)].interm).intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *(yyvsp[(3) - (6)].lex).string, type, (yyvsp[(3) - (6)].lex).line), (yyvsp[(3) - (6)].lex).line);
+        }
+    ;}
+    break;
+
+  case 95:
+
+    {
+        if (context->structQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type))
+            context->recover();
+
+        (yyval.interm) = (yyvsp[(1) - (5)].interm);
+
+        TIntermNode* intermNode;
+        if (!context->executeInitializer((yyvsp[(3) - (5)].lex).line, *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, (yyvsp[(5) - (5)].interm.intermTypedNode), intermNode)) {
+            //
+            // build the intermediate representation
+            //
+            if (intermNode)
+        (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (5)].interm).intermNode, intermNode, (yyvsp[(4) - (5)].lex).line);
+            else
+                (yyval.interm).intermAggregate = (yyvsp[(1) - (5)].interm).intermAggregate;
+        } else {
+            context->recover();
+            (yyval.interm).intermAggregate = 0;
+        }
+    ;}
+    break;
+
+  case 96:
+
+    {
+        (yyval.interm).type = (yyvsp[(1) - (1)].interm.type);
+        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType((yyvsp[(1) - (1)].interm.type)), (yyvsp[(1) - (1)].interm.type).line), (yyvsp[(1) - (1)].interm.type).line);
+    ;}
+    break;
+
+  case 97:
+
+    {
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyvsp[(1) - (2)].interm.type)), (yyvsp[(2) - (2)].lex).line);
+        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (2)].lex).line);
+        
+        if (context->structQualifierErrorCheck((yyvsp[(2) - (2)].lex).line, (yyval.interm).type))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type))
+            context->recover();
+            
+            (yyval.interm).type = (yyvsp[(1) - (2)].interm.type);
+
+        TVariable* variable = 0;
+        if (context->nonInitErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, variable))
+            context->recover();
+        if (variable && symbol)
+            symbol->setId(variable->getUniqueId());
+    ;}
+    break;
+
+  case 98:
+
+    {
+        context->error((yyvsp[(2) - (4)].lex).line, "unsized array declarations not supported", (yyvsp[(2) - (4)].lex).string->c_str(), "");
+        context->recover();
+
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (4)].lex).string, TType((yyvsp[(1) - (4)].interm.type)), (yyvsp[(2) - (4)].lex).line);
+        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (4)].lex).line);
+        (yyval.interm).type = (yyvsp[(1) - (4)].interm.type);
+    ;}
+    break;
+
+  case 99:
+
+    {
+        TType type = TType((yyvsp[(1) - (5)].interm.type));
+        int size;
+        if (context->arraySizeErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size))
+            context->recover();
+        type.setArraySize(size);
+        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (5)].lex).string, type, (yyvsp[(2) - (5)].lex).line);
+        (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (5)].lex).line);
+        
+        if (context->structQualifierErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)))
+            context->recover();
+
+        if (context->nonInitConstErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type)))
+            context->recover();
+
+        (yyval.interm).type = (yyvsp[(1) - (5)].interm.type);
+
+        if (context->arrayTypeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)) || context->arrayQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size))
+                context->recover();
+
+            (yyvsp[(1) - (5)].interm.type).setArray(true, size);
+            TVariable* variable = 0;
+            if (context->arrayErrorCheck((yyvsp[(3) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), variable))
+                context->recover();
+            if (variable && symbol)
+                symbol->setId(variable->getUniqueId());
+        }
+    ;}
+    break;
+
+  case 100:
+
+    {
+        if (context->structQualifierErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type)))
+            context->recover();
+
+        (yyval.interm).type = (yyvsp[(1) - (4)].interm.type);
+
+        TIntermNode* intermNode;
+        if (!context->executeInitializer((yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode)) {
+        //
+        // Build intermediate representation
+        //
+            if(intermNode)
+                (yyval.interm).intermAggregate = context->intermediate.makeAggregate(intermNode, (yyvsp[(3) - (4)].lex).line);
+            else
+                (yyval.interm).intermAggregate = 0;
+        } else {
+            context->recover();
+            (yyval.interm).intermAggregate = 0;
+        }
+    ;}
+    break;
+
+  case 101:
+
+    {
+        VERTEX_ONLY("invariant declaration", (yyvsp[(1) - (2)].lex).line);
+        (yyval.interm).qualifier = EvqInvariantVaryingOut;
+        (yyval.interm).intermAggregate = 0;
+    ;}
+    break;
+
+  case 102:
+
+    {
+        (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
+
+        if ((yyvsp[(1) - (1)].interm.type).array) {
+            context->error((yyvsp[(1) - (1)].interm.type).line, "not supported", "first-class array", "");
+            context->recover();
+            (yyvsp[(1) - (1)].interm.type).setArray(false);
+        }
+    ;}
+    break;
+
+  case 103:
+
+    {
+        if ((yyvsp[(2) - (2)].interm.type).array) {
+            context->error((yyvsp[(2) - (2)].interm.type).line, "not supported", "first-class array", "");
+            context->recover();
+            (yyvsp[(2) - (2)].interm.type).setArray(false);
+        }
+
+        if ((yyvsp[(1) - (2)].interm.type).qualifier == EvqAttribute &&
+            ((yyvsp[(2) - (2)].interm.type).type == EbtBool || (yyvsp[(2) - (2)].interm.type).type == EbtInt)) {
+            context->error((yyvsp[(2) - (2)].interm.type).line, "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier), "");
+            context->recover();
+        }
+        if (((yyvsp[(1) - (2)].interm.type).qualifier == EvqVaryingIn || (yyvsp[(1) - (2)].interm.type).qualifier == EvqVaryingOut) &&
+            ((yyvsp[(2) - (2)].interm.type).type == EbtBool || (yyvsp[(2) - (2)].interm.type).type == EbtInt)) {
+            context->error((yyvsp[(2) - (2)].interm.type).line, "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier), "");
+            context->recover();
+        }
+        (yyval.interm.type) = (yyvsp[(2) - (2)].interm.type);
+        (yyval.interm.type).qualifier = (yyvsp[(1) - (2)].interm.type).qualifier;
+    ;}
+    break;
+
+  case 104:
+
+    {
+        (yyval.interm.type).setBasic(EbtVoid, EvqConst, (yyvsp[(1) - (1)].lex).line);
+    ;}
+    break;
+
+  case 105:
+
+    {
+        VERTEX_ONLY("attribute", (yyvsp[(1) - (1)].lex).line);
+        if (context->globalErrorCheck((yyvsp[(1) - (1)].lex).line, context->symbolTable.atGlobalLevel(), "attribute"))
+            context->recover();
+        (yyval.interm.type).setBasic(EbtVoid, EvqAttribute, (yyvsp[(1) - (1)].lex).line);
+    ;}
+    break;
+
+  case 106:
+
+    {
+        if (context->globalErrorCheck((yyvsp[(1) - (1)].lex).line, context->symbolTable.atGlobalLevel(), "varying"))
+            context->recover();
+        if (context->shaderType == SH_VERTEX_SHADER)
+            (yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yyvsp[(1) - (1)].lex).line);
+        else
+            (yyval.interm.type).setBasic(EbtVoid, EvqVaryingIn, (yyvsp[(1) - (1)].lex).line);
+    ;}
+    break;
+
+  case 107:
+
+    {
+        if (context->globalErrorCheck((yyvsp[(1) - (2)].lex).line, context->symbolTable.atGlobalLevel(), "invariant varying"))
+            context->recover();
+        if (context->shaderType == SH_VERTEX_SHADER)
+            (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingOut, (yyvsp[(1) - (2)].lex).line);
+        else
+            (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingIn, (yyvsp[(1) - (2)].lex).line);
+    ;}
+    break;
+
+  case 108:
+
+    {
+        if (context->globalErrorCheck((yyvsp[(1) - (1)].lex).line, context->symbolTable.atGlobalLevel(), "uniform"))
+            context->recover();
+        (yyval.interm.type).setBasic(EbtVoid, EvqUniform, (yyvsp[(1) - (1)].lex).line);
+    ;}
+    break;
+
+  case 109:
+
+    {
+        (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
+    ;}
+    break;
+
+  case 110:
+
+    {
+        (yyval.interm.type) = (yyvsp[(2) - (2)].interm.type);
+        (yyval.interm.type).precision = (yyvsp[(1) - (2)].interm.precision);
+    ;}
+    break;
+
+  case 111:
+
+    {
+        (yyval.interm.precision) = EbpHigh;
+    ;}
+    break;
+
+  case 112:
+
+    {
+        (yyval.interm.precision) = EbpMedium;
+    ;}
+    break;
+
+  case 113:
+
+    {
+        (yyval.interm.precision) = EbpLow;
+    ;}
+    break;
+
+  case 114:
+
+    {
+        (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
+    ;}
+    break;
+
+  case 115:
+
+    {
+        (yyval.interm.type) = (yyvsp[(1) - (4)].interm.type);
+
+        if (context->arrayTypeErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type)))
+            context->recover();
+        else {
+            int size;
+            if (context->arraySizeErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(3) - (4)].interm.intermTypedNode), size))
+                context->recover();
+            (yyval.interm.type).setArray(true, size);
+        }
+    ;}
+    break;
+
+  case 116:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtVoid, qual, (yyvsp[(1) - (1)].lex).line);
+    ;}
+    break;
+
+  case 117:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
+    ;}
+    break;
+
+  case 118:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line);
+    ;}
+    break;
+
+  case 119:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line);
+    ;}
+    break;
+
+  case 120:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(2);
+    ;}
+    break;
+
+  case 121:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(3);
+    ;}
+    break;
+
+  case 122:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(4);
+    ;}
+    break;
+
+  case 123:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(2);
+    ;}
+    break;
+
+  case 124:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(3);
+    ;}
+    break;
+
+  case 125:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtBool, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(4);
+    ;}
+    break;
+
+  case 126:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(2);
+    ;}
+    break;
+
+  case 127:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(3);
+    ;}
+    break;
+
+  case 128:
+
+    {
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtInt, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(4);
+    ;}
+    break;
+
+  case 129:
+
+    {
+        FRAG_VERT_ONLY("mat2", (yyvsp[(1) - (1)].lex).line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(2, true);
+    ;}
+    break;
+
+  case 130:
+
+    {
+        FRAG_VERT_ONLY("mat3", (yyvsp[(1) - (1)].lex).line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(3, true);
+    ;}
+    break;
+
+  case 131:
+
+    {
+        FRAG_VERT_ONLY("mat4", (yyvsp[(1) - (1)].lex).line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtFloat, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).setAggregate(4, true);
+    ;}
+    break;
+
+  case 132:
+
+    {
+        FRAG_VERT_ONLY("sampler2D", (yyvsp[(1) - (1)].lex).line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtSampler2D, qual, (yyvsp[(1) - (1)].lex).line);
+    ;}
+    break;
+
+  case 133:
+
+    {
+        FRAG_VERT_ONLY("samplerCube", (yyvsp[(1) - (1)].lex).line);
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtSamplerCube, qual, (yyvsp[(1) - (1)].lex).line);
+    ;}
+    break;
+
+  case 134:
+
+    {
+        FRAG_VERT_ONLY("struct", (yyvsp[(1) - (1)].interm.type).line);
+        (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
+        (yyval.interm.type).qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+    ;}
+    break;
+
+  case 135:
+
+    {
+        //
+        // This is for user defined type names.  The lexical phase looked up the
+        // type.
+        //
+        TType& structure = static_cast<TVariable*>((yyvsp[(1) - (1)].lex).symbol)->getType();
+        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+        (yyval.interm.type).setBasic(EbtStruct, qual, (yyvsp[(1) - (1)].lex).line);
+        (yyval.interm.type).userDef = &structure;
+    ;}
+    break;
+
+  case 136:
+
+    {
+        if (context->reservedErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string))
+            context->recover();
+
+        TType* structure = new TType((yyvsp[(4) - (5)].interm.typeList), *(yyvsp[(2) - (5)].lex).string);
+        TVariable* userTypeDef = new TVariable((yyvsp[(2) - (5)].lex).string, *structure, true);
+        if (! context->symbolTable.insert(*userTypeDef)) {
+            context->error((yyvsp[(2) - (5)].lex).line, "redefinition", (yyvsp[(2) - (5)].lex).string->c_str(), "struct");
+            context->recover();
+        }
+        (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yyvsp[(1) - (5)].lex).line);
+        (yyval.interm.type).userDef = structure;
+    ;}
+    break;
+
+  case 137:
+
+    {
+        TType* structure = new TType((yyvsp[(3) - (4)].interm.typeList), TString(""));
+        (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yyvsp[(1) - (4)].lex).line);
+        (yyval.interm.type).userDef = structure;
+    ;}
+    break;
+
+  case 138:
+
+    {
+        (yyval.interm.typeList) = (yyvsp[(1) - (1)].interm.typeList);
+    ;}
+    break;
+
+  case 139:
+
+    {
+        (yyval.interm.typeList) = (yyvsp[(1) - (2)].interm.typeList);
+        for (unsigned int i = 0; i < (yyvsp[(2) - (2)].interm.typeList)->size(); ++i) {
+            for (unsigned int j = 0; j < (yyval.interm.typeList)->size(); ++j) {
+                if ((*(yyval.interm.typeList))[j].type->getFieldName() == (*(yyvsp[(2) - (2)].interm.typeList))[i].type->getFieldName()) {
+                    context->error((*(yyvsp[(2) - (2)].interm.typeList))[i].line, "duplicate field name in structure:", "struct", (*(yyvsp[(2) - (2)].interm.typeList))[i].type->getFieldName().c_str());
+                    context->recover();
+                }
+            }
+            (yyval.interm.typeList)->push_back((*(yyvsp[(2) - (2)].interm.typeList))[i]);
+        }
+    ;}
+    break;
+
+  case 140:
+
+    {
+        (yyval.interm.typeList) = (yyvsp[(2) - (3)].interm.typeList);
+
+        if (context->voidErrorCheck((yyvsp[(1) - (3)].interm.type).line, (*(yyvsp[(2) - (3)].interm.typeList))[0].type->getFieldName(), (yyvsp[(1) - (3)].interm.type))) {
+            context->recover();
+        }
+        for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) {
+            //
+            // Careful not to replace already known aspects of type, like array-ness
+            //
+            TType* type = (*(yyval.interm.typeList))[i].type;
+            type->setBasicType((yyvsp[(1) - (3)].interm.type).type);
+            type->setNominalSize((yyvsp[(1) - (3)].interm.type).size);
+            type->setMatrix((yyvsp[(1) - (3)].interm.type).matrix);
+
+            // don't allow arrays of arrays
+            if (type->isArray()) {
+                if (context->arrayTypeErrorCheck((yyvsp[(1) - (3)].interm.type).line, (yyvsp[(1) - (3)].interm.type)))
+                    context->recover();
+            }
+            if ((yyvsp[(1) - (3)].interm.type).array)
+                type->setArraySize((yyvsp[(1) - (3)].interm.type).arraySize);
+            if ((yyvsp[(1) - (3)].interm.type).userDef) {
+                type->setStruct((yyvsp[(1) - (3)].interm.type).userDef->getStruct());
+                type->setTypeName((yyvsp[(1) - (3)].interm.type).userDef->getTypeName());
+            }
+        }
+    ;}
+    break;
+
+  case 141:
+
+    {
+        (yyval.interm.typeList) = NewPoolTTypeList();
+        (yyval.interm.typeList)->push_back((yyvsp[(1) - (1)].interm.typeLine));
+    ;}
+    break;
+
+  case 142:
+
+    {
+        (yyval.interm.typeList)->push_back((yyvsp[(3) - (3)].interm.typeLine));
+    ;}
+    break;
+
+  case 143:
+
+    {
+        if (context->reservedErrorCheck((yyvsp[(1) - (1)].lex).line, *(yyvsp[(1) - (1)].lex).string))
+            context->recover();
+
+        (yyval.interm.typeLine).type = new TType(EbtVoid, EbpUndefined);
+        (yyval.interm.typeLine).line = (yyvsp[(1) - (1)].lex).line;
+        (yyval.interm.typeLine).type->setFieldName(*(yyvsp[(1) - (1)].lex).string);
+    ;}
+    break;
+
+  case 144:
+
+    {
+        if (context->reservedErrorCheck((yyvsp[(1) - (4)].lex).line, *(yyvsp[(1) - (4)].lex).string))
+            context->recover();
+
+        (yyval.interm.typeLine).type = new TType(EbtVoid, EbpUndefined);
+        (yyval.interm.typeLine).line = (yyvsp[(1) - (4)].lex).line;
+        (yyval.interm.typeLine).type->setFieldName(*(yyvsp[(1) - (4)].lex).string);
+
+        int size;
+        if (context->arraySizeErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(3) - (4)].interm.intermTypedNode), size))
+            context->recover();
+        (yyval.interm.typeLine).type->setArraySize(size);
+    ;}
+    break;
+
+  case 145:
+
+    { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); ;}
+    break;
+
+  case 146:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;}
+    break;
+
+  case 147:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermAggregate); ;}
+    break;
+
+  case 148:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;}
+    break;
+
+  case 149:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;}
+    break;
+
+  case 150:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;}
+    break;
+
+  case 151:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;}
+    break;
+
+  case 152:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;}
+    break;
+
+  case 153:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;}
+    break;
+
+  case 154:
+
+    { (yyval.interm.intermAggregate) = 0; ;}
+    break;
+
+  case 155:
+
+    { context->symbolTable.push(); ;}
+    break;
+
+  case 156:
+
+    { context->symbolTable.pop(); ;}
+    break;
+
+  case 157:
+
+    {
+        if ((yyvsp[(3) - (5)].interm.intermAggregate) != 0) {
+            (yyvsp[(3) - (5)].interm.intermAggregate)->setOp(EOpSequence);
+            (yyvsp[(3) - (5)].interm.intermAggregate)->setEndLine((yyvsp[(5) - (5)].lex).line);
+        }
+        (yyval.interm.intermAggregate) = (yyvsp[(3) - (5)].interm.intermAggregate);
+    ;}
+    break;
+
+  case 158:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;}
+    break;
+
+  case 159:
+
+    { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); ;}
+    break;
+
+  case 160:
+
+    {
+        (yyval.interm.intermNode) = 0;
+    ;}
+    break;
+
+  case 161:
+
+    {
+        if ((yyvsp[(2) - (3)].interm.intermAggregate)) {
+            (yyvsp[(2) - (3)].interm.intermAggregate)->setOp(EOpSequence);
+            (yyvsp[(2) - (3)].interm.intermAggregate)->setEndLine((yyvsp[(3) - (3)].lex).line);
+        }
+        (yyval.interm.intermNode) = (yyvsp[(2) - (3)].interm.intermAggregate);
+    ;}
+    break;
+
+  case 162:
+
+    {
+        (yyval.interm.intermAggregate) = context->intermediate.makeAggregate((yyvsp[(1) - (1)].interm.intermNode), 0);
+    ;}
+    break;
+
+  case 163:
+
+    {
+        (yyval.interm.intermAggregate) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermAggregate), (yyvsp[(2) - (2)].interm.intermNode), 0);
+    ;}
+    break;
+
+  case 164:
+
+    { (yyval.interm.intermNode) = 0; ;}
+    break;
+
+  case 165:
+
+    { (yyval.interm.intermNode) = static_cast<TIntermNode*>((yyvsp[(1) - (2)].interm.intermTypedNode)); ;}
+    break;
+
+  case 166:
+
+    {
+        if (context->boolErrorCheck((yyvsp[(1) - (5)].lex).line, (yyvsp[(3) - (5)].interm.intermTypedNode)))
+            context->recover();
+        (yyval.interm.intermNode) = context->intermediate.addSelection((yyvsp[(3) - (5)].interm.intermTypedNode), (yyvsp[(5) - (5)].interm.nodePair), (yyvsp[(1) - (5)].lex).line);
+    ;}
+    break;
+
+  case 167:
+
+    {
+        (yyval.interm.nodePair).node1 = (yyvsp[(1) - (3)].interm.intermNode);
+        (yyval.interm.nodePair).node2 = (yyvsp[(3) - (3)].interm.intermNode);
+    ;}
+    break;
+
+  case 168:
+
+    {
+        (yyval.interm.nodePair).node1 = (yyvsp[(1) - (1)].interm.intermNode);
+        (yyval.interm.nodePair).node2 = 0;
+    ;}
+    break;
+
+  case 169:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+        if (context->boolErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode)->getLine(), (yyvsp[(1) - (1)].interm.intermTypedNode)))
+            context->recover();
+    ;}
+    break;
+
+  case 170:
+
+    {
+        TIntermNode* intermNode;
+        if (context->structQualifierErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type)))
+            context->recover();
+        if (context->boolErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type)))
+            context->recover();
+
+        if (!context->executeInitializer((yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode))
+            (yyval.interm.intermTypedNode) = (yyvsp[(4) - (4)].interm.intermTypedNode);
+        else {
+            context->recover();
+            (yyval.interm.intermTypedNode) = 0;
+        }
+    ;}
+    break;
+
+  case 171:
+
+    { context->symbolTable.push(); ++context->loopNestingLevel; ;}
+    break;
+
+  case 172:
+
+    {
+        context->symbolTable.pop();
+        (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopWhile, 0, (yyvsp[(4) - (6)].interm.intermTypedNode), 0, (yyvsp[(6) - (6)].interm.intermNode), (yyvsp[(1) - (6)].lex).line);
+        --context->loopNestingLevel;
+    ;}
+    break;
+
+  case 173:
+
+    { ++context->loopNestingLevel; ;}
+    break;
+
+  case 174:
+
+    {
+        if (context->boolErrorCheck((yyvsp[(8) - (8)].lex).line, (yyvsp[(6) - (8)].interm.intermTypedNode)))
+            context->recover();
+
+        (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopDoWhile, 0, (yyvsp[(6) - (8)].interm.intermTypedNode), 0, (yyvsp[(3) - (8)].interm.intermNode), (yyvsp[(4) - (8)].lex).line);
+        --context->loopNestingLevel;
+    ;}
+    break;
+
+  case 175:
+
+    { context->symbolTable.push(); ++context->loopNestingLevel; ;}
+    break;
+
+  case 176:
+
+    {
+        context->symbolTable.pop();
+        (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopFor, (yyvsp[(4) - (7)].interm.intermNode), reinterpret_cast<TIntermTyped*>((yyvsp[(5) - (7)].interm.nodePair).node1), reinterpret_cast<TIntermTyped*>((yyvsp[(5) - (7)].interm.nodePair).node2), (yyvsp[(7) - (7)].interm.intermNode), (yyvsp[(1) - (7)].lex).line);
+        --context->loopNestingLevel;
+    ;}
+    break;
+
+  case 177:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+    ;}
+    break;
+
+  case 178:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+    ;}
+    break;
+
+  case 179:
+
+    {
+        (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+    ;}
+    break;
+
+  case 180:
+
+    {
+        (yyval.interm.intermTypedNode) = 0;
+    ;}
+    break;
+
+  case 181:
+
+    {
+        (yyval.interm.nodePair).node1 = (yyvsp[(1) - (2)].interm.intermTypedNode);
+        (yyval.interm.nodePair).node2 = 0;
+    ;}
+    break;
+
+  case 182:
+
+    {
+        (yyval.interm.nodePair).node1 = (yyvsp[(1) - (3)].interm.intermTypedNode);
+        (yyval.interm.nodePair).node2 = (yyvsp[(3) - (3)].interm.intermTypedNode);
+    ;}
+    break;
+
+  case 183:
+
+    {
+        if (context->loopNestingLevel <= 0) {
+            context->error((yyvsp[(1) - (2)].lex).line, "continue statement only allowed in loops", "", "");
+            context->recover();
+        }
+        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpContinue, (yyvsp[(1) - (2)].lex).line);
+    ;}
+    break;
+
+  case 184:
+
+    {
+        if (context->loopNestingLevel <= 0) {
+            context->error((yyvsp[(1) - (2)].lex).line, "break statement only allowed in loops", "", "");
+            context->recover();
+        }
+        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpBreak, (yyvsp[(1) - (2)].lex).line);
+    ;}
+    break;
+
+  case 185:
+
+    {
+        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpReturn, (yyvsp[(1) - (2)].lex).line);
+        if (context->currentFunctionType->getBasicType() != EbtVoid) {
+            context->error((yyvsp[(1) - (2)].lex).line, "non-void function must return a value", "return", "");
+            context->recover();
+        }
+    ;}
+    break;
+
+  case 186:
+
+    {
+        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpReturn, (yyvsp[(2) - (3)].interm.intermTypedNode), (yyvsp[(1) - (3)].lex).line);
+        context->functionReturnsValue = true;
+        if (context->currentFunctionType->getBasicType() == EbtVoid) {
+            context->error((yyvsp[(1) - (3)].lex).line, "void function cannot return a value", "return", "");
+            context->recover();
+        } else if (*(context->currentFunctionType) != (yyvsp[(2) - (3)].interm.intermTypedNode)->getType()) {
+            context->error((yyvsp[(1) - (3)].lex).line, "function return is not matching type:", "return", "");
+            context->recover();
+        }
+    ;}
+    break;
+
+  case 187:
+
+    {
+        FRAG_ONLY("discard", (yyvsp[(1) - (2)].lex).line);
+        (yyval.interm.intermNode) = context->intermediate.addBranch(EOpKill, (yyvsp[(1) - (2)].lex).line);
+    ;}
+    break;
+
+  case 188:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+        context->treeRoot = (yyval.interm.intermNode);
+    ;}
+    break;
+
+  case 189:
+
+    {
+        (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermNode), (yyvsp[(2) - (2)].interm.intermNode), 0);
+        context->treeRoot = (yyval.interm.intermNode);
+    ;}
+    break;
+
+  case 190:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+    ;}
+    break;
+
+  case 191:
+
+    {
+        (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+    ;}
+    break;
+
+  case 192:
+
+    {
+        TFunction* function = (yyvsp[(1) - (1)].interm).function;
+        TFunction* prevDec = static_cast<TFunction*>(context->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.
+            //
+            context->error((yyvsp[(1) - (1)].interm).line, "function already has a body", function->getName().c_str(), "");
+            context->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) {
+                context->error((yyvsp[(1) - (1)].interm).line, "function cannot take any parameter(s)", function->getName().c_str(), "");
+                context->recover();
+            }
+            if (function->getReturnType().getBasicType() != EbtVoid) {
+                context->error((yyvsp[(1) - (1)].interm).line, "", function->getReturnType().getBasicString(), "main function cannot return a value");
+                context->recover();
+            }
+        }
+
+        //
+        // New symbol table scope for body of function plus its arguments
+        //
+        context->symbolTable.push();
+
+        //
+        // Remember the return type for later checking for RETURN statements.
+        //
+        context->currentFunctionType = &(prevDec->getReturnType());
+        context->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++) {
+            const TParameter& param = function->getParam(i);
+            if (param.name != 0) {
+                TVariable *variable = new TVariable(param.name, *param.type);
+                //
+                // Insert the parameters with name in the symbol table.
+                //
+                if (! context->symbolTable.insert(*variable)) {
+                    context->error((yyvsp[(1) - (1)].interm).line, "redefinition", variable->getName().c_str(), "");
+                    context->recover();
+                    delete variable;
+                }
+
+                //
+                // Add the parameter to the HIL
+                //
+                paramNodes = context->intermediate.growAggregate(
+                                               paramNodes,
+                                               context->intermediate.addSymbol(variable->getUniqueId(),
+                                                                       variable->getName(),
+                                                                       variable->getType(), (yyvsp[(1) - (1)].interm).line),
+                                               (yyvsp[(1) - (1)].interm).line);
+            } else {
+                paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, (yyvsp[(1) - (1)].interm).line), (yyvsp[(1) - (1)].interm).line);
+            }
+        }
+        context->intermediate.setAggregateOperator(paramNodes, EOpParameters, (yyvsp[(1) - (1)].interm).line);
+        (yyvsp[(1) - (1)].interm).intermAggregate = paramNodes;
+        context->loopNestingLevel = 0;
+    ;}
+    break;
+
+  case 193:
+
+    {
+        //?? Check that all paths return a value if return type != void ?
+        //   May be best done as post process phase on intermediate code
+        if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
+            context->error((yyvsp[(1) - (3)].interm).line, "function does not return a value:", "", (yyvsp[(1) - (3)].interm).function->getName().c_str());
+            context->recover();
+        }
+        context->symbolTable.pop();
+        (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermAggregate, (yyvsp[(3) - (3)].interm.intermNode), 0);
+        context->intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yyvsp[(1) - (3)].interm).line);
+        (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[(1) - (3)].interm).function->getMangledName().c_str());
+        (yyval.interm.intermNode)->getAsAggregate()->setType((yyvsp[(1) - (3)].interm).function->getReturnType());
+
+        // store the pragma information for debug and optimize and other vendor specific
+        // information. This information can be queried from the parse tree
+        (yyval.interm.intermNode)->getAsAggregate()->setOptimize(context->contextPragma.optimize);
+        (yyval.interm.intermNode)->getAsAggregate()->setDebug(context->contextPragma.debug);
+        (yyval.interm.intermNode)->getAsAggregate()->addToPragmaTable(context->contextPragma.pragmaTable);
+
+        if ((yyvsp[(3) - (3)].interm.intermNode) && (yyvsp[(3) - (3)].interm.intermNode)->getAsAggregate())
+            (yyval.interm.intermNode)->getAsAggregate()->setEndLine((yyvsp[(3) - (3)].interm.intermNode)->getAsAggregate()->getEndLine());
+    ;}
+    break;
+
+
+/* Line 1267 of yacc.c.  */
+
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+
+  /* 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 - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (context, YY_("syntax error"));
+#else
+      {
+	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+	  {
+	    YYSIZE_T yyalloc = 2 * yysize;
+	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
+	    if (yymsg != yymsgbuf)
+	      YYSTACK_FREE (yymsg);
+	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+	    if (yymsg)
+	      yymsg_alloc = yyalloc;
+	    else
+	      {
+		yymsg = yymsgbuf;
+		yymsg_alloc = sizeof yymsgbuf;
+	      }
+	  }
+
+	if (0 < yysize && yysize <= yymsg_alloc)
+	  {
+	    (void) yysyntax_error (yymsg, yystate, yychar);
+	    yyerror (context, yymsg);
+	  }
+	else
+	  {
+	    yyerror (context, YY_("syntax error"));
+	    if (yysize != 0)
+	      goto yyexhaustedlab;
+	  }
+      }
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse look-ahead token after an
+	 error, discard it.  */
+
+      if (yychar <= YYEOF)
+	{
+	  /* Return failure if at end of input.  */
+	  if (yychar == YYEOF)
+	    YYABORT;
+	}
+      else
+	{
+	  yydestruct ("Error: discarding",
+		      yytoken, &yylval, context);
+	  yychar = YYEMPTY;
+	}
+    }
+
+  /* Else will try to reuse look-ahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+	{
+	  yyn += YYTERROR;
+	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+	    {
+	      yyn = yytable[yyn];
+	      if (0 < yyn)
+		break;
+	    }
+	}
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+	YYABORT;
+
+
+      yydestruct ("Error: popping",
+		  yystos[yystate], yyvsp, context);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  *++yyvsp = yylval;
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (context, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEOF && yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+		 yytoken, &yylval, context);
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+		  yystos[*yyssp], yyvsp, context);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+
+
+
+int glslang_parse(TParseContext* context) {
+    return yyparse(context);
+}
+
+
diff --git a/src/OpenGL ES 2.0/compiler/glslang_tab.h b/src/OpenGL ES 2.0/compiler/glslang_tab.h
new file mode 100644
index 0000000..fa8480d
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/glslang_tab.h
@@ -0,0 +1,274 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   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., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     INVARIANT = 258,
+     HIGH_PRECISION = 259,
+     MEDIUM_PRECISION = 260,
+     LOW_PRECISION = 261,
+     PRECISION = 262,
+     ATTRIBUTE = 263,
+     CONST_QUAL = 264,
+     BOOL_TYPE = 265,
+     FLOAT_TYPE = 266,
+     INT_TYPE = 267,
+     BREAK = 268,
+     CONTINUE = 269,
+     DO = 270,
+     ELSE = 271,
+     FOR = 272,
+     IF = 273,
+     DISCARD = 274,
+     RETURN = 275,
+     BVEC2 = 276,
+     BVEC3 = 277,
+     BVEC4 = 278,
+     IVEC2 = 279,
+     IVEC3 = 280,
+     IVEC4 = 281,
+     VEC2 = 282,
+     VEC3 = 283,
+     VEC4 = 284,
+     MATRIX2 = 285,
+     MATRIX3 = 286,
+     MATRIX4 = 287,
+     IN_QUAL = 288,
+     OUT_QUAL = 289,
+     INOUT_QUAL = 290,
+     UNIFORM = 291,
+     VARYING = 292,
+     STRUCT = 293,
+     VOID_TYPE = 294,
+     WHILE = 295,
+     SAMPLER2D = 296,
+     SAMPLERCUBE = 297,
+     IDENTIFIER = 298,
+     TYPE_NAME = 299,
+     FLOATCONSTANT = 300,
+     INTCONSTANT = 301,
+     BOOLCONSTANT = 302,
+     FIELD_SELECTION = 303,
+     LEFT_OP = 304,
+     RIGHT_OP = 305,
+     INC_OP = 306,
+     DEC_OP = 307,
+     LE_OP = 308,
+     GE_OP = 309,
+     EQ_OP = 310,
+     NE_OP = 311,
+     AND_OP = 312,
+     OR_OP = 313,
+     XOR_OP = 314,
+     MUL_ASSIGN = 315,
+     DIV_ASSIGN = 316,
+     ADD_ASSIGN = 317,
+     MOD_ASSIGN = 318,
+     LEFT_ASSIGN = 319,
+     RIGHT_ASSIGN = 320,
+     AND_ASSIGN = 321,
+     XOR_ASSIGN = 322,
+     OR_ASSIGN = 323,
+     SUB_ASSIGN = 324,
+     LEFT_PAREN = 325,
+     RIGHT_PAREN = 326,
+     LEFT_BRACKET = 327,
+     RIGHT_BRACKET = 328,
+     LEFT_BRACE = 329,
+     RIGHT_BRACE = 330,
+     DOT = 331,
+     COMMA = 332,
+     COLON = 333,
+     EQUAL = 334,
+     SEMICOLON = 335,
+     BANG = 336,
+     DASH = 337,
+     TILDE = 338,
+     PLUS = 339,
+     STAR = 340,
+     SLASH = 341,
+     PERCENT = 342,
+     LEFT_ANGLE = 343,
+     RIGHT_ANGLE = 344,
+     VERTICAL_BAR = 345,
+     CARET = 346,
+     AMPERSAND = 347,
+     QUESTION = 348
+   };
+#endif
+/* Tokens.  */
+#define INVARIANT 258
+#define HIGH_PRECISION 259
+#define MEDIUM_PRECISION 260
+#define LOW_PRECISION 261
+#define PRECISION 262
+#define ATTRIBUTE 263
+#define CONST_QUAL 264
+#define BOOL_TYPE 265
+#define FLOAT_TYPE 266
+#define INT_TYPE 267
+#define BREAK 268
+#define CONTINUE 269
+#define DO 270
+#define ELSE 271
+#define FOR 272
+#define IF 273
+#define DISCARD 274
+#define RETURN 275
+#define BVEC2 276
+#define BVEC3 277
+#define BVEC4 278
+#define IVEC2 279
+#define IVEC3 280
+#define IVEC4 281
+#define VEC2 282
+#define VEC3 283
+#define VEC4 284
+#define MATRIX2 285
+#define MATRIX3 286
+#define MATRIX4 287
+#define IN_QUAL 288
+#define OUT_QUAL 289
+#define INOUT_QUAL 290
+#define UNIFORM 291
+#define VARYING 292
+#define STRUCT 293
+#define VOID_TYPE 294
+#define WHILE 295
+#define SAMPLER2D 296
+#define SAMPLERCUBE 297
+#define IDENTIFIER 298
+#define TYPE_NAME 299
+#define FLOATCONSTANT 300
+#define INTCONSTANT 301
+#define BOOLCONSTANT 302
+#define FIELD_SELECTION 303
+#define LEFT_OP 304
+#define RIGHT_OP 305
+#define INC_OP 306
+#define DEC_OP 307
+#define LE_OP 308
+#define GE_OP 309
+#define EQ_OP 310
+#define NE_OP 311
+#define AND_OP 312
+#define OR_OP 313
+#define XOR_OP 314
+#define MUL_ASSIGN 315
+#define DIV_ASSIGN 316
+#define ADD_ASSIGN 317
+#define MOD_ASSIGN 318
+#define LEFT_ASSIGN 319
+#define RIGHT_ASSIGN 320
+#define AND_ASSIGN 321
+#define XOR_ASSIGN 322
+#define OR_ASSIGN 323
+#define SUB_ASSIGN 324
+#define LEFT_PAREN 325
+#define RIGHT_PAREN 326
+#define LEFT_BRACKET 327
+#define RIGHT_BRACKET 328
+#define LEFT_BRACE 329
+#define RIGHT_BRACE 330
+#define DOT 331
+#define COMMA 332
+#define COLON 333
+#define EQUAL 334
+#define SEMICOLON 335
+#define BANG 336
+#define DASH 337
+#define TILDE 338
+#define PLUS 339
+#define STAR 340
+#define SLASH 341
+#define PERCENT 342
+#define LEFT_ANGLE 343
+#define RIGHT_ANGLE 344
+#define VERTICAL_BAR 345
+#define CARET 346
+#define AMPERSAND 347
+#define QUESTION 348
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+
+{
+    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;
+}
+/* Line 1529 of yacc.c.  */
+
+	YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
diff --git a/src/OpenGL ES 2.0/compiler/intermOut.cpp b/src/OpenGL ES 2.0/compiler/intermOut.cpp
new file mode 100644
index 0000000..798a69a
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/intermOut.cpp
@@ -0,0 +1,417 @@
+//
+// 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 "compiler/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(TInfoSinkBase& i) : sink(i) { }
+    TInfoSinkBase& sink;
+
+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
+{
+    TStringStream stream;
+
+    if (qualifier != EvqTemporary && qualifier != EvqGlobal)
+        stream << getQualifierString() << " " << getPrecisionString() << " ";
+    if (array)
+        stream << "array of ";
+    if (matrix)
+        stream << size << "X" << size << " matrix of ";
+    else if (size > 1)
+        stream << size << "-component vector of ";
+
+    stream << getBasicString();
+    return stream.str();
+}
+
+//
+// Helper functions for printing, not part of traversing.
+//
+
+void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth)
+{
+    int i;
+
+    sink.location(node->getLine());
+
+    for (i = 0; i < depth; ++i)
+        sink << "  ";
+}
+
+//
+// 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(sink, node, depth);
+
+    sink << "'" << node->getSymbol() << "' ";
+    sink << "(" << node->getCompleteString() << ")\n";
+}
+
+bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    switch (node->getOp()) {
+        case EOpAssign:                   out << "move second child to first child";           break;
+        case EOpInitialize:               out << "initialize first child with second child";   break;
+        case EOpAddAssign:                out << "add second child into first child";          break;
+        case EOpSubAssign:                out << "subtract second child into first child";     break;
+        case EOpMulAssign:                out << "multiply second child into first child";     break;
+        case EOpVectorTimesMatrixAssign:  out << "matrix mult second child into first child";  break;
+        case EOpVectorTimesScalarAssign:  out << "vector scale second child into first child"; break;
+        case EOpMatrixTimesScalarAssign:  out << "matrix scale second child into first child"; break;
+        case EOpMatrixTimesMatrixAssign:  out << "matrix mult second child into first child"; break;
+        case EOpDivAssign:                out << "divide second child into first child";       break;
+        case EOpIndexDirect:   out << "direct index";   break;
+        case EOpIndexIndirect: out << "indirect index"; break;
+        case EOpIndexDirectStruct:   out << "direct index for structure";   break;
+        case EOpVectorSwizzle: out << "vector swizzle"; break;
+
+        case EOpAdd:    out << "add";                     break;
+        case EOpSub:    out << "subtract";                break;
+        case EOpMul:    out << "component-wise multiply"; break;
+        case EOpDiv:    out << "divide";                  break;
+        case EOpEqual:            out << "Compare Equal";                 break;
+        case EOpNotEqual:         out << "Compare Not Equal";             break;
+        case EOpLessThan:         out << "Compare Less Than";             break;
+        case EOpGreaterThan:      out << "Compare Greater Than";          break;
+        case EOpLessThanEqual:    out << "Compare Less Than or Equal";    break;
+        case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
+
+        case EOpVectorTimesScalar: out << "vector-scale";          break;
+        case EOpVectorTimesMatrix: out << "vector-times-matrix";   break;
+        case EOpMatrixTimesVector: out << "matrix-times-vector";   break;
+        case EOpMatrixTimesScalar: out << "matrix-scale";          break;
+        case EOpMatrixTimesMatrix: out << "matrix-multiply";       break;
+
+        case EOpLogicalOr:  out << "logical-or";   break;
+        case EOpLogicalXor: out << "logical-xor"; break;
+        case EOpLogicalAnd: out << "logical-and"; break;
+        default: out << "<unknown op>";
+    }
+
+    out << " (" << node->getCompleteString() << ")";
+
+    out << "\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    switch (node->getOp()) {
+        case EOpNegative:       out << "Negate value";         break;
+        case EOpVectorLogicalNot:
+        case EOpLogicalNot:     out << "Negate conditional";   break;
+
+        case EOpPostIncrement:  out << "Post-Increment";       break;
+        case EOpPostDecrement:  out << "Post-Decrement";       break;
+        case EOpPreIncrement:   out << "Pre-Increment";        break;
+        case EOpPreDecrement:   out << "Pre-Decrement";        break;
+
+        case EOpConvIntToBool:  out << "Convert int to bool";  break;
+        case EOpConvFloatToBool:out << "Convert float to bool";break;
+        case EOpConvBoolToFloat:out << "Convert bool to float";break;
+        case EOpConvIntToFloat: out << "Convert int to float"; break;
+        case EOpConvFloatToInt: out << "Convert float to int"; break;
+        case EOpConvBoolToInt:  out << "Convert bool to int";  break;
+
+        case EOpRadians:        out << "radians";              break;
+        case EOpDegrees:        out << "degrees";              break;
+        case EOpSin:            out << "sine";                 break;
+        case EOpCos:            out << "cosine";               break;
+        case EOpTan:            out << "tangent";              break;
+        case EOpAsin:           out << "arc sine";             break;
+        case EOpAcos:           out << "arc cosine";           break;
+        case EOpAtan:           out << "arc tangent";          break;
+
+        case EOpExp:            out << "exp";                  break;
+        case EOpLog:            out << "log";                  break;
+        case EOpExp2:           out << "exp2";                 break;
+        case EOpLog2:           out << "log2";                 break;
+        case EOpSqrt:           out << "sqrt";                 break;
+        case EOpInverseSqrt:    out << "inverse sqrt";         break;
+
+        case EOpAbs:            out << "Absolute value";       break;
+        case EOpSign:           out << "Sign";                 break;
+        case EOpFloor:          out << "Floor";                break;
+        case EOpCeil:           out << "Ceiling";              break;
+        case EOpFract:          out << "Fraction";             break;
+
+        case EOpLength:         out << "length";               break;
+        case EOpNormalize:      out << "normalize";            break;
+            //	case EOpDPdx:           out << "dPdx";                 break;               
+            //	case EOpDPdy:           out << "dPdy";                 break;   
+            //	case EOpFwidth:         out << "fwidth";               break;                   
+
+        case EOpAny:            out << "any";                  break;
+        case EOpAll:            out << "all";                  break;
+
+        default: out.message(EPrefixError, "Bad unary op");
+    }
+
+    out << " (" << node->getCompleteString() << ")";
+
+    out << "\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    TInfoSinkBase& out = sink;
+
+    if (node->getOp() == EOpNull) {
+        out.message(EPrefixError, "node is still EOpNull!");
+        return true;
+    }
+
+    OutputTreeText(out, node, depth);
+
+    switch (node->getOp()) {
+        case EOpSequence:      out << "Sequence\n"; return true;
+        case EOpComma:         out << "Comma\n"; return true;
+        case EOpFunction:      out << "Function Definition: " << node->getName(); break;
+        case EOpFunctionCall:  out << "Function Call: " << node->getName(); break;
+        case EOpParameters:    out << "Function Parameters: ";              break;
+
+        case EOpConstructFloat: out << "Construct float"; break;
+        case EOpConstructVec2:  out << "Construct vec2";  break;
+        case EOpConstructVec3:  out << "Construct vec3";  break;
+        case EOpConstructVec4:  out << "Construct vec4";  break;
+        case EOpConstructBool:  out << "Construct bool";  break;
+        case EOpConstructBVec2: out << "Construct bvec2"; break;
+        case EOpConstructBVec3: out << "Construct bvec3"; break;
+        case EOpConstructBVec4: out << "Construct bvec4"; break;
+        case EOpConstructInt:   out << "Construct int";   break;
+        case EOpConstructIVec2: out << "Construct ivec2"; break;
+        case EOpConstructIVec3: out << "Construct ivec3"; break;
+        case EOpConstructIVec4: out << "Construct ivec4"; break;
+        case EOpConstructMat2:  out << "Construct mat2";  break;
+        case EOpConstructMat3:  out << "Construct mat3";  break;
+        case EOpConstructMat4:  out << "Construct mat4";  break;
+        case EOpConstructStruct:  out << "Construct structure";  break;
+
+        case EOpLessThan:         out << "Compare Less Than";             break;
+        case EOpGreaterThan:      out << "Compare Greater Than";          break;
+        case EOpLessThanEqual:    out << "Compare Less Than or Equal";    break;
+        case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
+        case EOpVectorEqual:      out << "Equal";                         break;
+        case EOpVectorNotEqual:   out << "NotEqual";                      break;
+
+        case EOpMod:           out << "mod";         break;
+        case EOpPow:           out << "pow";         break;
+
+        case EOpAtan:          out << "arc tangent"; break;
+
+        case EOpMin:           out << "min";         break;
+        case EOpMax:           out << "max";         break;
+        case EOpClamp:         out << "clamp";       break;
+        case EOpMix:           out << "mix";         break;
+        case EOpStep:          out << "step";        break;
+        case EOpSmoothStep:    out << "smoothstep";  break;
+
+        case EOpDistance:      out << "distance";                break;
+        case EOpDot:           out << "dot-product";             break;
+        case EOpCross:         out << "cross-product";           break;
+        case EOpFaceForward:   out << "face-forward";            break;
+        case EOpReflect:       out << "reflect";                 break;
+        case EOpRefract:       out << "refract";                 break;
+        case EOpMul:           out << "component-wise multiply"; break;
+
+        default: out.message(EPrefixError, "Bad aggregation op");
+    }
+
+    if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
+        out << " (" << node->getCompleteString() << ")";
+
+    out << "\n";
+
+    return true;
+}
+
+bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    out << "Test condition and select";
+    out << " (" << node->getCompleteString() << ")\n";
+
+    ++depth;
+
+    OutputTreeText(sink, node, depth);
+    out << "Condition\n";
+    node->getCondition()->traverse(this);
+
+    OutputTreeText(sink, node, depth);
+    if (node->getTrueBlock()) {
+        out << "true case\n";
+        node->getTrueBlock()->traverse(this);
+    } else
+        out << "true case is null\n";
+
+    if (node->getFalseBlock()) {
+        OutputTreeText(sink, node, depth);
+        out << "false case\n";
+        node->getFalseBlock()->traverse(this);
+    }
+
+    --depth;
+
+    return false;
+}
+
+void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+    TInfoSinkBase& out = sink;
+
+    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 << "true";
+                else
+                    out << "false";
+
+                out << " (" << "const bool" << ")";
+                out << "\n";
+                break;
+            case EbtFloat:
+                out << node->getUnionArrayPointer()[i].getFConst();
+                out << " (const float)\n";
+                break;
+            case EbtInt:
+                out << node->getUnionArrayPointer()[i].getIConst();
+                out << " (const int)\n";
+                break;
+            default:
+                out.message(EPrefixInternalError, "Unknown constant", node->getLine());
+                break;
+        }
+    }
+}
+
+bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    out << "Loop with condition ";
+    if (node->getType() == ELoopDoWhile)
+        out << "not ";
+    out << "tested first\n";
+
+    ++depth;
+
+    OutputTreeText(sink, node, depth);
+    if (node->getCondition()) {
+        out << "Loop Condition\n";
+        node->getCondition()->traverse(this);
+    } else
+        out << "No loop condition\n";
+
+    OutputTreeText(sink, node, depth);
+    if (node->getBody()) {
+        out << "Loop Body\n";
+        node->getBody()->traverse(this);
+    } else
+        out << "No loop body\n";
+
+    if (node->getExpression()) {
+        OutputTreeText(sink, node, depth);
+        out << "Loop Terminal Expression\n";
+        node->getExpression()->traverse(this);
+    }
+
+    --depth;
+
+    return false;
+}
+
+bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node)
+{
+    TInfoSinkBase& out = sink;
+
+    OutputTreeText(out, node, depth);
+
+    switch (node->getFlowOp()) {
+        case EOpKill:      out << "Branch: Kill";           break;
+        case EOpBreak:     out << "Branch: Break";          break;
+        case EOpContinue:  out << "Branch: Continue";       break;
+        case EOpReturn:    out << "Branch: Return";         break;
+        default:           out << "Branch: Unknown Branch"; break;
+    }
+
+    if (node->getExpression()) {
+        out << " with expression\n";
+        ++depth;
+        node->getExpression()->traverse(this);
+        --depth;
+    } else
+        out << "\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.info);
+
+    root->traverse(&it);
+}
diff --git a/src/OpenGL ES 2.0/compiler/intermediate.h b/src/OpenGL ES 2.0/compiler/intermediate.h
new file mode 100644
index 0000000..a8af5ab
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/intermediate.h
@@ -0,0 +1,544 @@
+//
+// 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 "compiler/Common.h"
+#include "compiler/Types.h"
+#include "compiler/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,
+    EOpPrototype,
+
+    //
+    // Unary operators
+    //
+
+    EOpNegative,
+    EOpLogicalNot,
+    EOpVectorLogicalNot,
+
+    EOpPostIncrement,
+    EOpPostDecrement,
+    EOpPreIncrement,
+    EOpPreDecrement,
+
+    EOpConvIntToBool,
+    EOpConvFloatToBool,
+    EOpConvBoolToFloat,
+    EOpConvIntToFloat,
+    EOpConvFloatToInt,
+    EOpConvBoolToInt,
+
+    //
+    // binary operations
+    //
+
+    EOpAdd,
+    EOpSub,
+    EOpMul,
+    EOpDiv,
+    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,
+    EOpMod,
+    EOpMin,
+    EOpMax,
+    EOpClamp,
+    EOpMix,
+    EOpStep,
+    EOpSmoothStep,
+
+    EOpLength,
+    EOpDistance,
+    EOpDot,
+    EOpCross,
+    EOpNormalize,
+    EOpFaceForward,
+    EOpReflect,
+    EOpRefract,
+
+    EOpDFdx,            // Fragment only, OES_standard_derivatives extension
+    EOpDFdy,            // Fragment only, OES_standard_derivatives extension
+    EOpFwidth,          // Fragment only, OES_standard_derivatives extension
+
+    EOpMatrixTimesMatrix,
+
+    EOpAny,
+    EOpAll,
+
+    //
+    // 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,
+};
+
+extern const char* getOperatorString(TOperator op);
+
+class TIntermTraverser;
+class TIntermAggregate;
+class TIntermBinary;
+class TIntermUnary;
+class TIntermConstantUnion;
+class TIntermSelection;
+class TIntermTyped;
+class TIntermSymbol;
+class TIntermLoop;
+class TInfoSink;
+
+//
+// Base class for the tree nodes
+//
+class TIntermNode {
+public:
+    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+
+    TIntermNode() : line(0) {}
+
+    TSourceLoc getLine() const { return line; }
+    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 TIntermUnary* getAsUnaryNode() { return 0; }
+    virtual TIntermSelection* getAsSelectionNode() { return 0; }
+    virtual TIntermSymbol* getAsSymbolNode() { return 0; }
+    virtual TIntermLoop* getAsLoopNode() { return 0; }
+    virtual ~TIntermNode() { }
+
+protected:
+    TSourceLoc line;
+};
+
+//
+// This is just to help yacc.
+//
+struct TIntermNodePair {
+    TIntermNode* node1;
+    TIntermNode* node2;
+};
+
+//
+// Intermediate class for nodes that have a type.
+//
+class TIntermTyped : public TIntermNode {
+public:
+    TIntermTyped(const TType& t) : type(t)  { }
+    virtual TIntermTyped* getAsTyped() { return this; }
+
+    void setType(const TType& t) { type = t; }
+    const TType& getType() const { return type; }
+    TType* getTypePointer() { return &type; }
+
+    TBasicType getBasicType() const { return type.getBasicType(); }
+    TQualifier getQualifier() const { return type.getQualifier(); }
+    TPrecision getPrecision() const { return type.getPrecision(); }
+    int getNominalSize() const { return type.getNominalSize(); }
+    
+    bool isMatrix() const { return type.isMatrix(); }
+    bool isArray()  const { return type.isArray(); }
+    bool isVector() const { return type.isVector(); }
+    bool isScalar() const { return type.isScalar(); }
+    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.
+//
+enum TLoopType {
+    ELoopFor,
+    ELoopWhile,
+    ELoopDoWhile,
+};
+
+class TIntermLoop : public TIntermNode {
+public:
+    TIntermLoop(TLoopType aType,
+                TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
+                TIntermNode* aBody) :
+            type(aType),
+            init(aInit),
+            cond(aCond),
+            expr(aExpr),
+            body(aBody),
+            unrollFlag(false) { }
+
+    virtual TIntermLoop* getAsLoopNode() { return this; }
+    virtual void traverse(TIntermTraverser*);
+
+    TLoopType getType() const { return type; }
+    TIntermNode* getInit() { return init; }
+    TIntermTyped* getCondition() { return cond; }
+    TIntermTyped* getExpression() { return expr; }
+    TIntermNode* getBody() { return body; }
+
+    void setUnrollFlag(bool flag) { unrollFlag = flag; }
+    bool getUnrollFlag() { return unrollFlag; }
+
+protected:
+    TLoopType type;
+    TIntermNode* init;  // for-loop initialization
+    TIntermTyped* cond; // loop exit condition
+    TIntermTyped* expr; // for-loop expression
+    TIntermNode* body;  // loop body
+
+    bool unrollFlag; // Whether the loop should be unrolled or not.
+};
+
+//
+// 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; originalSymbol = sym; } 
+
+    int getId() const { return id; }
+    const TString& getSymbol() const { return symbol; }
+
+    void setId(int newId) { id = newId; }
+    void setSymbol(const TString& sym) { symbol = sym; }
+
+    const TString& getOriginalSymbol() const { return originalSymbol; }
+
+    virtual void traverse(TIntermTraverser*);
+    virtual TIntermSymbol* getAsSymbolNode() { return this; }
+
+protected:
+    int id;
+    TString symbol;
+    TString originalSymbol;
+};
+
+class TIntermConstantUnion : public TIntermTyped {
+public:
+    TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
+
+    ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
+    void setUnionArrayPointer(ConstantUnion *c) { unionArrayPointer = c; }
+
+    virtual TIntermConstantUnion* getAsConstantUnion()  { return this; }
+    virtual void traverse(TIntermTraverser*);
+
+    TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
+
+protected:
+    ConstantUnion *unionArrayPointer;
+};
+
+//
+// Intermediate class for node types that hold operators.
+//
+class TIntermOperator : public TIntermTyped {
+public:
+    TOperator getOp() const { return op; }
+    void setOp(TOperator o) { op = o; }
+
+    bool modifiesState() const;
+    bool isConstructor() const;
+
+protected:
+    TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), 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 TIntermBinary* getAsBinaryNode() { return this; }
+    virtual void traverse(TIntermTraverser*);
+
+    void setLeft(TIntermTyped* n) { left = n; }
+    void setRight(TIntermTyped* n) { right = n; }
+    TIntermTyped* getLeft() const { return left; }
+    TIntermTyped* getRight() const { return right; }
+    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 TIntermUnary* getAsUnaryNode() { return this; }
+
+    void setOperand(TIntermTyped* o) { operand = o; }
+    TIntermTyped* getOperand() { return operand; }    
+    bool promote(TInfoSink&);
+
+protected:
+    TIntermTyped* operand;
+};
+
+typedef TVector<TIntermNode*> TIntermSequence;
+typedef TVector<int> TQualifierList;
+typedef TMap<TString, TString> TPragmaTable;
+//
+// Nodes that operate on an arbitrary sized set of children.
+//
+class TIntermAggregate : public TIntermOperator {
+public:
+    TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0), endLine(0) { }
+    TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
+    ~TIntermAggregate() { delete pragmaTable; }
+
+    virtual TIntermAggregate* getAsAggregate() { return this; }
+    virtual void traverse(TIntermTraverser*);
+
+    TIntermSequence& getSequence() { return sequence; }
+
+    void setName(const TString& n) { name = n; }
+    const TString& getName() const { return name; }
+
+    void setUserDefined() { userDefined = true; }
+    bool isUserDefined() { return userDefined; }
+
+    void setOptimize(bool o) { optimize = o; }
+    bool getOptimize() { return optimize; }
+    void setDebug(bool d) { debug = d; }
+    bool getDebug() { return debug; }
+    void addToPragmaTable(const TPragmaTable& pTable);
+    const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
+    void setEndLine(TSourceLoc line) { endLine = line; }
+    TSourceLoc getEndLine() const { return endLine; }
+
+protected:
+    TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
+    TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
+    TIntermSequence sequence;
+    TString name;
+    bool userDefined; // used for user defined function names
+
+    bool optimize;
+    bool debug;
+    TPragmaTable *pragmaTable;
+    TSourceLoc endLine;
+};
+
+//
+// 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, EbpUndefined)), 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*);
+
+    bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
+    TIntermNode* getCondition() const { return condition; }
+    TIntermNode* getTrueBlock() const { return trueBlock; }
+    TIntermNode* getFalseBlock() const { return falseBlock; }
+    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/src/OpenGL ES 2.0/compiler/localintermediate.h b/src/OpenGL ES 2.0/compiler/localintermediate.h
new file mode 100644
index 0000000..56890bd
--- /dev/null
+++ b/src/OpenGL ES 2.0/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 "GLSLANG/ShaderLang.h"
+#include "compiler/intermediate.h"
+#include "compiler/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(ConstantUnion*, const TType&, TSourceLoc);
+    TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
+    bool parseConstTree(TSourceLoc, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);        
+    TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, TSourceLoc);
+    TIntermBranch* addBranch(TOperator, TSourceLoc);
+    TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
+    TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
+    bool postProcess(TIntermNode*);
+	void remove(TIntermNode*);
+    void outputTree(TIntermNode*);
+    
+protected:
+    TInfoSink& infoSink;
+
+private:
+    void operator=(TIntermediate&); // prevent assignments
+};
+
+#endif // _LOCAL_INTERMEDIATE_INCLUDED_
diff --git a/src/OpenGL ES 2.0/compiler/osinclude.h b/src/OpenGL ES 2.0/compiler/osinclude.h
new file mode 100644
index 0000000..6ce4df9
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/osinclude.h
@@ -0,0 +1,70 @@
+//
+// 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 os-specific datatypes and
+// declares any os-specific functions.
+//
+
+#if defined(_WIN32) || defined(_WIN64)
+#define ANGLE_OS_WIN
+#elif defined(__APPLE__) || defined(__linux__) || \
+      defined(__FreeBSD__) || defined(__OpenBSD__) || \
+      defined(__sun) || defined(ANDROID)
+#define ANGLE_OS_POSIX
+#else
+#error Unsupported platform.
+#endif
+
+#if defined(ANGLE_USE_NSPR)
+#include "prthread.h"
+#elif defined(ANGLE_OS_WIN)
+#define STRICT
+#define VC_EXTRALEAN 1
+#include <windows.h>
+#elif defined(ANGLE_OS_POSIX)
+#include <pthread.h>
+#include <semaphore.h>
+#include <errno.h>
+#endif  // ANGLE_USE_NSPR
+
+
+#include "compiler/debug.h"
+
+//
+// Thread Local Storage Operations
+//
+#if defined(ANGLE_USE_NSPR)
+typedef PRUintn OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX 0xFFFFFFFF
+#elif defined(ANGLE_OS_WIN)
+typedef DWORD OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES)
+#elif defined(ANGLE_OS_POSIX)
+typedef unsigned int OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX 0xFFFFFFFF
+#endif  // ANGLE_USE_NSPR
+
+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);
+#if defined(ANGLE_USE_NSPR)
+    return PR_GetThreadPrivate(nIndex);
+#elif defined(ANGLE_OS_WIN)
+    return TlsGetValue(nIndex);
+#elif defined(ANGLE_OS_POSIX)
+    return pthread_getspecific(nIndex);
+#endif  // ANGLE_OS_WIN
+}
+
+#endif // __OSINCLUDE_H
diff --git a/src/OpenGL ES 2.0/compiler/ossource_nspr.cpp b/src/OpenGL ES 2.0/compiler/ossource_nspr.cpp
new file mode 100644
index 0000000..f63d81e
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/ossource_nspr.cpp
@@ -0,0 +1,43 @@
+//
+// 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 file contains the nspr specific functions
+//
+#include "compiler/osinclude.h"
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+    PRUintn index;
+    PRStatus status = PR_NewThreadPrivateIndex(&index, NULL);
+
+    if (status) {
+        assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+        return OS_INVALID_TLS_INDEX;
+    }
+
+    return index;
+}
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+    if (nIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+        return false;
+    }
+
+    return PR_SetThreadPrivate(nIndex, lpvValue) == 0;
+}
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+    // Can't delete TLS keys with nspr
+    return true;
+}
+
diff --git a/src/OpenGL ES 2.0/compiler/ossource_posix.cpp b/src/OpenGL ES 2.0/compiler/ossource_posix.cpp
new file mode 100644
index 0000000..1e1e699
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/ossource_posix.cpp
@@ -0,0 +1,64 @@
+//
+// 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 file contains the posix specific functions
+//
+#include "compiler/osinclude.h"
+
+#if !defined(ANGLE_OS_POSIX)
+#error Trying to build a posix specific file in a non-posix build.
+#endif
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+    pthread_key_t pPoolIndex;
+
+    //
+    // Create global pool key.
+    //
+    if ((pthread_key_create(&pPoolIndex, NULL)) != 0) {
+        assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+        return false;
+    }
+    else {
+        return pPoolIndex;
+    }
+}
+
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+    if (nIndex == OS_INVALID_TLS_INDEX) {
+        assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+        return false;
+    }
+
+    if (pthread_setspecific(nIndex, lpvValue) == 0)
+        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;
+    }
+
+    //
+    // Delete the global pool key.
+    //
+    if (pthread_key_delete(nIndex) == 0)
+        return true;
+    else
+        return false;
+}
diff --git a/src/OpenGL ES 2.0/compiler/ossource_win.cpp b/src/OpenGL ES 2.0/compiler/ossource_win.cpp
new file mode 100644
index 0000000..89922fe
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/ossource_win.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 "compiler/osinclude.h"
+//
+// This file contains contains the window's specific functions
+//
+
+#if !defined(ANGLE_OS_WIN)
+#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/src/OpenGL ES 2.0/compiler/parseConst.cpp b/src/OpenGL ES 2.0/compiler/parseConst.cpp
new file mode 100644
index 0000000..9a8a50c
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/parseConst.cpp
@@ -0,0 +1,238 @@
+//
+// 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 "compiler/ParseHelper.h"
+
+//
+// Use this class to carry along data from node to node in 
+// the traversal
+//
+class TConstTraverser : public TIntermTraverser {
+public:
+    TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t)
+        : error(false),
+          index(0),
+          unionArray(cUnion),
+          type(t),
+          constructorType(constructType),
+          singleConstantParam(singleConstParam),
+          infoSink(sink),
+          symbolTable(symTable),
+          size(0),
+          isMatrix(false),
+          matrixSize(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;
+    ConstantUnion *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) {
+        TString buf;
+        buf.append("'constructor' : assigning non-constant to ");
+        buf.append(type.getCompleteString());
+        infoSink.info.message(EPrefixError, buf.c_str(), 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)
+{
+    TString buf;
+    buf.append("'constructor' : assigning non-constant to ");
+    buf.append(type.getCompleteString());
+    infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
+    error = true;
+    return false;  
+}
+
+bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+    if (!node->isConstructor() && node->getOp() != EOpComma) {
+        TString buf;
+        buf.append("'constructor' : assigning non-constant to ");
+        buf.append(type.getCompleteString());
+        infoSink.info.message(EPrefixError, buf.c_str(), 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)
+{
+    ConstantUnion* leftUnionArray = unionArray;
+    int instanceSize = type.getObjectSize();
+
+    if (index >= instanceSize)
+        return;
+
+    if (!singleConstantParam) {
+        int size = node->getType().getObjectSize();
+    
+        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+        for (int i=0; i < size; i++) {
+            if (index >= instanceSize)
+                return;
+            leftUnionArray[index] = rightUnionArray[i];
+
+            (index)++;
+        }
+    } else {
+        int totalSize = index + size;
+        ConstantUnion *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);
+
+                (index)++;
+
+                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, ConstantUnion* 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/src/OpenGL ES 2.0/compiler/preprocessor/atom.c b/src/OpenGL ES 2.0/compiler/preprocessor/atom.c
new file mode 100644
index 0000000..a17c319
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/atom.c
@@ -0,0 +1,736 @@
+/****************************************************************************\
+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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "compiler/debug.h"
+#include "compiler/preprocessor/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);
+    while (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;
+        stable->size = stable->size*2;
+    }
+    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->arev = 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)
+{
+    unsigned 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/src/OpenGL ES 2.0/compiler/preprocessor/atom.h b/src/OpenGL ES 2.0/compiler/preprocessor/atom.h
new file mode 100644
index 0000000..1d84c32
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/atom.h
@@ -0,0 +1,63 @@
+/****************************************************************************\
+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/src/OpenGL ES 2.0/compiler/preprocessor/compile.h b/src/OpenGL ES 2.0/compiler/preprocessor/compile.h
new file mode 100644
index 0000000..1180853
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/compile.h
@@ -0,0 +1,100 @@
+/****************************************************************************\
+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;
+
+#define MAX_IF_NESTING  64
+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 pastFirstStatement;     // used to make sure that #version is the first statement 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[MAX_IF_NESTING];//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
+    const int* PaStrLen;        // array of lengths of the PaArgv strings
+    int PaArgc;                 // count of strings in the array
+    const char* const* PaArgv;  // our array of strings to parse    
+    unsigned int tokensBeforeEOF : 1;
+};
+
+#endif // !defined(__COMPILE_H)
diff --git a/src/OpenGL ES 2.0/compiler/preprocessor/cpp.c b/src/OpenGL ES 2.0/compiler/preprocessor/cpp.c
new file mode 100644
index 0000000..03dd4f6
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/cpp.c
@@ -0,0 +1,1114 @@
+/****************************************************************************\
+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 "compiler/preprocessor/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
+
+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;
+
+    PredefineIntMacro("GL_ES", 1);
+    PredefineIntMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
+
+	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') {
+        if (token == '\\') {
+            CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
+            return token;
+        } else if (token <= 0) { // EOF or error
+            CPPErrorToInfoLog("unexpected end of input in #define preprocessor directive - expected a newline");
+            return 0;
+        }
+        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);
+                if (token <= 0) { // EOF or error
+                    CPPErrorToInfoLog("unexpected end of input in #else preprocessor directive - expected a newline");
+                    return 0;
+                }
+            }
+            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++;
+            if (cpp->ifdepth > MAX_IF_NESTING) {
+                CPPErrorToInfoLog("max #if nesting depth exceeded");
+                cpp->CompileError = 1;
+                return 0;
+            }
+            // sanity check elsetracker
+            if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
+                CPPErrorToInfoLog("mismatched #if/#endif statements");
+                cpp->CompileError = 1;
+                return 0;
+            }
+            cpp->elsedepth[cpp->elsetracker] = 0;
+        }
+        else if (atom == endifAtom) {
+            if(--depth<0){
+                if (cpp->elsetracker)
+                    --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);
+                        if (token <= 0) { // EOF or error
+                            CPPErrorToInfoLog("unexpected end of input following #else preprocessor directive - expected a newline");
+                            return 0;
+                        }
+                    }
+                } 
+				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 0;
+        }
+	};
+    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);
+        
+        if (binop[i].op == op_div || binop[i].op == op_mod)
+        {
+            if (*res == 0)
+            {
+                CPPErrorToInfoLog("preprocessor divide or modulo by zero");
+                *err = 1;
+                return token;
+            }
+        }
+
+        *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;
+
+    if (!cpp->ifdepth++)
+        ifloc = *cpp->tokenLoc;
+    if(cpp->ifdepth > MAX_IF_NESTING){
+        CPPErrorToInfoLog("max #if nesting depth exceeded");
+        cpp->CompileError = 1;
+        return 0;
+    }
+    cpp->elsetracker++;
+    // sanity check elsetracker
+    if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
+        CPPErrorToInfoLog("mismatched #if/#endif statements");
+        cpp->CompileError = 1;
+        return 0;
+    }
+    cpp->elsedepth[cpp->elsetracker] = 0;
+
+    token = eval(token, MIN_PREC, &res, &err, yylvalpp);
+    if (token != '\n') {
+        CPPWarningToInfoLog("unexpected tokens following #if preprocessor directive - expected a newline");
+        while (token != '\n') {
+            token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+            if (token <= 0) { // EOF or error
+                CPPErrorToInfoLog("unexpected end of input in #if preprocessor directive - expected a newline");
+                return 0;
+            }
+        }
+    } 
+    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");
+        cpp->CompileError = 1;
+        return 0;
+    }
+    cpp->elsetracker++;
+    // sanity check elsetracker
+    if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
+        CPPErrorToInfoLog("mismatched #if/#endif statements");
+        cpp->CompileError = 1;
+        return 0;
+    }
+    cpp->elsedepth[cpp->elsetracker] = 0;
+
+    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 (token <= 0) { // EOF or error
+                    CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline");
+                    return 0;
+                }
+            }
+        }
+        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 <= 0){
+            CPPErrorToInfoLog("unexpected end of input in #error preprocessor directive - expected a newline");
+            return 0;
+        }else 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 ESSL_VERSION_NUMBER 100
+#define ESSL_VERSION_STRING "100"
+
+static int CPPversion(yystypepp * yylvalpp)
+{
+
+    int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
+
+    if (cpp->pastFirstStatement == 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 != ESSL_VERSION_NUMBER)
+        CPPShInfoLogMsg("Version number not supported by ESSL");
+
+    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[MAX_SYMBOL_NAME_LEN + 1];
+
+    if(token=='\n'){
+		DecLineNumber();
+        CPPShInfoLogMsg("extension name not specified");
+        IncLineNumber();
+		return token;
+	}
+
+    if (token != CPP_IDENTIFIER)
+        CPPErrorToInfoLog("#extension");
+    
+    strncpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident), MAX_SYMBOL_NAME_LEN);
+    extensionName[MAX_SYMBOL_NAME_LEN] = '\0';
+	    
+    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;
+                     return 0;
+                 }
+                 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);
+                         if (token <= 0) { // EOF or error
+                             CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline");
+                             return 0;
+                         }
+                     }
+                 }
+			     token = CPPelse(0, yylvalpp);
+             }else{
+                 CPPErrorToInfoLog("#else after a #else");
+                 cpp->ifdepth = 0;
+                 cpp->elsetracker = 0;
+                 cpp->pastFirstStatement = 1;
+                 cpp->CompileError = 1;
+                 return 0;
+             }
+		} else if (yylvalpp->sc_ident == elifAtom) {
+            if (!cpp->ifdepth){
+                 CPPErrorToInfoLog("#elif mismatch");
+                 cpp->CompileError=1;
+                 return 0;
+            } 
+            // 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);
+                if (token <= 0) { // EOF or error
+                    CPPErrorToInfoLog("unexpect tokens following #elif preprocessor directive - expected a newline");
+                    cpp->CompileError = 1;
+                    return 0;
+                }
+            }
+		    token = CPPelse(0, yylvalpp);
+        } else if (yylvalpp->sc_ident == endifAtom) {
+             if (!cpp->ifdepth){
+                 CPPErrorToInfoLog("#endif mismatch");
+                 cpp->CompileError=1;
+                 return 0;
+             }
+             else
+                 --cpp->ifdepth;
+
+             if (cpp->elsetracker)
+                 --cpp->elsetracker;
+
+	    } 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->pastFirstStatement = 1;
+
+    return token;
+} // readCPPline
+
+void FreeMacro(MacroSymbol *s) {
+    DeleteTokenStream(s->body);
+}
+
+void PredefineIntMacro(const char *name, int value) {
+    SourceLoc location = {0};
+    Symbol *symbol = NULL;
+    MacroSymbol macro = {0};
+    yystypepp val = {0};
+    int atom = 0;
+
+    macro.body = NewTokenStream(name, macros->pool);
+    val.sc_int = value;
+    sprintf(val.symbol_name, "%d", value);
+    RecordToken(macro.body, CPP_INTCONSTANT, &val);
+    atom = LookUpAddString(atable, name);
+    symbol = AddSymbol(&location, macros, atom, MACRO_S);
+    symbol->details.mac = macro;
+}
+
+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,ESSL_VERSION_STRING);
+        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)
+{
+    // sanity check to make sure elsetracker is in a valid range
+    if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
+        return 0;
+    }
+
+    if (cpp->elsedepth[cpp->elsetracker] == 0) {
+        cpp->elsedepth[cpp->elsetracker] = 1;
+        return 1;
+    }
+    return 0;
+}
+
+
diff --git a/src/OpenGL ES 2.0/compiler/preprocessor/cpp.h b/src/OpenGL ES 2.0/compiler/preprocessor/cpp.h
new file mode 100644
index 0000000..db4c184
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/cpp.h
@@ -0,0 +1,86 @@
+/****************************************************************************\
+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 "compiler/preprocessor/parser.h"
+#include "compiler/preprocessor/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 *);
+void PredefineIntMacro(const char *name, int value);
+
+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/src/OpenGL ES 2.0/compiler/preprocessor/cppstruct.c b/src/OpenGL ES 2.0/compiler/preprocessor/cppstruct.c
new file mode 100644
index 0000000..58cff31
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/cppstruct.c
@@ -0,0 +1,152 @@
+/****************************************************************************\
+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 "compiler/preprocessor/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 < MAX_IF_NESTING; 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/src/OpenGL ES 2.0/compiler/preprocessor/memory.c b/src/OpenGL ES 2.0/compiler/preprocessor/memory.c
new file mode 100644
index 0000000..e6fea7a
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/memory.c
@@ -0,0 +1,154 @@
+/****************************************************************************\
+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>
+
+#ifndef _MSC_VER
+#include <stdint.h>
+#endif
+
+#include "compiler/preprocessor/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/src/OpenGL ES 2.0/compiler/preprocessor/memory.h b/src/OpenGL ES 2.0/compiler/preprocessor/memory.h
new file mode 100644
index 0000000..b3ae2f9
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/memory.h
@@ -0,0 +1,56 @@
+/****************************************************************************\
+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 int 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/src/OpenGL ES 2.0/compiler/preprocessor/parser.h b/src/OpenGL ES 2.0/compiler/preprocessor/parser.h
new file mode 100644
index 0000000..f67342b
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/parser.h
@@ -0,0 +1,93 @@
+/****************************************************************************\
+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/src/OpenGL ES 2.0/compiler/preprocessor/preprocess.h b/src/OpenGL ES 2.0/compiler/preprocessor/preprocess.h
new file mode 100644
index 0000000..88d196f
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/preprocess.h
@@ -0,0 +1,51 @@
+/****************************************************************************\
+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 "compiler/preprocessor/slglobals.h"
+extern CPPStruct *cpp;
+int InitCPPStruct(void);
+int InitScanner(CPPStruct *cpp);
+int InitAtomTable(AtomTable *atable, int htsize);
+int ScanFromString(const char *s);
+char* GetStringOfAtom(AtomTable *atable, int atom);
diff --git a/src/OpenGL ES 2.0/compiler/preprocessor/scanner.c b/src/OpenGL ES 2.0/compiler/preprocessor/scanner.c
new file mode 100644
index 0000000..deedb43
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/scanner.c
@@ -0,0 +1,688 @@
+/****************************************************************************\
+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 <assert.h>
+#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 "compiler/preprocessor/slglobals.h"
+#include "compiler/util.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(_MSC_VER)
+    #define DBG_BREAKPOINT() __asm int 3
+#elif defined(_M_AMD64)
+    #define DBG_BREAKPOINT() assert(!"Dbg_Breakpoint");
+#else
+    #define DBG_BREAKPOINT()
+#endif
+
+#if defined(_MSC_VER) && !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->pastFirstStatement = 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(const char *s)
+{
+    
+    StringInputSrc *in = malloc(sizeof(StringInputSrc));
+    memset(in, 0, sizeof(StringInputSrc));
+    in->p = (char*) 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: /////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define APPEND_CHAR_S(ch, str, len, max_len) \
+      if (len < max_len) { \
+          str[len++] = ch; \
+      } else if (!alreadyComplained) { \
+          CPPErrorToInfoLog("BUFFER OVERFLOW"); \
+          alreadyComplained = 1; \
+      }
+
+/*
+ * 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'.
+ * ch - '.' or 'e'
+ * len - length of string already copied into yylvalpp->symbol_name.
+ */
+
+static int lFloatConst(int ch, int len, yystypepp * yylvalpp)
+{
+    int alreadyComplained = 0;
+    assert((ch == '.') || (ch == 'e') || (ch == 'E'));
+
+    if (ch == '.') {
+        do {
+            APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        } while (ch >= '0' && ch <= '9');
+    }
+
+    // Exponent:
+    if (ch == 'e' || ch == 'E') {
+        APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        if (ch == '+') {
+            APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        } else if (ch == '-') {
+            APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+        }
+        if (ch >= '0' && ch <= '9') {
+            while (ch >= '0' && ch <= '9') {
+                APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            }
+        } else {
+            CPPErrorToInfoLog("EXPONENT INVALID");
+        }
+    }
+    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+
+    assert(len <= MAX_SYMBOL_NAME_LEN);
+    yylvalpp->symbol_name[len] = '\0';
+    yylvalpp->sc_fval = (float) atof_dot(yylvalpp->symbol_name);
+    if (isinff(yylvalpp->sc_fval)) {
+        CPPErrorToInfoLog("FLOAT CONSTANT OVERFLOW");
+    }
+    return CPP_FLOATCONSTANT;
+} // lFloatConst
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////// Normal Scanner //////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+    
+static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
+{
+    char string_val[MAX_STRING_LEN + 1];
+    int alreadyComplained = 0;
+    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;
+        alreadyComplained = 0;
+        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 {
+                APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            } while ((ch >= 'a' && ch <= 'z') ||
+                     (ch >= 'A' && ch <= 'Z') ||
+                     (ch >= '0' && ch <= '9') ||
+                     ch == '_');
+            assert(len <= MAX_SYMBOL_NAME_LEN);
+            yylvalpp->symbol_name[len] = '\0';
+            cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+            yylvalpp->sc_ident = LookUpAddString(atable, yylvalpp->symbol_name);
+            return CPP_IDENTIFIER;
+            break;
+        case '0':
+            APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            if (ch == 'x' || ch == 'X') {  // hexadecimal integer constants
+                APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                if ((ch >= '0' && ch <= '9') ||
+                    (ch >= 'A' && ch <= 'F') ||
+                    (ch >= 'a' && ch <= 'f'))
+                {
+                    ival = 0;
+                    do {
+                        if ((ival <= 0x0fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
+                            yylvalpp->symbol_name[len++] = ch;
+                            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("HEX CONSTANT 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("HEX CONSTANT INVALID");
+                }
+                assert(len <= MAX_SYMBOL_NAME_LEN);
+                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
+                ival = 0;
+                do {
+                    if ((ival <= 0x1fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
+                        yylvalpp->symbol_name[len++] = ch;
+                        ii = ch - '0';
+                        ival = (ival << 3) | ii;
+                    } else if (!alreadyComplained) {
+                        CPPErrorToInfoLog("OCT CONSTANT 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(ch, len, yylvalpp);
+                assert(len <= MAX_SYMBOL_NAME_LEN);
+                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 {
+                APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            } while (ch >= '0' && ch <= '9');
+            if (ch == '.' || ch == 'e' || ch == 'E') {
+                return lFloatConst(ch, len, yylvalpp);
+            } else {
+                assert(len <= MAX_SYMBOL_NAME_LEN);
+                yylvalpp->symbol_name[len] = '\0';
+                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+                ival = 0;
+                for (ii = 0; ii < len; ii++) {
+                    ch = yylvalpp->symbol_name[ii] - '0';
+                    ival = ival*10 + ch;
+                    if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) {
+                        CPPErrorToInfoLog("INTEGER CONSTANT OVERFLOW");
+                        break;
+                    }
+                }
+                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('.', 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 == '*') {
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                do {
+                    while (ch != '*') {
+                        if (ch == EOF) {
+                            CPPErrorToInfoLog("EOF IN COMMENT");
+                            return -1;
+                        }
+                        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                    }
+                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+                    if (ch == EOF) {
+                        CPPErrorToInfoLog("EOF IN COMMENT");
+                        return -1;
+                    }
+                } while (ch != '/');
+                // 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 == '\\') {
+                    CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
+                    return -1;
+                }
+                APPEND_CHAR_S(ch, string_val, len, MAX_STRING_LEN);
+                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+            };
+            assert(len <= MAX_STRING_LEN);
+            string_val[len] = '\0';
+            if (ch == '"') {
+                yylvalpp->sc_ident = LookUpAddString(atable, string_val);
+                return CPP_STRCONSTANT;
+            } else {
+                CPPErrorToInfoLog("EOL IN STRING");
+                return ERROR_SY;
+            }
+            break;
+        }
+    }
+} // 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 < 0) {
+            // This check may need to be improved to support UTF-8
+            // characters in comments.
+            CPPErrorToInfoLog("preprocessor encountered non-ASCII character in shader source");
+            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->pastFirstStatement = 1;
+            continue;
+        }
+
+        if (token == '\n')
+            continue;
+        cpp->pastFirstStatement = 1;
+
+        if (token == CPP_IDENTIFIER) {
+            tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident);
+        } else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
+            tokenString = yylvalpp.symbol_name;
+        } else {
+            tokenString = GetStringOfAtom(atable,token);
+        }
+
+        if (tokenString) {
+            int len = strlen(tokenString);
+            cpp->tokensBeforeEOF = 1;
+            if (len >= maxSize) {
+                return maxSize;
+            } else  if (len > 0) {
+                strcpy(buf, tokenString);
+                return len;
+            }
+
+            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/src/OpenGL ES 2.0/compiler/preprocessor/scanner.h b/src/OpenGL ES 2.0/compiler/preprocessor/scanner.h
new file mode 100644
index 0000000..33306e5
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/scanner.h
@@ -0,0 +1,84 @@
+/****************************************************************************\
+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
+
+// These lengths do not include the NULL terminator.
+#define MAX_SYMBOL_NAME_LEN 256
+#define MAX_STRING_LEN 511
+
+#include "compiler/preprocessor/parser.h"
+
+// Not really atom table stuff but needed first...
+
+typedef struct SourceLoc_Rec {
+    unsigned short file, line;
+} SourceLoc;
+
+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(const 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/src/OpenGL ES 2.0/compiler/preprocessor/slglobals.h b/src/OpenGL ES 2.0/compiler/preprocessor/slglobals.h
new file mode 100644
index 0000000..4634626
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/slglobals.h
@@ -0,0 +1,82 @@
+/****************************************************************************\
+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 "compiler/preprocessor/memory.h"
+#include "compiler/preprocessor/atom.h"
+#include "compiler/preprocessor/scanner.h"
+#include "compiler/preprocessor/cpp.h"
+#include "compiler/preprocessor/tokens.h"
+#include "compiler/preprocessor/symbols.h"
+#include "compiler/preprocessor/compile.h"
+#if !defined(NO_PARSER)
+#include "compiler/preprocessor/parser.h"
+#endif
+
+#if !defined(NULL)
+#define NULL 0
+#endif
+
+#endif // !(defined(__SLGLOBALS_H)
+
+
+    
+
diff --git a/src/OpenGL ES 2.0/compiler/preprocessor/symbols.c b/src/OpenGL ES 2.0/compiler/preprocessor/symbols.c
new file mode 100644
index 0000000..5baedf5
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/symbols.c
@@ -0,0 +1,284 @@
+/****************************************************************************\
+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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "compiler/preprocessor/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;
+    unsigned 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/src/OpenGL ES 2.0/compiler/preprocessor/symbols.h b/src/OpenGL ES 2.0/compiler/preprocessor/symbols.h
new file mode 100644
index 0000000..c19f79c
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/symbols.h
@@ -0,0 +1,112 @@
+/****************************************************************************\
+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 "compiler/preprocessor/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 "compiler/preprocessor/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/src/OpenGL ES 2.0/compiler/preprocessor/tokens.c b/src/OpenGL ES 2.0/compiler/preprocessor/tokens.c
new file mode 100644
index 0000000..aa83d2f
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/tokens.c
@@ -0,0 +1,436 @@
+/****************************************************************************\
+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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "compiler/debug.h"
+#include "compiler/preprocessor/slglobals.h"
+#include "compiler/util.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;
+    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++);
+         }
+         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;
+                    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;
+                    ch = lReadByte(pTok);
+                }
+            }
+            symbol_name[len] = '\0';
+            assert(ch == '\0');
+            strcpy(yylvalpp->symbol_name,symbol_name);
+            yylvalpp->sc_fval=(float)atof_dot(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;
+                    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/src/OpenGL ES 2.0/compiler/preprocessor/tokens.h b/src/OpenGL ES 2.0/compiler/preprocessor/tokens.h
new file mode 100644
index 0000000..8766df9
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/preprocessor/tokens.h
@@ -0,0 +1,89 @@
+/****************************************************************************\
+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 "compiler/preprocessor/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/src/OpenGL ES 2.0/compiler/translator_common.vcxproj b/src/OpenGL ES 2.0/compiler/translator_common.vcxproj
new file mode 100644
index 0000000..15974d1
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/translator_common.vcxproj
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{5B3A6DB8-1E7E-40D7-92B9-DA8AAE619FAD}</ProjectGuid>

+    <RootNamespace>compiler</RootNamespace>

+    <Keyword>Win32Proj</Keyword>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup>

+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</IntDir>

+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\include;$(DXSDK_DIR)\Include;$(VCInstallDir)PlatformSDK\include;$(IncludePath)</IncludePath>

+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\include;$(DXSDK_DIR)\Include;$(VCInstallDir)PlatformSDK\include;$(IncludePath)</IncludePath>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <Optimization>Disabled</Optimization>

+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <MinimalRebuild>true</MinimalRebuild>

+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+      <BrowseInformation>true</BrowseInformation>

+      <ExceptionHandling>Sync</ExceptionHandling>

+    </ClCompile>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <Optimization>MaxSpeed</Optimization>

+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+      <ExceptionHandling>Sync</ExceptionHandling>

+    </ClCompile>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ClCompile Include="Compiler.cpp" />

+    <ClCompile Include="debug.cpp" />

+    <ClCompile Include="DetectRecursion.cpp" />

+    <ClCompile Include="InfoSink.cpp" />

+    <ClCompile Include="Initialize.cpp" />

+    <ClCompile Include="InitializeDll.cpp" />

+    <ClCompile Include="Intermediate.cpp" />

+    <ClCompile Include="intermOut.cpp" />

+    <ClCompile Include="IntermTraverse.cpp" />

+    <ClCompile Include="MapLongVariableNames.cpp" />

+    <ClCompile Include="ossource_win.cpp" />

+    <ClCompile Include="parseConst.cpp" />

+    <ClCompile Include="ParseHelper.cpp" />

+    <ClCompile Include="PoolAlloc.cpp" />

+    <ClCompile Include="QualifierAlive.cpp" />

+    <ClCompile Include="RemoveTree.cpp" />

+    <ClCompile Include="ShaderLang.cpp" />

+    <ClCompile Include="SymbolTable.cpp" />

+    <ClCompile Include="util.cpp" />

+    <ClCompile Include="ValidateLimitations.cpp" />

+    <ClCompile Include="VariableInfo.cpp" />

+    <ClCompile Include="preprocessor\atom.c" />

+    <ClCompile Include="preprocessor\cpp.c" />

+    <ClCompile Include="preprocessor\cppstruct.c" />

+    <ClCompile Include="preprocessor\memory.c" />

+    <ClCompile Include="preprocessor\scanner.c" />

+    <ClCompile Include="preprocessor\symbols.c" />

+    <ClCompile Include="preprocessor\tokens.c" />

+    <ClCompile Include="glslang_lex.cpp" />

+    <ClCompile Include="glslang_tab.cpp" />

+  </ItemGroup>

+  <ItemGroup>

+    <CustomBuild Include="glslang.l">

+      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+      </Message>

+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+      </Command>

+      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>

+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Outputs)</Outputs>

+      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+      </Message>

+      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+      </Command>

+      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>

+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Outputs)</Outputs>

+    </CustomBuild>

+    <CustomBuild Include="glslang.y">

+      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+      </Message>

+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+      </Command>

+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Outputs)</Outputs>

+      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+      </Message>

+      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+      </Command>

+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Outputs)</Outputs>

+    </CustomBuild>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="BaseTypes.h" />

+    <ClInclude Include="Common.h" />

+    <ClInclude Include="ConstantUnion.h" />

+    <ClInclude Include="debug.h" />

+    <ClInclude Include="DetectRecursion.h" />

+    <ClInclude Include="InfoSink.h" />

+    <ClInclude Include="Initialize.h" />

+    <ClInclude Include="InitializeDll.h" />

+    <ClInclude Include="InitializeGlobals.h" />

+    <ClInclude Include="InitializeParseContext.h" />

+    <ClInclude Include="intermediate.h" />

+    <ClInclude Include="localintermediate.h" />

+    <ClInclude Include="MapLongVariableNames.h" />

+    <ClInclude Include="MMap.h" />

+    <ClInclude Include="osinclude.h" />

+    <ClInclude Include="ParseHelper.h" />

+    <ClInclude Include="PoolAlloc.h" />

+    <ClInclude Include="QualifierAlive.h" />

+    <ClInclude Include="RemoveTree.h" />

+    <ClInclude Include="..\..\include\GLSLANG\ResourceLimits.h" />

+    <ClInclude Include="..\..\include\GLSLANG\ShaderLang.h" />

+    <ClInclude Include="ShHandle.h" />

+    <ClInclude Include="SymbolTable.h" />

+    <ClInclude Include="Types.h" />

+    <ClInclude Include="util.h" />

+    <ClInclude Include="ValidateLimitations.h" />

+    <ClInclude Include="VariableInfo.h" />

+    <ClInclude Include="preprocessor\atom.h" />

+    <ClInclude Include="preprocessor\compile.h" />

+    <ClInclude Include="preprocessor\cpp.h" />

+    <ClInclude Include="preprocessor\memory.h" />

+    <ClInclude Include="preprocessor\parser.h" />

+    <ClInclude Include="preprocessor\preprocess.h" />

+    <ClInclude Include="preprocessor\scanner.h" />

+    <ClInclude Include="preprocessor\slglobals.h" />

+    <ClInclude Include="preprocessor\symbols.h" />

+    <ClInclude Include="preprocessor\tokens.h" />

+    <ClInclude Include="glslang_tab.h" />

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>
\ No newline at end of file
diff --git a/src/OpenGL ES 2.0/compiler/translator_common.vcxproj.filters b/src/OpenGL ES 2.0/compiler/translator_common.vcxproj.filters
new file mode 100644
index 0000000..012d17f
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/translator_common.vcxproj.filters
@@ -0,0 +1,241 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup>

+    <Filter Include="Source Files">

+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

+    </Filter>

+    <Filter Include="Source Files\preprocessor">

+      <UniqueIdentifier>{01ac9b3c-03a5-4ac1-af5a-59fcf0258595}</UniqueIdentifier>

+    </Filter>

+    <Filter Include="Source Files\generated">

+      <UniqueIdentifier>{1add4406-d193-4c4e-a8ec-c41c8d0bd499}</UniqueIdentifier>

+    </Filter>

+    <Filter Include="Header Files">

+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

+    </Filter>

+    <Filter Include="Header Files\preprocessor">

+      <UniqueIdentifier>{63184d78-5261-4b85-a56c-1c69e626cdf3}</UniqueIdentifier>

+    </Filter>

+    <Filter Include="Header Files\generated">

+      <UniqueIdentifier>{a56a1771-4799-47ac-ace9-6955dd3f055b}</UniqueIdentifier>

+    </Filter>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="Compiler.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="debug.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="InfoSink.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Initialize.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="InitializeDll.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="Intermediate.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="intermOut.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="IntermTraverse.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="MapLongVariableNames.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ossource_win.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="parseConst.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ParseHelper.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="PoolAlloc.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="QualifierAlive.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="RemoveTree.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ShaderLang.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="SymbolTable.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="util.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="ValidateLimitations.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="VariableInfo.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="preprocessor\atom.c">

+      <Filter>Source Files\preprocessor</Filter>

+    </ClCompile>

+    <ClCompile Include="preprocessor\cpp.c">

+      <Filter>Source Files\preprocessor</Filter>

+    </ClCompile>

+    <ClCompile Include="preprocessor\cppstruct.c">

+      <Filter>Source Files\preprocessor</Filter>

+    </ClCompile>

+    <ClCompile Include="preprocessor\memory.c">

+      <Filter>Source Files\preprocessor</Filter>

+    </ClCompile>

+    <ClCompile Include="preprocessor\scanner.c">

+      <Filter>Source Files\preprocessor</Filter>

+    </ClCompile>

+    <ClCompile Include="preprocessor\symbols.c">

+      <Filter>Source Files\preprocessor</Filter>

+    </ClCompile>

+    <ClCompile Include="preprocessor\tokens.c">

+      <Filter>Source Files\preprocessor</Filter>

+    </ClCompile>

+    <ClCompile Include="glslang_lex.cpp">

+      <Filter>Source Files\generated</Filter>

+    </ClCompile>

+    <ClCompile Include="glslang_tab.cpp">

+      <Filter>Source Files\generated</Filter>

+    </ClCompile>

+    <ClCompile Include="DetectRecursion.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="BaseTypes.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Common.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="ConstantUnion.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="debug.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="InfoSink.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Initialize.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="InitializeDll.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="InitializeGlobals.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="InitializeParseContext.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="intermediate.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="localintermediate.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="MapLongVariableNames.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="MMap.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="osinclude.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="ParseHelper.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="PoolAlloc.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="QualifierAlive.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="RemoveTree.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="..\..\include\GLSLANG\ResourceLimits.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="..\..\include\GLSLANG\ShaderLang.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="ShHandle.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="SymbolTable.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="Types.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="util.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="ValidateLimitations.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="VariableInfo.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="preprocessor\atom.h">

+      <Filter>Header Files\preprocessor</Filter>

+    </ClInclude>

+    <ClInclude Include="preprocessor\compile.h">

+      <Filter>Header Files\preprocessor</Filter>

+    </ClInclude>

+    <ClInclude Include="preprocessor\cpp.h">

+      <Filter>Header Files\preprocessor</Filter>

+    </ClInclude>

+    <ClInclude Include="preprocessor\memory.h">

+      <Filter>Header Files\preprocessor</Filter>

+    </ClInclude>

+    <ClInclude Include="preprocessor\parser.h">

+      <Filter>Header Files\preprocessor</Filter>

+    </ClInclude>

+    <ClInclude Include="preprocessor\preprocess.h">

+      <Filter>Header Files\preprocessor</Filter>

+    </ClInclude>

+    <ClInclude Include="preprocessor\scanner.h">

+      <Filter>Header Files\preprocessor</Filter>

+    </ClInclude>

+    <ClInclude Include="preprocessor\slglobals.h">

+      <Filter>Header Files\preprocessor</Filter>

+    </ClInclude>

+    <ClInclude Include="preprocessor\symbols.h">

+      <Filter>Header Files\preprocessor</Filter>

+    </ClInclude>

+    <ClInclude Include="preprocessor\tokens.h">

+      <Filter>Header Files\preprocessor</Filter>

+    </ClInclude>

+    <ClInclude Include="glslang_tab.h">

+      <Filter>Header Files\generated</Filter>

+    </ClInclude>

+    <ClInclude Include="DetectRecursion.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+  </ItemGroup>

+  <ItemGroup>

+    <CustomBuild Include="glslang.l">

+      <Filter>Source Files</Filter>

+    </CustomBuild>

+    <CustomBuild Include="glslang.y">

+      <Filter>Source Files</Filter>

+    </CustomBuild>

+  </ItemGroup>

+</Project>
\ No newline at end of file
diff --git a/src/OpenGL ES 2.0/compiler/translator_hlsl.vcxproj b/src/OpenGL ES 2.0/compiler/translator_hlsl.vcxproj
new file mode 100644
index 0000000..713faf3
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/translator_hlsl.vcxproj
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{5620F0E4-6C43-49BC-A178-B804E1A0C3A7}</ProjectGuid>

+    <RootNamespace>CrossCompilerHLSL</RootNamespace>

+    <Keyword>Win32Proj</Keyword>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup>

+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>

+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</OutDir>

+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</IntDir>

+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\include;C:\Program Files (x86)\Microsoft DirectX SDK (February 2010)\Include;C:\Program Files (x86)\Microsoft DirectX SDK (November 2008)\Include;C:\Program Files (x86)\Microsoft DirectX SDK (August 2009)\Include;C:\Program Files (x86)\Microsoft DirectX SDK (February 2006)\Include;$(VCInstallDir)PlatformSDK\include;$(IncludePath)</IncludePath>

+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\include;C:\Program Files (x86)\Microsoft DirectX SDK (February 2010)\Include;C:\Program Files (x86)\Microsoft DirectX SDK (November 2008)\Include;C:\Program Files (x86)\Microsoft DirectX SDK (August 2009)\Include;C:\Program Files (x86)\Microsoft DirectX SDK (February 2006)\Include;$(VCInstallDir)PlatformSDK\include;$(IncludePath)</IncludePath>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <Optimization>Disabled</Optimization>

+      <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <MinimalRebuild>true</MinimalRebuild>

+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+      <BrowseInformation>true</BrowseInformation>

+      <ExceptionHandling>Sync</ExceptionHandling>

+    </ClCompile>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <Optimization>MaxSpeed</Optimization>

+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <AdditionalIncludeDirectories>$(ProjectDir)../;$(ProjectDir)../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+      <ExceptionHandling>Sync</ExceptionHandling>

+    </ClCompile>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ClCompile Include="CodeGenHLSL.cpp" />

+    <ClCompile Include="OutputHLSL.cpp" />

+    <ClCompile Include="SearchSymbol.cpp" />

+    <ClCompile Include="TranslatorHLSL.cpp" />

+    <ClCompile Include="UnfoldSelect.cpp" />

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="OutputHLSL.h" />

+    <ClInclude Include="SearchSymbol.h" />

+    <ClInclude Include="TranslatorHLSL.h" />

+    <ClInclude Include="UnfoldSelect.h" />

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>
\ No newline at end of file
diff --git a/src/OpenGL ES 2.0/compiler/translator_hlsl.vcxproj.filters b/src/OpenGL ES 2.0/compiler/translator_hlsl.vcxproj.filters
new file mode 100644
index 0000000..1856453
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/translator_hlsl.vcxproj.filters
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup>

+    <Filter Include="Source Files">

+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

+    </Filter>

+    <Filter Include="Header Files">

+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>

+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>

+    </Filter>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="CodeGenHLSL.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="OutputHLSL.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="SearchSymbol.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="TranslatorHLSL.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="UnfoldSelect.cpp">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+  </ItemGroup>

+  <ItemGroup>

+    <ClInclude Include="OutputHLSL.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="SearchSymbol.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="TranslatorHLSL.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+    <ClInclude Include="UnfoldSelect.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

+  </ItemGroup>

+</Project>
\ No newline at end of file
diff --git a/src/OpenGL ES 2.0/compiler/util.cpp b/src/OpenGL ES 2.0/compiler/util.cpp
new file mode 100644
index 0000000..b46e4d0
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/util.cpp
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 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 <math.h>
+#include <stdlib.h>
+
+#include "util.h"
+
+#ifdef _MSC_VER
+    #include <locale.h>
+#else
+    #include <sstream>
+#endif
+
+double atof_dot(const char *str)
+{
+#ifdef _MSC_VER
+    _locale_t l = _create_locale(LC_NUMERIC, "C");
+    double result = _atof_l(str, l);
+    _free_locale(l);
+    return result;
+#else
+    double result;
+    std::istringstream s(str);
+    std::locale l("C");
+    s.imbue(l);
+    s >> result;
+    return result;
+#endif
+}
diff --git a/src/OpenGL ES 2.0/compiler/util.h b/src/OpenGL ES 2.0/compiler/util.h
new file mode 100644
index 0000000..35288b7
--- /dev/null
+++ b/src/OpenGL ES 2.0/compiler/util.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 COMPILER_UTIL_H
+#define COMPILER_UTIL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// atof_dot is like atof but forcing C locale, i.e. forcing '.' as decimal point.
+double atof_dot(const char *str);
+
+#ifdef __cplusplus
+} // end extern "C"
+#endif
+
+#endif // COMPILER_UTIL_H