diff --git a/Install/Linux/README.txt b/Install/Linux/README.txt
index fc5651c964f292dfa18496a2d7f9ce588404d88a..06e78a89a2350aa4f648f3b03d244183d818ecc5 100644
--- a/Install/Linux/README.txt
+++ b/Install/Linux/README.txt
@@ -2,12 +2,12 @@ This directory contains linux binaries for the glslang validator.  The main
 executable is glslangValidator, which requires use of the shared object
 file libglsang.so.
 
-Installation: Executing the ./install script will copy these to /usr/local/* 
-so that they may be executed from any directory.  
-
-Alternatively, you may put them where you wish, but will then need to use 
-something like:
-
+Installation: Executing the ./install script will copy these to /usr/local/* 
+so that they may be executed from any directory.  
+
+Alternatively, you may put them where you wish, but will then need to use 
+something like:
+
     export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:<path to libglslang.so>
 
 Usage:  Execute glslangValidator with no arguments to get a usage statement.
diff --git a/Install/Windows/glslangValidator.exe b/Install/Windows/glslangValidator.exe
index 0dc01f9b7ad2c39c19448e17fe8442e9e120e179..9e288e73157a9b7c3e54dc5b2edb067bddca97e6 100644
Binary files a/Install/Windows/glslangValidator.exe and b/Install/Windows/glslangValidator.exe differ
diff --git a/README.txt b/README.txt
index e50c9026d2a7813943568135c4743a4e5714568b..3a2fe2984f3244c35a52af35c040330b6ec81a14 100644
--- a/README.txt
+++ b/README.txt
@@ -66,22 +66,54 @@ shell.
 Note: Despite appearances, the use of a DLL is currently disabled; it
 simply makes a standalone executable from a statically linked library.
 
-Basic external programmatic interface
--------------------------------------
+Programmatic Interfaces
+-----------------------
 
 Another piece of software can programmatically translate shaders to an AST 
-using the C-style ShInitialize(), ShCompile(), et. al. interface.  The main() in 
-StandAlone/StandAlone.cpp shows an example way of using these.
+using one of two different interfaces: 
+    - A new C++ class-oriented interface, or
+    - The original C functional interface
 
-The Sh*() interface takes a "compiler" call-back object, which it calls after 
-building call back that is passed the AST and can then execute a backend on it.
+The main() in StandAlone/StandAlone.cpp shows examples using both styles.
 
-The following is a simplified resulting run-time call stack:
+C++ Class Interface (new, preferred):
 
-    ShCompile(shader, compiler) -> compiler(AST) -> <back end>
+    This interface is in roughly the last 1/3 of ShaderLang.h.  It is in the 
+    glslang namespace and contains the following.
 
-In practice, ShCompile() takes shader strings, default version, and
-warning/error and other options for controling compilation.
+        const char* GetEsslVersionString();
+        const char* GetGlslVersionString();
+        bool InitializeProcess();
+        void FinalizeProcess();
+
+        class TShader
+            bool parse(...);
+            void setStrings(...);
+            const char* getInfoLog();
+
+        class TProgram
+            void addShader(...);
+            bool link(...);
+            const char* getInfoLog();
+            Reflection queries
+
+    See ShaderLang.h and the usage of it in StandAlone/StandAlone.cpp for more
+    details.
+            
+C Functional Interface (orginal):
+
+    This interface is in roughly the first 2/3 of ShaderLang.h, and referred to
+    as the Sh*() interface, as all the entry points start "Sh".
+
+    The Sh*() interface takes a "compiler" call-back object, which it calls after 
+    building call back that is passed the AST and can then execute a backend on it.
+
+    The following is a simplified resulting run-time call stack:
+
+        ShCompile(shader, compiler) -> compiler(AST) -> <back end>
+
+    In practice, ShCompile() takes shader strings, default version, and
+    warning/error and other options for controling compilation.
 
 Testing
 -------
@@ -100,7 +132,7 @@ missing, those tests just won't run.
 Basic Internal Operation
 ------------------------
 
- -  Initial lexical analysis is done be the preprocessor in
+ -  Initial lexical analysis is done by the preprocessor in
     MachineIndependent/Preprocessor, and then refined by a GLSL scanner
     in MachineIndependent/Scan.cpp.  There is currently no use of flex.
 
diff --git a/Test/baseResults/cppSimple.vert.out b/Test/baseResults/cppSimple.vert.out
index a19885cd51fedbfbe23b84985acb450fb9f56b81..2f542d6376b2178666120e4a1c6bd2d16c00d326 100644
--- a/Test/baseResults/cppSimple.vert.out
+++ b/Test/baseResults/cppSimple.vert.out
@@ -67,12 +67,15 @@ ERROR: 7:14014: '#error' : line should be 14014 , string 7
 ERROR: 12:14014: '#error' : line should be 14014 , string 12  
 ERROR: 12:14026: '#error' : line should be 14026 , string 12  
 ERROR: 12:1234: '#line' : unexpected tokens following directive 
+ERROR: 12:1237: '#line' : unexpected tokens following directive 
 ERROR: 12:20001: '#error' : line should be 20001  
 ERROR: 12:20011: '#error' : line should be 20011  
 ERROR: 12:20021: '#error' : line should be 20021  
 ERROR: 12:20046: '#define' : Macro redefined; different substitutions: SPACE_IN_MIDDLE
+ERROR: 12:20052: '#error' : good evaluation 1  
+ERROR: 12:20056: '#error' : good evaluation 2  
 ERROR: 12:10003: '' : missing #endif 
-ERROR: 72 compilation errors.  No code generated.
+ERROR: 75 compilation errors.  No code generated.
 
 
 ERROR: node is still EOpNull!
diff --git a/Test/cppSimple.vert b/Test/cppSimple.vert
index 8f1f8cb6d6e215a836422c38c316b7ee72b3c607..006d9ed7e07ccc51f0f67c4ec4b71ea7f19bc1bc 100644
--- a/Test/cppSimple.vert
+++ b/Test/cppSimple.vert
@@ -251,11 +251,18 @@ double f = f1;
 #define F2 7
 #line L1 + L2
 #error line should be 14014, string 7
-#line L1 + L2 F1 + F2
+#line L1 + L2 F1 + F2 //  antoeuh sat  comment
 #error line should be 14014, string 12
 #line L1 + L2 + F1 + F2
 #error line should be 14026, string 12
 #line 1234 F1 + F2 extra
+#define empty_extra
+#line 1235 F1 + F2 empty_extra
+#define moreEmpty empty_extra
+#line 1236 F1 + F2 moreEmpty empty_extra // okay, lots of nothin
+#line 1237 F1 + F2 moreEmpty empty_extra extra  // ERROR, 'extra'
+#line 1238 F1 + F2 moreEmpty empty_extra
+#line 1239 empty_extra F1 empty_extra + empty_extra F2 empty_extra moreEmpty empty_extra
 #line (20000)
 #error line should be 20001
 #line (20000+10)
@@ -288,6 +295,17 @@ void foo234()
 #define SPACE_IN_MIDDLE(a,b) space +in middle
 #define SPACE_IN_MIDDLE(a,b) space + in middle
 
+#define FIRSTPART 17
+#define SECONDPART + 5
+
+#if FIRSTPART SECONDPART == 22
+#error good evaluation 1
+#endif
+
+#if moreEmpty FIRSTPART moreEmpty SECONDPART moreEmpty == moreEmpty 22 moreEmpty
+#error good evaluation 2
+#endif
+
 #line 10000
 #if 1
 #else
diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h
index 5982b3fcb9086af4ff16b0a47f41064284d7b18c..f974ed04da154dccfc146191aa945c35718a33aa 100644
--- a/glslang/Include/revision.h
+++ b/glslang/Include/revision.h
@@ -9,5 +9,5 @@
 // source have to figure out how to create revision.h just to get a build
 // going.  However, if it is not updated, it can be a version behind.
 
-#define GLSLANG_REVISION "24400"
-#define GLSLANG_DATE     "2013/12/06 17:28:07"
+#define GLSLANG_REVISION "24406"
+#define GLSLANG_DATE     "2013/12/08 17:37:46"
diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp
index 730ffe96841e8675bc155a3f37893341c50e47e9..7b5a01cbdb2a9b6e9feee58bf8f8b1a72fda56c3 100644
--- a/glslang/MachineIndependent/ShaderLang.cpp
+++ b/glslang/MachineIndependent/ShaderLang.cpp
@@ -376,7 +376,7 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
     }
 
     // A metecheck on the condition the compiler itself...
-    switch(version) {
+    switch (version) {
     case 100:
     case 300:
 
diff --git a/glslang/MachineIndependent/preprocessor/Pp.cpp b/glslang/MachineIndependent/preprocessor/Pp.cpp
index 9214c7fdb93baf58d538e3a427c136226acec4be..7fa5b92960c9d1746c76abf25a75de272427e88f 100644
--- a/glslang/MachineIndependent/preprocessor/Pp.cpp
+++ b/glslang/MachineIndependent/preprocessor/Pp.cpp
@@ -473,28 +473,8 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
                 token = currentInput->scan(this, currentInput, ppToken);
             }
         } else {
-            int macroReturn = MacroExpand(ppToken->atom, ppToken, 1);
-            if (macroReturn == 0) {
-                parseContext.error(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", "");
-                err = true;
-                res = 0;
-
-                return token;
-            } else {
-                if (macroReturn == -1) {
-                    if (! shortCircuit && parseContext.profile == EEsProfile) {
-                        const char* message = "undefined macro in expression not allowed in es profile";
-                        const char* name = GetAtomString(ppToken->atom);
-                        if (parseContext.messages & EShMsgRelaxedErrors)
-                            parseContext.warn(ppToken->loc, message, "preprocessor evaluation", name);
-                        else
-                            parseContext.error(ppToken->loc, message, "preprocessor evaluation", name);
-                    }
-                }
-                token = currentInput->scan(this, currentInput, ppToken);
-
-                return eval(token, precedence, shortCircuit, res, err, ppToken);
-            }
+            token = evalToToken(token, shortCircuit, res, err, ppToken);
+            return eval(token, precedence, shortCircuit, res, err, ppToken);
         }
     } else if (token == CPP_INTCONSTANT) {
         res = ppToken->ival;
@@ -530,6 +510,10 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
             return token;
         }
     }
+
+    token = evalToToken(token, shortCircuit, res, err, ppToken);
+
+    // Perform evaluation of binary operation, if there is one, otherwise we are done.
     while (! err) {
         if (token == ')' || token == '\n') 
             break;
@@ -558,6 +542,33 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
     return token;
 }
 
+// Expand macros, skipping empty expansions, to get to the first real token in those expansions.
+int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken* ppToken)
+{
+    while (token == CPP_IDENTIFIER && ppToken->atom != definedAtom) {
+        int macroReturn = MacroExpand(ppToken->atom, ppToken, true);
+        if (macroReturn == 0) {
+            parseContext.error(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", "");
+            err = true;
+            res = 0;
+            break;
+        }
+        if (macroReturn == -1) {
+            if (! shortCircuit && parseContext.profile == EEsProfile) {
+                const char* message = "undefined macro in expression not allowed in es profile";
+                const char* name = GetAtomString(ppToken->atom);
+                if (parseContext.messages & EShMsgRelaxedErrors)
+                    parseContext.warn(ppToken->loc, message, "preprocessor evaluation", name);
+                else
+                    parseContext.error(ppToken->loc, message, "preprocessor evaluation", name);
+            }
+        }
+        token = currentInput->scan(this, currentInput, ppToken);
+    }
+
+    return token;
+}
+
 // Handle #if
 int TPpContext::CPPif(TPpToken* ppToken) 
 {
@@ -612,6 +623,10 @@ int TPpContext::CPPifdef(int defined, TPpToken* ppToken)
 // Handle #line
 int TPpContext::CPPline(TPpToken* ppToken) 
 {
+    // "#line must have, after macro substitution, one of the following forms:
+    // "#line line
+    // "#line line source-string-number"
+
     int token = currentInput->scan(this, currentInput, ppToken);
     if (token == '\n') {
         parseContext.error(ppToken->loc, "must by followed by an integral literal", "#line", "");
@@ -633,6 +648,7 @@ int TPpContext::CPPline(TPpToken* ppToken)
                 parseContext.setCurrentString(fileRes);
         }
     }
+
     token = extraTokenCheck(lineAtom, ppToken, token);
 
     return token;
@@ -886,7 +902,7 @@ TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream *a, TPpToken* p
     PushEofSrc();
     ReadFromTokenStream(a, 0, 0);
     while ((token = currentInput->scan(this, currentInput, ppToken)) > 0) {
-        if (token == CPP_IDENTIFIER && MacroExpand(ppToken->atom, ppToken, 0) == 1)
+        if (token == CPP_IDENTIFIER && MacroExpand(ppToken->atom, ppToken, false) == 1)
             continue;
         RecordToken(n, token, ppToken);
     }
@@ -952,13 +968,13 @@ int TPpContext::zero_scan(TPpContext* pp, InputSrc *inInput, TPpToken* ppToken)
 
 /*
 ** Check an identifier (atom) to see if it is a macro that should be expanded.
-** If it is, push an InputSrc that will produce the appropriate expansion
+** If it is, and defined, push an InputSrc that will produce the appropriate expansion
 ** and return 1.
-** If it is, but undefined, it should expand to 0, push an InputSrc that will 
+** If it is, but undefined, and expandUndef is requested, push an InputSrc that will 
 ** expand to 0 and return -1.
 ** Otherwise, return 0.
 */
-int TPpContext::MacroExpand(int atom, TPpToken* ppToken, int expandUndef)
+int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef)
 {
     Symbol *sym = LookUpSymbol(atom);
     MacroInputSrc *in;
diff --git a/glslang/MachineIndependent/preprocessor/PpContext.h b/glslang/MachineIndependent/preprocessor/PpContext.h
index 4fc2c87fb9eb7ee4a7fc23278846902e3da3ce45..81dbe9c032c8c707d99e496a34875d9ae27366b7 100644
--- a/glslang/MachineIndependent/preprocessor/PpContext.h
+++ b/glslang/MachineIndependent/preprocessor/PpContext.h
@@ -247,6 +247,7 @@ protected:
     int CPPelse(int matchelse, TPpToken * ppToken);
     int extraTokenCheck(int atom, TPpToken* ppToken, int token);
     int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
+    int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
     int CPPif (TPpToken * ppToken); 
     int CPPifdef(int defined, TPpToken * ppToken);
     int CPPline(TPpToken * ppToken); 
@@ -260,7 +261,7 @@ protected:
     TokenStream* PrescanMacroArg(TokenStream *a, TPpToken * ppToken);
     static int macro_scan(TPpContext* pp, InputSrc *inInput, TPpToken * ppToken); 
     static int zero_scan(TPpContext* pp, InputSrc *inInput, TPpToken * ppToken); 
-    int MacroExpand(int atom, TPpToken* ppToken, int expandUndef);
+    int MacroExpand(int atom, TPpToken* ppToken, bool expandUndef);
 
     //
     // from PpSymbols.cpp
diff --git a/glslang/MachineIndependent/preprocessor/PpScanner.cpp b/glslang/MachineIndependent/preprocessor/PpScanner.cpp
index d29ac10e441ba8846f9de8bb725035968c5e9739..1add7a2732f2304cc6d11556e4530c9258aa013f 100644
--- a/glslang/MachineIndependent/preprocessor/PpScanner.cpp
+++ b/glslang/MachineIndependent/preprocessor/PpScanner.cpp
@@ -744,7 +744,7 @@ const char* TPpContext::tokenize(TPpToken* ppToken)
             continue;
 
         // expand macros
-        if (token == CPP_IDENTIFIER && MacroExpand(ppToken->atom, ppToken, 0) == 1)
+        if (token == CPP_IDENTIFIER && MacroExpand(ppToken->atom, ppToken, false) == 1)
             continue;
 
         if (token == CPP_IDENTIFIER)