diff --git a/src/lib/libc_preprocessor.js b/src/lib/libc_preprocessor.js index 9763b58d9e67c..b3bdc6172ee1e 100644 --- a/src/lib/libc_preprocessor.js +++ b/src/lib/libc_preprocessor.js @@ -247,6 +247,14 @@ addToLibrary({ var evaluated = exprTree(); stack.push(!!evaluated * stack[stack.length-1]); break; + case 'elif': + var tokens = tokenize(expandMacros(expression, 0)); + var exprTree = buildExprTree(tokens); + var evaluated = exprTree(); + // If the previous #if / #elif block was executed, output NaN so that all further #elif and #else blocks will + // short to false. + stack[stack.length-1] = !!evaluated * (stack[stack.length-1] ? NaN : 1-stack[stack.length-1]); + break; case 'ifdef': stack.push(!!defs[expression] * stack[stack.length-1]); break; case 'ifndef': stack.push(!defs[expression] * stack[stack.length-1]); break; case 'else': stack[stack.length-1] = (1-stack[stack.length-1]) * stack[stack.length-2]; break; diff --git a/test/test_c_preprocessor.c b/test/test_c_preprocessor.c index 55dea067822ce..348a99f681d58 100644 --- a/test/test_c_preprocessor.c +++ b/test/test_c_preprocessor.c @@ -191,6 +191,11 @@ EM_JS(void, test_c_preprocessor, (void), { test('#line 162 "foo.glsl"\n', '#line 162 "foo.glsl"\n'); // Test that #line directives are retained in the output + test('#define FOO 1\n#ifdef FOO\nA\n#elif defined(BAR)\nB\n#elif defined(BAZ)\nC\n#else\nD\n#endif', "A\n"); // Test #elif support, taking #ifdef path + test('#define BAR 1\n#ifdef FOO\nA\n#elif defined(BAR)\nB\n#elif defined(BAZ)\nC\n#else\nD\n#endif', "B\n"); // Test #elif support, taking first #elif path + test('#define BAZ 1\n#ifdef FOO\nA\n#elif defined(BAR)\nB\n#elif defined(BAZ)\nC\n#else\nD\n#endif', "C\n"); // Test #elif support, taking a second #elif path + test( '#ifdef FOO\nA\n#elif defined(BAR)\nB\n#elif defined(BAZ)\nC\n#else\nD\n#endif', "D\n"); // Test #elif support, taking the final #else path + if (numFailed) throw numFailed + ' tests failed!'; });