diff options
Diffstat (limited to 'chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor')
9 files changed, 3559 insertions, 0 deletions
diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/Pp.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/Pp.cpp new file mode 100644 index 00000000000..35097588c43 --- /dev/null +++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -0,0 +1,1151 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//Copyright (C) 2013 LunarG, Inc. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +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 +// + +#define _CRT_SECURE_NO_WARNINGS + +#include <stdarg.h> +#include <stdio.h> +#include <sstream> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "PpContext.h" +#include "PpTokens.h" + +namespace glslang { + +int TPpContext::InitCPP() +{ + pool = mem_CreatePool(0, 0); + + return 1; +} + +// Handle #define +int TPpContext::CPPdefine(TPpToken* ppToken) +{ + MacroSymbol mac; + Symbol *symb; + + // get macro name + int token = scanToken(ppToken); + if (token != PpAtomIdentifier) { + parseContext.ppError(ppToken->loc, "must be followed by macro name", "#define", ""); + return token; + } + if (ppToken->loc.string >= 0) { + // We are in user code; check for reserved name use: + parseContext.reservedPpErrorCheck(ppToken->loc, ppToken->name, "#define"); + } + + // save the original atom + const int defAtom = ppToken->atom; + + // gather parameters to the macro, between (...) + token = scanToken(ppToken); + if (token == '(' && ! ppToken->space) { + int argc = 0; + int args[maxMacroArgs]; + do { + token = scanToken(ppToken); + if (argc == 0 && token == ')') + break; + if (token != PpAtomIdentifier) { + parseContext.ppError(ppToken->loc, "bad argument", "#define", ""); + + return token; + } + // check for duplication of parameter name + bool duplicate = false; + for (int a = 0; a < argc; ++a) { + if (args[a] == ppToken->atom) { + parseContext.ppError(ppToken->loc, "duplicate macro parameter", "#define", ""); + duplicate = true; + break; + } + } + if (! duplicate) { + if (argc < maxMacroArgs) + args[argc++] = ppToken->atom; + else + parseContext.ppError(ppToken->loc, "too many macro parameters", "#define", ""); + } + token = scanToken(ppToken); + } while (token == ','); + if (token != ')') { + parseContext.ppError(ppToken->loc, "missing parenthesis", "#define", ""); + + return token; + } + mac.argc = argc; + mac.args = (int*)mem_Alloc(pool, argc * sizeof(int)); + memcpy(mac.args, args, argc * sizeof(int)); + token = scanToken(ppToken); + } + + // record the definition of the macro + TSourceLoc defineLoc = ppToken->loc; // because ppToken is going to go to the next line before we report errors + mac.body = new TokenStream; + while (token != '\n' && token != EndOfInput) { + RecordToken(mac.body, token, ppToken); + token = scanToken(ppToken); + if (token != '\n' && ppToken->space) + RecordToken(mac.body, ' ', ppToken); + } + + // check for duplicate definition + symb = LookUpSymbol(defAtom); + if (symb) { + if (! symb->mac.undef) { + // Already defined -- need to make sure they are identical: + // "Two replacement lists are identical if and only if the preprocessing tokens in both have the same number, + // ordering, spelling, and white-space separation, where all white-space separations are considered identical." + if (symb->mac.argc != mac.argc) + parseContext.ppError(defineLoc, "Macro redefined; different number of arguments:", "#define", GetAtomString(defAtom)); + else { + for (int argc = 0; argc < mac.argc; argc++) { + if (symb->mac.args[argc] != mac.args[argc]) + parseContext.ppError(defineLoc, "Macro redefined; different argument names:", "#define", GetAtomString(defAtom)); + } + RewindTokenStream(symb->mac.body); + RewindTokenStream(mac.body); + int newToken; + do { + int oldToken; + TPpToken oldPpToken; + TPpToken newPpToken; + oldToken = ReadToken(symb->mac.body, &oldPpToken); + newToken = ReadToken(mac.body, &newPpToken); + if (oldToken != newToken || oldPpToken != newPpToken) { + parseContext.ppError(defineLoc, "Macro redefined; different substitutions:", "#define", GetAtomString(defAtom)); + break; + } + } while (newToken > 0); + } + } + } else + symb = AddSymbol(defAtom); + + delete symb->mac.body; + symb->mac = mac; + + return '\n'; +} + +// Handle #undef +int TPpContext::CPPundef(TPpToken* ppToken) +{ + int token = scanToken(ppToken); + Symbol *symb; + if (token != PpAtomIdentifier) { + parseContext.ppError(ppToken->loc, "must be followed by macro name", "#undef", ""); + + return token; + } + + parseContext.reservedPpErrorCheck(ppToken->loc, ppToken->name, "#undef"); + + symb = LookUpSymbol(ppToken->atom); + if (symb) { + symb->mac.undef = 1; + } + token = scanToken(ppToken); + if (token != '\n') + parseContext.ppError(ppToken->loc, "can only be followed by a single macro name", "#undef", ""); + + return token; +} + +// Handle #else +/* Skip forward to appropriate spot. This is used both +** to skip to a #endif after seeing an #else, AND to skip to a #else, +** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false. +*/ +int TPpContext::CPPelse(int matchelse, TPpToken* ppToken) +{ + int atom; + int depth = 0; + int token = scanToken(ppToken); + + while (token != EndOfInput) { + if (token != '#') { + while (token != '\n' && token != EndOfInput) + token = scanToken(ppToken); + + if (token == EndOfInput) + return token; + + token = scanToken(ppToken); + continue; + } + + if ((token = scanToken(ppToken)) != PpAtomIdentifier) + continue; + + atom = ppToken->atom; + if (atom == PpAtomIf || atom == PpAtomIfdef || atom == PpAtomIfndef) { + depth++; + ifdepth++; + elsetracker++; + } else if (atom == PpAtomEndif) { + token = extraTokenCheck(atom, ppToken, scanToken(ppToken)); + elseSeen[elsetracker] = false; + --elsetracker; + if (depth == 0) { + // found the #endif we are looking for + if (ifdepth) + --ifdepth; + break; + } + --depth; + --ifdepth; + } else if (matchelse && depth == 0) { + if (atom == PpAtomElse) { + elseSeen[elsetracker] = true; + token = extraTokenCheck(atom, ppToken, scanToken(ppToken)); + // found the #else we are looking for + break; + } else if (atom == PpAtomElif) { + if (elseSeen[elsetracker]) + parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", ""); + /* we decrement ifdepth here, because CPPif will increment + * it and we really want to leave it alone */ + if (ifdepth) { + --ifdepth; + elseSeen[elsetracker] = false; + --elsetracker; + } + + return CPPif(ppToken); + } + } else if (atom == PpAtomElse) { + if (elseSeen[elsetracker]) + parseContext.ppError(ppToken->loc, "#else after #else", "#else", ""); + else + elseSeen[elsetracker] = true; + token = extraTokenCheck(atom, ppToken, scanToken(ppToken)); + } else if (atom == PpAtomElif) { + if (elseSeen[elsetracker]) + parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", ""); + } + } + + return token; +} + +// Call when there should be no more tokens left on a line. +int TPpContext::extraTokenCheck(int atom, TPpToken* ppToken, int token) +{ + if (token != '\n' && token != EndOfInput) { + static const char* message = "unexpected tokens following directive"; + + const char* label; + if (atom == PpAtomElse) + label = "#else"; + else if (atom == PpAtomElif) + label = "#elif"; + else if (atom == PpAtomEndif) + label = "#endif"; + else if (atom == PpAtomIf) + label = "#if"; + else if (atom == PpAtomLine) + label = "#line"; + else + label = ""; + + if (parseContext.relaxedErrors()) + parseContext.ppWarn(ppToken->loc, message, label, ""); + else + parseContext.ppError(ppToken->loc, message, label, ""); + + while (token != '\n' && token != EndOfInput) + token = scanToken(ppToken); + } + + return token; +} + +enum eval_prec { + MIN_PRECEDENCE, + COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY, + MAX_PRECEDENCE +}; + +namespace { + + int op_logor(int a, int b) { return a || b; } + int op_logand(int a, int b) { return a && b; } + int op_or(int a, int b) { return a | b; } + int op_xor(int a, int b) { return a ^ b; } + int op_and(int a, int b) { return a & b; } + int op_eq(int a, int b) { return a == b; } + int op_ne(int a, int b) { return a != b; } + int op_ge(int a, int b) { return a >= b; } + int op_le(int a, int b) { return a <= b; } + int op_gt(int a, int b) { return a > b; } + int op_lt(int a, int b) { return a < b; } + int op_shl(int a, int b) { return a << b; } + int op_shr(int a, int b) { return a >> b; } + int op_add(int a, int b) { return a + b; } + int op_sub(int a, int b) { return a - b; } + int op_mul(int a, int b) { return a * b; } + int op_div(int a, int b) { return a / b; } + int op_mod(int a, int b) { return a % b; } + int op_pos(int a) { return a; } + int op_neg(int a) { return -a; } + int op_cmpl(int a) { return ~a; } + int op_not(int a) { return !a; } + +}; + +struct TBinop { + int token, precedence, (*op)(int, int); +} binop[] = { + { PpAtomOr, LOGOR, op_logor }, + { PpAtomAnd, LOGAND, op_logand }, + { '|', OR, op_or }, + { '^', XOR, op_xor }, + { '&', AND, op_and }, + { PpAtomEQ, EQUAL, op_eq }, + { PpAtomNE, EQUAL, op_ne }, + { '>', RELATION, op_gt }, + { PpAtomGE, RELATION, op_ge }, + { '<', RELATION, op_lt }, + { PpAtomLE, RELATION, op_le }, + { PpAtomLeft, SHIFT, op_shl }, + { PpAtomRight, SHIFT, op_shr }, + { '+', ADD, op_add }, + { '-', ADD, op_sub }, + { '*', MUL, op_mul }, + { '/', MUL, op_div }, + { '%', MUL, op_mod }, +}; + +struct TUnop { + int token, (*op)(int); +} unop[] = { + { '+', op_pos }, + { '-', op_neg }, + { '~', op_cmpl }, + { '!', op_not }, +}; + +#define NUM_ELEMENTS(A) (sizeof(A) / sizeof(A[0])) + +int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken* ppToken) +{ + TSourceLoc loc = ppToken->loc; // because we sometimes read the newline before reporting the error + if (token == PpAtomIdentifier) { + if (ppToken->atom == PpAtomDefined) { + bool needclose = 0; + token = scanToken(ppToken); + if (token == '(') { + needclose = true; + token = scanToken(ppToken); + } + if (token != PpAtomIdentifier) { + parseContext.ppError(loc, "incorrect directive, expected identifier", "preprocessor evaluation", ""); + err = true; + res = 0; + + return token; + } + Symbol* s = LookUpSymbol(ppToken->atom); + res = s ? ! s->mac.undef : 0; + token = scanToken(ppToken); + if (needclose) { + if (token != ')') { + parseContext.ppError(loc, "expected ')'", "preprocessor evaluation", ""); + err = true; + res = 0; + + return token; + } + token = scanToken(ppToken); + } + } else { + token = evalToToken(token, shortCircuit, res, err, ppToken); + return eval(token, precedence, shortCircuit, res, err, ppToken); + } + } else if (token == PpAtomConstInt) { + res = ppToken->ival; + token = scanToken(ppToken); + } else if (token == '(') { + token = scanToken(ppToken); + token = eval(token, MIN_PRECEDENCE, shortCircuit, res, err, ppToken); + if (! err) { + if (token != ')') { + parseContext.ppError(loc, "expected ')'", "preprocessor evaluation", ""); + err = true; + res = 0; + + return token; + } + token = scanToken(ppToken); + } + } else { + int op = NUM_ELEMENTS(unop) - 1; + for (; op >= 0; op--) { + if (unop[op].token == token) + break; + } + if (op >= 0) { + token = scanToken(ppToken); + token = eval(token, UNARY, shortCircuit, res, err, ppToken); + res = unop[op].op(res); + } else { + parseContext.ppError(loc, "bad expression", "preprocessor evaluation", ""); + err = true; + res = 0; + + 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; + int op; + for (op = NUM_ELEMENTS(binop) - 1; op >= 0; op--) { + if (binop[op].token == token) + break; + } + if (op < 0 || binop[op].precedence <= precedence) + break; + int leftSide = res; + + // Setup short-circuiting, needed for ES, unless already in a short circuit. + // (Once in a short-circuit, can't turn off again, until that whole subexpression is done. + if (! shortCircuit) { + if ((token == PpAtomOr && leftSide == 1) || + (token == PpAtomAnd && leftSide == 0)) + shortCircuit = true; + } + + token = scanToken(ppToken); + token = eval(token, binop[op].precedence, shortCircuit, res, err, ppToken); + + if (binop[op].op == op_div || binop[op].op == op_mod) { + if (res == 0) { + parseContext.ppError(loc, "division by 0", "preprocessor evaluation", ""); + res = 1; + } + } + res = binop[op].op(leftSide, res); + } + + 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 == PpAtomIdentifier && ppToken->atom != PpAtomDefined) { + int macroReturn = MacroExpand(ppToken->atom, ppToken, true, false); + if (macroReturn == 0) { + parseContext.ppError(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", ""); + err = true; + res = 0; + token = scanToken(ppToken); + break; + } + if (macroReturn == -1) { + if (! shortCircuit && parseContext.profile == EEsProfile) { + const char* message = "undefined macro in expression not allowed in es profile"; + if (parseContext.relaxedErrors()) + parseContext.ppWarn(ppToken->loc, message, "preprocessor evaluation", ppToken->name); + else + parseContext.ppError(ppToken->loc, message, "preprocessor evaluation", ppToken->name); + } + } + token = scanToken(ppToken); + } + + return token; +} + +// Handle #if +int TPpContext::CPPif(TPpToken* ppToken) +{ + int token = scanToken(ppToken); + elsetracker++; + ifdepth++; + if (ifdepth > maxIfNesting) { + parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if", ""); + return 0; + } + int res = 0; + bool err = false; + token = eval(token, MIN_PRECEDENCE, false, res, err, ppToken); + token = extraTokenCheck(PpAtomIf, ppToken, token); + if (!res && !err) + token = CPPelse(1, ppToken); + + return token; +} + +// Handle #ifdef +int TPpContext::CPPifdef(int defined, TPpToken* ppToken) +{ + int token = scanToken(ppToken); + int name = ppToken->atom; + if (++ifdepth > maxIfNesting) { + parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#ifdef", ""); + return 0; + } + elsetracker++; + if (token != PpAtomIdentifier) { + if (defined) + parseContext.ppError(ppToken->loc, "must be followed by macro name", "#ifdef", ""); + else + parseContext.ppError(ppToken->loc, "must be followed by macro name", "#ifndef", ""); + } else { + Symbol *s = LookUpSymbol(name); + token = scanToken(ppToken); + if (token != '\n') { + parseContext.ppError(ppToken->loc, "unexpected tokens following #ifdef directive - expected a newline", "#ifdef", ""); + while (token != '\n' && token != EndOfInput) + token = scanToken(ppToken); + } + if (((s && !s->mac.undef) ? 1 : 0) != defined) + token = CPPelse(1, ppToken); + } + + return token; +} + +// Handle #include +int TPpContext::CPPinclude(TPpToken* ppToken) +{ + const TSourceLoc directiveLoc = ppToken->loc; + int token = scanToken(ppToken); + if (token != PpAtomConstString) { + // TODO: handle angle brackets. + parseContext.ppError(directiveLoc, "must be followed by a file designation", "#include", ""); + } else { + // Make a copy of the name because it will be overwritten by the next token scan. + const std::string filename = ppToken->name; + token = scanToken(ppToken); + if (token != '\n' && token != EndOfInput) { + parseContext.ppError(ppToken->loc, "extra content after file designation", "#include", ""); + } else { + TShader::Includer::IncludeResult* res = includer.include(filename.c_str(), TShader::Includer::EIncludeRelative, currentSourceFile.c_str(), includeStack.size() + 1); + if (res && !res->file_name.empty()) { + if (res->file_data && res->file_length) { + const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine(); + std::ostringstream prologue; + std::ostringstream epilogue; + prologue << "#line " << forNextLine << " " << "\"" << res->file_name << "\"\n"; + epilogue << (res->file_data[res->file_length - 1] == '\n'? "" : "\n") << "#line " << directiveLoc.line + forNextLine << " " << directiveLoc.getStringNameOrNum() << "\n"; + pushInput(new TokenizableIncludeFile(directiveLoc, prologue.str(), res, epilogue.str(), this)); + } + // At EOF, there's no "current" location anymore. + if (token != EndOfInput) parseContext.setCurrentColumn(0); + // Don't accidentally return EndOfInput, which will end all preprocessing. + return '\n'; + } else { + std::string message = + res ? std::string(res->file_data, res->file_length) + : std::string("Could not process include directive"); + parseContext.ppError(directiveLoc, message.c_str(), "#include", ""); + if (res) { + includer.releaseInclude(res); + } + } + } + } + return token; +} + +// 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 = scanToken(ppToken); + const TSourceLoc directiveLoc = ppToken->loc; + if (token == '\n') { + parseContext.ppError(ppToken->loc, "must by followed by an integral literal", "#line", ""); + return token; + } + + int lineRes = 0; // Line number after macro expansion. + int lineToken = 0; + bool hasFile = false; + int fileRes = 0; // Source file number after macro expansion. + const char* sourceName = nullptr; // Optional source file name. + bool lineErr = false; + bool fileErr = false; + token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken); + if (! lineErr) { + lineToken = lineRes; + if (token == '\n') + ++lineRes; + + if (parseContext.lineDirectiveShouldSetNextLine()) + --lineRes; + parseContext.setCurrentLine(lineRes); + + if (token != '\n') { + if (token == PpAtomConstString) { + parseContext.ppRequireExtensions(directiveLoc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based #line"); + // We need to save a copy of the string instead of pointing + // to the name field of the token since the name field + // will likely be overwritten by the next token scan. + sourceName = GetAtomString(LookUpAddString(ppToken->name)); + parseContext.setCurrentSourceName(sourceName); + hasFile = true; + token = scanToken(ppToken); + } else { + token = eval(token, MIN_PRECEDENCE, false, fileRes, fileErr, ppToken); + if (! fileErr) { + parseContext.setCurrentString(fileRes); + hasFile = true; + } + } + } + } + if (!fileErr && !lineErr) { + parseContext.notifyLineDirective(directiveLoc.line, lineToken, hasFile, fileRes, sourceName); + } + token = extraTokenCheck(PpAtomLine, ppToken, token); + + return token; +} + +// Handle #error +int TPpContext::CPPerror(TPpToken* ppToken) +{ + int token = scanToken(ppToken); + std::string message; + TSourceLoc loc = ppToken->loc; + + while (token != '\n' && token != EndOfInput) { + if (token == PpAtomConstInt || token == PpAtomConstUint || + token == PpAtomConstInt64 || token == PpAtomConstUint64 || + token == PpAtomConstFloat || token == PpAtomConstDouble) { + message.append(ppToken->name); + } else if (token == PpAtomIdentifier || token == PpAtomConstString) { + message.append(ppToken->name); + } else { + message.append(GetAtomString(token)); + } + message.append(" "); + token = scanToken(ppToken); + } + parseContext.notifyErrorDirective(loc.line, message.c_str()); + //store this msg into the shader's information log..set the Compile Error flag!!!! + parseContext.ppError(loc, message.c_str(), "#error", ""); + + return '\n'; +} + +// Handle #pragma +int TPpContext::CPPpragma(TPpToken* ppToken) +{ + char SrcStrName[2]; + TVector<TString> tokens; + + TSourceLoc loc = ppToken->loc; // because we go to the next line before processing + int token = scanToken(ppToken); + while (token != '\n' && token != EndOfInput) { + switch (token) { + case PpAtomIdentifier: + case PpAtomConstInt: + case PpAtomConstUint: + case PpAtomConstInt64: + case PpAtomConstUint64: + case PpAtomConstFloat: + case PpAtomConstDouble: + tokens.push_back(ppToken->name); + break; + default: + SrcStrName[0] = (char)token; + SrcStrName[1] = '\0'; + tokens.push_back(SrcStrName); + } + token = scanToken(ppToken); + } + + if (token == EndOfInput) + parseContext.ppError(loc, "directive must end with a newline", "#pragma", ""); + else + parseContext.handlePragma(loc, tokens); + + return token; +} + +// #version: This is just for error checking: the version and profile are decided before preprocessing starts +int TPpContext::CPPversion(TPpToken* ppToken) +{ + int token = scanToken(ppToken); + + if (errorOnVersion || versionSeen) + parseContext.ppError(ppToken->loc, "must occur first in shader", "#version", ""); + versionSeen = true; + + if (token == '\n') { + parseContext.ppError(ppToken->loc, "must be followed by version number", "#version", ""); + + return token; + } + + if (token != PpAtomConstInt) + parseContext.ppError(ppToken->loc, "must be followed by version number", "#version", ""); + + ppToken->ival = atoi(ppToken->name); + int versionNumber = ppToken->ival; + int line = ppToken->loc.line; + token = scanToken(ppToken); + + if (token == '\n') { + parseContext.notifyVersion(line, versionNumber, nullptr); + return token; + } else { + if (ppToken->atom != PpAtomCore && + ppToken->atom != PpAtomCompatibility && + ppToken->atom != PpAtomEs) + parseContext.ppError(ppToken->loc, "bad profile name; use es, core, or compatibility", "#version", ""); + parseContext.notifyVersion(line, versionNumber, ppToken->name); + token = scanToken(ppToken); + + if (token == '\n') + return token; + else + parseContext.ppError(ppToken->loc, "bad tokens following profile -- expected newline", "#version", ""); + } + + return token; +} + +// Handle #extension +int TPpContext::CPPextension(TPpToken* ppToken) +{ + int line = ppToken->loc.line; + int token = scanToken(ppToken); + char extensionName[MaxTokenLength + 1]; + + if (token=='\n') { + parseContext.ppError(ppToken->loc, "extension name not specified", "#extension", ""); + return token; + } + + if (token != PpAtomIdentifier) + parseContext.ppError(ppToken->loc, "extension name expected", "#extension", ""); + + assert(strlen(ppToken->name) <= MaxTokenLength); + strcpy(extensionName, ppToken->name); + + token = scanToken(ppToken); + if (token != ':') { + parseContext.ppError(ppToken->loc, "':' missing after extension name", "#extension", ""); + return token; + } + + token = scanToken(ppToken); + if (token != PpAtomIdentifier) { + parseContext.ppError(ppToken->loc, "behavior for extension not specified", "#extension", ""); + return token; + } + + parseContext.updateExtensionBehavior(line, extensionName, ppToken->name); + parseContext.notifyExtensionDirective(line, extensionName, ppToken->name); + + token = scanToken(ppToken); + if (token == '\n') + return token; + else + parseContext.ppError(ppToken->loc, "extra tokens -- expected newline", "#extension",""); + + return token; +} + +int TPpContext::readCPPline(TPpToken* ppToken) +{ + int token = scanToken(ppToken); + + if (token == PpAtomIdentifier) { + switch (ppToken->atom) { + case PpAtomDefine: + token = CPPdefine(ppToken); + break; + case PpAtomElse: + if (elsetracker[elseSeen]) + parseContext.ppError(ppToken->loc, "#else after #else", "#else", ""); + elsetracker[elseSeen] = true; + if (! ifdepth) + parseContext.ppError(ppToken->loc, "mismatched statements", "#else", ""); + token = extraTokenCheck(PpAtomElse, ppToken, scanToken(ppToken)); + token = CPPelse(0, ppToken); + break; + case PpAtomElif: + if (! ifdepth) + parseContext.ppError(ppToken->loc, "mismatched statements", "#elif", ""); + if (elseSeen[elsetracker]) + parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", ""); + // this token is really a dont care, but we still need to eat the tokens + token = scanToken(ppToken); + while (token != '\n' && token != EndOfInput) + token = scanToken(ppToken); + token = CPPelse(0, ppToken); + break; + case PpAtomEndif: + if (! ifdepth) + parseContext.ppError(ppToken->loc, "mismatched statements", "#endif", ""); + else { + elseSeen[elsetracker] = false; + --elsetracker; + --ifdepth; + } + token = extraTokenCheck(PpAtomEndif, ppToken, scanToken(ppToken)); + break; + case PpAtomIf: + token = CPPif(ppToken); + break; + case PpAtomIfdef: + token = CPPifdef(1, ppToken); + break; + case PpAtomIfndef: + token = CPPifdef(0, ppToken); + break; + case PpAtomInclude: + parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_include_directive, "#include"); + token = CPPinclude(ppToken); + break; + case PpAtomLine: + token = CPPline(ppToken); + break; + case PpAtomPragma: + token = CPPpragma(ppToken); + break; + case PpAtomUndef: + token = CPPundef(ppToken); + break; + case PpAtomError: + token = CPPerror(ppToken); + break; + case PpAtomVersion: + token = CPPversion(ppToken); + break; + case PpAtomExtension: + token = CPPextension(ppToken); + break; + default: + parseContext.ppError(ppToken->loc, "invalid directive:", "#", ppToken->name); + break; + } + } else if (token != '\n' && token != EndOfInput) + parseContext.ppError(ppToken->loc, "invalid directive", "#", ""); + + while (token != '\n' && token != EndOfInput) + token = scanToken(ppToken); + + return token; +} + +TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream* a, TPpToken* ppToken, bool newLineOkay) +{ + int token; + TokenStream *n; + RewindTokenStream(a); + do { + token = ReadToken(a, ppToken); + if (token == PpAtomIdentifier && LookUpSymbol(ppToken->atom)) + break; + } while (token != EndOfInput); + + if (token == EndOfInput) + return a; + + n = new TokenStream; + pushInput(new tMarkerInput(this)); + pushTokenStreamInput(a); + while ((token = scanToken(ppToken)) != tMarkerInput::marker) { + if (token == PpAtomIdentifier && MacroExpand(ppToken->atom, ppToken, false, newLineOkay) != 0) + continue; + RecordToken(n, token, ppToken); + } + popInput(); + delete a; + + return n; +} + +// +// Return the next token for a macro expansion, handling macro args. +// +int TPpContext::tMacroInput::scan(TPpToken* ppToken) +{ + int token; + do { + token = pp->ReadToken(mac->body, ppToken); + } while (token == ' '); // handle white space in macro + + // TODO: preprocessor: properly handle whitespace (or lack of it) between tokens when expanding + if (token == PpAtomIdentifier) { + int i; + for (i = mac->argc - 1; i >= 0; i--) + if (mac->args[i] == ppToken->atom) + break; + if (i >= 0) { + pp->pushTokenStreamInput(args[i]); + + return pp->scanToken(ppToken); + } + } + + if (token == EndOfInput) + mac->busy = 0; + + return token; +} + +// return a textual zero, for scanning a macro that was never defined +int TPpContext::tZeroInput::scan(TPpToken* ppToken) +{ + if (done) + return EndOfInput; + + strcpy(ppToken->name, "0"); + ppToken->ival = 0; + ppToken->space = false; + done = true; + + return PpAtomConstInt; +} + +// +// Check an identifier (atom) to see if it is a macro that should be expanded. +// If it is, and defined, push a tInput that will produce the appropriate expansion +// and return 1. +// If it is, but undefined, and expandUndef is requested, push a tInput that will +// expand to 0 and return -1. +// Otherwise, return 0 to indicate no expansion, which is not necessarily an error. +// +int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool newLineOkay) +{ + ppToken->space = false; + switch (atom) { + case PpAtomLineMacro: + ppToken->ival = parseContext.getCurrentLoc().line; + snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival); + UngetToken(PpAtomConstInt, ppToken); + return 1; + + case PpAtomFileMacro: { + if (parseContext.getCurrentLoc().name) + parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based __FILE__"); + ppToken->ival = parseContext.getCurrentLoc().string; + snprintf(ppToken->name, sizeof(ppToken->name), "%s", ppToken->loc.getStringNameOrNum().c_str()); + UngetToken(PpAtomConstInt, ppToken); + return 1; + } + + case PpAtomVersionMacro: + ppToken->ival = parseContext.version; + snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival); + UngetToken(PpAtomConstInt, ppToken); + return 1; + + default: + break; + } + + Symbol *sym = LookUpSymbol(atom); + int token; + int depth = 0; + + // no recursive expansions + if (sym && sym->mac.busy) + return 0; + + // not expanding undefined macros + if ((! sym || sym->mac.undef) && ! expandUndef) + return 0; + + // 0 is the value of an undefined macro + if ((! sym || sym->mac.undef) && expandUndef) { + pushInput(new tZeroInput(this)); + return -1; + } + + tMacroInput *in = new tMacroInput(this); + + TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error + in->mac = &sym->mac; + if (sym->mac.args) { + token = scanToken(ppToken); + if (newLineOkay) { + while (token == '\n') + token = scanToken(ppToken); + } + if (token != '(') { + parseContext.ppError(loc, "expected '(' following", "macro expansion", GetAtomString(atom)); + UngetToken(token, ppToken); + ppToken->atom = atom; + + delete in; + return 0; + } + in->args.resize(in->mac->argc); + for (int i = 0; i < in->mac->argc; i++) + in->args[i] = new TokenStream; + int arg = 0; + bool tokenRecorded = false; + do { + depth = 0; + while (1) { + token = scanToken(ppToken); + if (token == EndOfInput) { + parseContext.ppError(loc, "End of input in macro", "macro expansion", GetAtomString(atom)); + delete in; + return 0; + } + if (token == '\n') { + if (! newLineOkay) { + parseContext.ppError(loc, "End of line in macro substitution:", "macro expansion", GetAtomString(atom)); + delete in; + return 0; + } + continue; + } + if (token == '#') { + parseContext.ppError(ppToken->loc, "unexpected '#'", "macro expansion", GetAtomString(atom)); + delete in; + return 0; + } + if (in->mac->argc == 0 && token != ')') + break; + if (depth == 0 && (token == ',' || token == ')')) + break; + if (token == '(') + depth++; + if (token == ')') + depth--; + RecordToken(in->args[arg], token, ppToken); + tokenRecorded = true; + } + if (token == ')') { + if (in->mac->argc == 1 && tokenRecorded == 0) + break; + arg++; + break; + } + arg++; + } while (arg < in->mac->argc); + + if (arg < in->mac->argc) + parseContext.ppError(loc, "Too few args in Macro", "macro expansion", GetAtomString(atom)); + else if (token != ')') { + depth=0; + while (token != EndOfInput && (depth > 0 || token != ')')) { + if (token == ')') + depth--; + token = scanToken(ppToken); + if (token == '(') + depth++; + } + + if (token == EndOfInput) { + parseContext.ppError(loc, "End of input in macro", "macro expansion", GetAtomString(atom)); + delete in; + return 0; + } + parseContext.ppError(loc, "Too many args in macro", "macro expansion", GetAtomString(atom)); + } + for (int i = 0; i < in->mac->argc; i++) + in->args[i] = PrescanMacroArg(in->args[i], ppToken, newLineOkay); + } + + pushInput(in); + sym->mac.busy = 1; + RewindTokenStream(sym->mac.body); + + return 1; +} + +} // end namespace glslang diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpAtom.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpAtom.cpp new file mode 100644 index 00000000000..763b6b4e67b --- /dev/null +++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpAtom.cpp @@ -0,0 +1,192 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//Copyright (C) 2013 LunarG, Inc. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +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 +// + +#define _CRT_SECURE_NO_WARNINGS + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "PpContext.h" +#include "PpTokens.h" + +namespace { + +using namespace glslang; + +const struct { + int val; + const char* str; +} tokens[] = { + { PpAtomDefine, "define" }, + { PpAtomDefined, "defined" }, + { PpAtomUndef, "undef" }, + { PpAtomIf, "if" }, + { PpAtomElif, "elif" }, + { PpAtomElse, "else" }, + { PpAtomEndif, "endif" }, + { PpAtomIfdef, "ifdef" }, + { PpAtomIfndef, "ifndef" }, + { PpAtomLine, "line" }, + { PpAtomPragma, "pragma" }, + { PpAtomError, "error" }, + + { PpAtomVersion, "version" }, + { PpAtomCore, "core" }, + { PpAtomCompatibility, "compatibility" }, + { PpAtomEs, "es" }, + { PpAtomExtension, "extension" }, + + { PpAtomLineMacro, "__LINE__" }, + { PpAtomFileMacro, "__FILE__" }, + { PpAtomVersionMacro, "__VERSION__" }, + + { PpAtomInclude, "include" }, + +}; + +} // end anonymous namespace + +namespace glslang { + +// +// Map a new or existing string to an atom, inventing a new atom if necessary. +// +int TPpContext::LookUpAddString(const char* s) +{ + auto it = atomMap.find(s); + if (it == atomMap.end()) { + AddAtomFixed(s, nextAtom); + return nextAtom++; + } else + return it->second; +} + +// +// Map an already created atom to its string. +// +const char* TPpContext::GetAtomString(int atom) +{ + if ((size_t)atom >= stringMap.size()) + return "<bad token>"; + + const TString* atomString = stringMap[atom]; + + return atomString ? atomString->c_str() : "<bad token>"; +} + +// +// Add forced mapping of string to atom. +// +void TPpContext::AddAtomFixed(const char* s, int atom) +{ + auto it = atomMap.insert(std::pair<TString, int>(s, atom)).first; + if (stringMap.size() < (size_t)atom + 1) + stringMap.resize(atom + 100, 0); + stringMap[atom] = &it->first; +} + +// +// Initialize the atom table. +// +void TPpContext::InitAtomTable() +{ + // Add single character tokens to the atom table: + const char* s = "~!%^&*()-+=|,.<>/?;:[]{}#\\"; + char t[2]; + + t[1] = '\0'; + while (*s) { + t[0] = *s; + AddAtomFixed(t, s[0]); + s++; + } + + // Add multiple character scanner tokens : + for (size_t ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++) + AddAtomFixed(tokens[ii].str, tokens[ii].val); + + nextAtom = PpAtomLast; +} + +} // end namespace glslang diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpContext.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpContext.cpp new file mode 100644 index 00000000000..6f0b8a9a11a --- /dev/null +++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpContext.cpp @@ -0,0 +1,122 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//Copyright (C) 2013 LunarG, Inc. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +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 <stdio.h> +#include <stdlib.h> + +#include "PpContext.h" + +namespace glslang { + +TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, TShader::Includer& inclr) : + preamble(0), strings(0), parseContext(pc), includer(inclr), inComment(false), + rootFileName(rootFileName), + currentSourceFile(rootFileName) +{ + InitAtomTable(); + InitScanner(); + + ifdepth = 0; + for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++) + elseSeen[elsetracker] = false; + elsetracker = 0; +} + +TPpContext::~TPpContext() +{ + for (TSymbolMap::iterator it = symbols.begin(); it != symbols.end(); ++it) + delete it->second->mac.body; + mem_FreePool(pool); + delete [] preamble; + + // free up the inputStack + while (! inputStack.empty()) + popInput(); +} + +void TPpContext::setInput(TInputScanner& input, bool versionWillBeError) +{ + assert(inputStack.size() == 0); + + pushInput(new tStringInput(this, input)); + + errorOnVersion = versionWillBeError; + versionSeen = false; +} + +} // end namespace glslang diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpContext.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpContext.h new file mode 100644 index 00000000000..4e47fa055ec --- /dev/null +++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpContext.h @@ -0,0 +1,570 @@ +// +//Copyright (C) 2013 LunarG, Inc. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +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 PPCONTEXT_H +#define PPCONTEXT_H + +#include <stack> +#include <unordered_map> + +#include "../ParseHelper.h" + +/* windows only pragma */ +#ifdef _MSC_VER + #pragma warning(disable : 4127) +#endif + +namespace glslang { + +class TPpToken { +public: + TPpToken() : token(0), space(false), ival(0), dval(0.0), atom(0) + { + loc.init(); + name[0] = 0; + } + + bool operator==(const TPpToken& right) + { + return token == right.token && atom == right.atom && + ival == right.ival && dval == right.dval && + strcmp(name, right.name) == 0; + } + bool operator!=(const TPpToken& right) { return ! operator==(right); } + + TSourceLoc loc; + int token; + bool space; // true if a space (for white space or a removed comment) should also be recognized, in front of the token returned + int ival; + double dval; + long long i64val; + int atom; + char name[MaxTokenLength + 1]; +}; + +class TInputScanner; + +// This class is the result of turning a huge pile of C code communicating through globals +// into a class. This was done to allowing instancing to attain thread safety. +// Don't expect too much in terms of OO design. +class TPpContext { +public: + TPpContext(TParseContextBase&, const std::string& rootFileName, TShader::Includer&); + virtual ~TPpContext(); + + void setPreamble(const char* preamble, size_t length); + + const char* tokenize(TPpToken* ppToken); + + class tInput { + public: + tInput(TPpContext* p) : done(false), pp(p) { } + virtual ~tInput() { } + + virtual int scan(TPpToken*) = 0; + virtual int getch() = 0; + virtual void ungetch() = 0; + + // Will be called when we start reading tokens from this instance + virtual void notifyActivated() {} + // Will be called when we do not read tokens from this instance anymore + virtual void notifyDeleted() {} + protected: + bool done; + TPpContext* pp; + }; + + void setInput(TInputScanner& input, bool versionWillBeError); + + void pushInput(tInput* in) + { + inputStack.push_back(in); + in->notifyActivated(); + } + void popInput() + { + inputStack.back()->notifyDeleted(); + delete inputStack.back(); + inputStack.pop_back(); + } + + struct TokenStream { + TokenStream() : current(0) { } + TVector<unsigned char> data; + size_t current; + }; + + struct MemoryPool { + struct chunk *next; + uintptr_t free, end; + size_t chunksize; + uintptr_t alignmask; + }; + + // + // From Pp.cpp + // + + struct MacroSymbol { + MacroSymbol() : argc(0), args(0), body(0), busy(0), undef(0) { } + int argc; + int *args; + TokenStream *body; + unsigned busy:1; + unsigned undef:1; + }; + + struct Symbol { + int atom; + MacroSymbol mac; + }; + + struct SymbolList { + struct SymbolList_Rec *next; + Symbol *symb; + }; + + MemoryPool *pool; + typedef TMap<int, Symbol*> TSymbolMap; + TSymbolMap symbols; // this has light use... just defined macros + +protected: + TPpContext(TPpContext&); + TPpContext& operator=(TPpContext&); + + char* preamble; // string to parse, all before line 1 of string 0, it is 0 if no preamble + int preambleLength; + char** strings; // official strings of shader, starting a string 0 line 1 + size_t* lengths; + int numStrings; // how many official strings there are + int currentString; // which string we're currently parsing (-1 for preamble) + + // Scanner data: + int previous_token; + TParseContextBase& parseContext; + + // Get the next token from *stack* of input sources, popping input sources + // that are out of tokens, down until an input sources is found that has a token. + // Return EndOfInput when there are no more tokens to be found by doing this. + int scanToken(TPpToken* ppToken) + { + int token = EndOfInput; + + while (! inputStack.empty()) { + token = inputStack.back()->scan(ppToken); + if (token != EndOfInput) + break; + popInput(); + } + + return token; + } + int getChar() { return inputStack.back()->getch(); } + void ungetChar() { inputStack.back()->ungetch(); } + + static const int maxMacroArgs = 64; + static const int maxIfNesting = 64; + + int ifdepth; // current #if-#else-#endif nesting in the cpp.c file (pre-processor) + bool elseSeen[maxIfNesting]; // Keep a track of whether an else has been seen at a particular depth + int elsetracker; // #if-#else and #endif constructs...Counter. + + class tMacroInput : public tInput { + public: + tMacroInput(TPpContext* pp) : tInput(pp) { } + virtual ~tMacroInput() + { + for (size_t i = 0; i < args.size(); ++i) + delete args[i]; + } + + virtual int scan(TPpToken*); + virtual int getch() { assert(0); return EndOfInput; } + virtual void ungetch() { assert(0); } + MacroSymbol *mac; + TVector<TokenStream*> args; + }; + + class tMarkerInput : public tInput { + public: + tMarkerInput(TPpContext* pp) : tInput(pp) { } + virtual int scan(TPpToken*) + { + if (done) + return EndOfInput; + done = true; + + return marker; + } + virtual int getch() { assert(0); return EndOfInput; } + virtual void ungetch() { assert(0); } + static const int marker = -3; + }; + + class tZeroInput : public tInput { + public: + tZeroInput(TPpContext* pp) : tInput(pp) { } + virtual int scan(TPpToken*); + virtual int getch() { assert(0); return EndOfInput; } + virtual void ungetch() { assert(0); } + }; + + std::vector<tInput*> inputStack; + bool errorOnVersion; + bool versionSeen; + + // + // from Pp.cpp + // + + // Used to obtain #include content. + TShader::Includer& includer; + + int InitCPP(); + int CPPdefine(TPpToken * ppToken); + int CPPundef(TPpToken * ppToken); + 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 CPPinclude(TPpToken * ppToken); + int CPPline(TPpToken * ppToken); + int CPPerror(TPpToken * ppToken); + int CPPpragma(TPpToken * ppToken); + int CPPversion(TPpToken * ppToken); + int CPPextension(TPpToken * ppToken); + int readCPPline(TPpToken * ppToken); + TokenStream* PrescanMacroArg(TokenStream *a, TPpToken * ppToken, bool newLineOkay); + int MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool newLineOkay); + + // + // from PpSymbols.cpp + // + Symbol *NewSymbol(int name); + Symbol *AddSymbol(int atom); + Symbol *LookUpSymbol(int atom); + + // + // From PpTokens.cpp + // + void lAddByte(TokenStream *fTok, unsigned char fVal); + int lReadByte(TokenStream *pTok); + void lUnreadByte(TokenStream *pTok); + void RecordToken(TokenStream* pTok, int token, TPpToken* ppToken); + void RewindTokenStream(TokenStream *pTok); + int ReadToken(TokenStream* pTok, TPpToken* ppToken); + void pushTokenStreamInput(TokenStream *ts); + void UngetToken(int token, TPpToken* ppToken); + + class tTokenInput : public tInput { + public: + tTokenInput(TPpContext* pp, TokenStream* t) : tInput(pp), tokens(t) { } + virtual int scan(TPpToken *); + virtual int getch() { assert(0); return EndOfInput; } + virtual void ungetch() { assert(0); } + protected: + TokenStream *tokens; + }; + + class tUngotTokenInput : public tInput { + public: + tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { } + virtual int scan(TPpToken *); + virtual int getch() { assert(0); return EndOfInput; } + virtual void ungetch() { assert(0); } + protected: + int token; + TPpToken lval; + }; + + // + // From PpScanner.cpp + // + class tStringInput : public tInput { + public: + tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { } + virtual int scan(TPpToken*); + + // Scanner used to get source stream characters. + // - Escaped newlines are handled here, invisibly to the caller. + // - All forms of newline are handled, and turned into just a '\n'. + int getch() + { + int ch = input->get(); + + if (ch == '\\') { + // Move past escaped newlines, as many as sequentially exist + do { + if (input->peek() == '\r' || input->peek() == '\n') { + bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment); + if (! allowed && pp->inComment) + return '\\'; + + // escape one newline now + ch = input->get(); + int nextch = input->get(); + if (ch == '\r' && nextch == '\n') + ch = input->get(); + else + ch = nextch; + } else + return '\\'; + } while (ch == '\\'); + } + + // handle any non-escaped newline + if (ch == '\r' || ch == '\n') { + if (ch == '\r' && input->peek() == '\n') + input->get(); + return '\n'; + } + + return ch; + } + + // Scanner used to backup the source stream characters. Newlines are + // handled here, invisibly to the caller, meaning have to undo exactly + // what getch() above does (e.g., don't leave things in the middle of a + // sequence of escaped newlines). + void ungetch() + { + input->unget(); + + do { + int ch = input->peek(); + if (ch == '\r' || ch == '\n') { + if (ch == '\n') { + // correct for two-character newline + input->unget(); + if (input->peek() != '\r') + input->get(); + } + // now in front of a complete newline, move past an escape character + input->unget(); + if (input->peek() == '\\') + input->unget(); + else { + input->get(); + break; + } + } else + break; + } while (true); + } + + protected: + TInputScanner* input; + }; + + // Holds a reference to included file data, as well as a + // prologue and an epilogue string. This can be scanned using the tInput + // interface and acts as a single source string. + class TokenizableIncludeFile : public tInput { + public: + // Copies prologue and epilogue. The includedFile must remain valid + // until this TokenizableIncludeFile is no longer used. + TokenizableIncludeFile(const TSourceLoc& startLoc, + const std::string& prologue, + TShader::Includer::IncludeResult* includedFile, + const std::string& epilogue, + TPpContext* pp) + : tInput(pp), + prologue_(prologue), + includedFile_(includedFile), + epilogue_(epilogue), + scanner(3, strings, lengths, names, 0, 0, true), + prevScanner(nullptr), + stringInput(pp, scanner) + { + strings[0] = prologue_.data(); + strings[1] = includedFile_->file_data; + strings[2] = epilogue_.data(); + + lengths[0] = prologue_.size(); + lengths[1] = includedFile_->file_length; + lengths[2] = epilogue_.size(); + + scanner.setLine(startLoc.line); + scanner.setString(startLoc.string); + + scanner.setFile(startLoc.name, 0); + scanner.setFile(startLoc.name, 1); + scanner.setFile(startLoc.name, 2); + } + + // tInput methods: + int scan(TPpToken* t) override { return stringInput.scan(t); } + int getch() override { return stringInput.getch(); } + void ungetch() override { stringInput.ungetch(); } + + void notifyActivated() override + { + prevScanner = pp->parseContext.getScanner(); + pp->parseContext.setScanner(&scanner); + pp->push_include(includedFile_); + } + + void notifyDeleted() override + { + pp->parseContext.setScanner(prevScanner); + pp->pop_include(); + } + + private: + // Stores the prologue for this string. + const std::string prologue_; + + // Stores the epilogue for this string. + const std::string epilogue_; + + // Points to the IncludeResult that this TokenizableIncludeFile represents. + TShader::Includer::IncludeResult* includedFile_; + + // Will point to prologue_, includedFile_->file_data and epilogue_ + // This is passed to scanner constructor. + // These do not own the storage and it must remain valid until this + // object has been destroyed. + const char* strings[3]; + // Length of str_, passed to scanner constructor. + size_t lengths[3]; + // String names + const char* names[3]; + // Scans over str_. + TInputScanner scanner; + // The previous effective scanner before the scanner in this instance + // has been activated. + TInputScanner* prevScanner; + // Delegate object implementing the tInput interface. + tStringInput stringInput; + }; + + int InitScanner(); + int ScanFromString(char* s); + void missingEndifCheck(); + int lFloatConst(int len, int ch, TPpToken* ppToken); + + void push_include(TShader::Includer::IncludeResult* result) + { + currentSourceFile = result->file_name; + includeStack.push(result); + } + + void pop_include() + { + TShader::Includer::IncludeResult* include = includeStack.top(); + includeStack.pop(); + includer.releaseInclude(include); + if (includeStack.empty()) { + currentSourceFile = rootFileName; + } else { + currentSourceFile = includeStack.top()->file_name; + } + } + + bool inComment; + + // + // From PpAtom.cpp + // + typedef TUnorderedMap<TString, int> TAtomMap; + typedef TVector<const TString*> TStringMap; + + TAtomMap atomMap; + TStringMap stringMap; + std::stack<TShader::Includer::IncludeResult*> includeStack; + std::string currentSourceFile; + std::string rootFileName; + int nextAtom; + void InitAtomTable(); + void AddAtomFixed(const char* s, int atom); + int LookUpAddString(const char* s); + const char* GetAtomString(int atom); + + // + // From PpMemory.cpp + // + MemoryPool *mem_CreatePool(size_t chunksize, unsigned align); + void mem_FreePool(MemoryPool*); + void *mem_Alloc(MemoryPool* p, size_t size); + int mem_AddCleanup(MemoryPool* p, void (*fn)(void *, void*), void* arg1, void* arg2); +}; + +} // end namespace glslang + +#endif // PPCONTEXT_H diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpMemory.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpMemory.cpp new file mode 100644 index 00000000000..57a49fb893a --- /dev/null +++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpMemory.cpp @@ -0,0 +1,162 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//Copyright (C) 2013 LunarG, Inc. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +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> +#include <stdint.h> + +#include "PpContext.h" + +// default alignment and chunksize, if called with 0 arguments +#define CHUNKSIZE (64*1024) +#define ALIGN 8 + +namespace glslang { + +struct chunk { + struct chunk *next; +}; + +TPpContext::MemoryPool* TPpContext::mem_CreatePool(size_t chunksize, unsigned int align) +{ + if (align == 0) + align = ALIGN; + if (chunksize == 0) + chunksize = CHUNKSIZE; + if (align & (align - 1)) + return nullptr; + if (chunksize < sizeof(MemoryPool)) + return nullptr; + if (chunksize & (align - 1)) + return nullptr; + + MemoryPool *pool = (MemoryPool*)malloc(chunksize); + if (! pool) + return nullptr; + + 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; + + return pool; +} + +void TPpContext::mem_FreePool(MemoryPool *pool) +{ + struct chunk *p, *next; + + for (p = (struct chunk *)pool; p; p = next) { + next = p->next; + free(p); + } +} + +void* TPpContext::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 = (struct chunk*)malloc(minreq); + if (! ch) + return nullptr; + } else { + ch = (struct chunk*)malloc(pool->chunksize); + if (! ch) + return nullptr; + 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; +} + +} // end namespace glslang diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpScanner.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpScanner.cpp new file mode 100644 index 00000000000..b3d1af6dad2 --- /dev/null +++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpScanner.cpp @@ -0,0 +1,778 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//Copyright (C) 2013 LunarG, Inc. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +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 +// + +#define _CRT_SECURE_NO_WARNINGS + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "PpContext.h" +#include "PpTokens.h" +#include "../Scan.h" + +namespace glslang { + +int TPpContext::InitScanner() +{ + // Add various atoms needed by the CPP line scanner: + if (!InitCPP()) + return 0; + + previous_token = '\n'; + + return 1; +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////// Floating point constants: ///////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +/* +* lFloatConst() - Scan a single- or double-precision floating point constant. Assumes that the scanner +* has seen at least one digit, followed by either a decimal '.' or the +* letter 'e', or a precision ending (e.g., F or LF). +*/ + +int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken) +{ + bool HasDecimalOrExponent = false; + int declen; + int str_len; + int isDouble = 0; + + declen = 0; + + str_len=len; + char* str = ppToken->name; + if (ch == '.') { + HasDecimalOrExponent = true; + str[len++] = (char)ch; + ch = getChar(); + while (ch >= '0' && ch <= '9') { + if (len < MaxTokenLength) { + declen++; + if (len > 0 || ch != '0') { + str[len] = (char)ch; + len++; + str_len++; + } + ch = getChar(); + } else { + parseContext.ppError(ppToken->loc, "float literal too long", "", ""); + len = 1; + str_len = 1; + } + } + } + + // Exponent: + + if (ch == 'e' || ch == 'E') { + HasDecimalOrExponent = true; + if (len >= MaxTokenLength) { + parseContext.ppError(ppToken->loc, "float literal too long", "", ""); + len = 1; + str_len = 1; + } else { + str[len++] = (char)ch; + ch = getChar(); + if (ch == '+') { + str[len++] = (char)ch; + ch = getChar(); + } else if (ch == '-') { + str[len++] = (char)ch; + ch = getChar(); + } + if (ch >= '0' && ch <= '9') { + while (ch >= '0' && ch <= '9') { + if (len < MaxTokenLength) { + str[len++] = (char)ch; + ch = getChar(); + } else { + parseContext.ppError(ppToken->loc, "float literal too long", "", ""); + len = 1; + str_len = 1; + } + } + } else { + parseContext.ppError(ppToken->loc, "bad character in float exponent", "", ""); + } + } + } + + if (len == 0) { + ppToken->dval = 0.0; + strcpy(str, "0.0"); + } else { + if (ch == 'l' || ch == 'L') { + parseContext.doubleCheck(ppToken->loc, "double floating-point suffix"); + if (! HasDecimalOrExponent) + parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", ""); + int ch2 = getChar(); + if (ch2 != 'f' && ch2 != 'F') { + ungetChar(); + ungetChar(); + } else { + if (len < MaxTokenLength) { + str[len++] = (char)ch; + str[len++] = (char)ch2; + isDouble = 1; + } else { + parseContext.ppError(ppToken->loc, "float literal too long", "", ""); + len = 1,str_len=1; + } + } + } else if (ch == 'f' || ch == 'F') { + parseContext.profileRequires(ppToken->loc, EEsProfile, 300, nullptr, "floating-point suffix"); + if (! parseContext.relaxedErrors()) + parseContext.profileRequires(ppToken->loc, ~EEsProfile, 120, nullptr, "floating-point suffix"); + if (! HasDecimalOrExponent) + parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", ""); + if (len < MaxTokenLength) + str[len++] = (char)ch; + else { + parseContext.ppError(ppToken->loc, "float literal too long", "", ""); + len = 1,str_len=1; + } + } else + ungetChar(); + + str[len]='\0'; + + ppToken->dval = strtod(str, nullptr); + } + + if (isDouble) + return PpAtomConstDouble; + else + return PpAtomConstFloat; +} + +// +// Scanner used to tokenize source stream. +// +int TPpContext::tStringInput::scan(TPpToken* ppToken) +{ + char* tokenText = ppToken->name; + int AlreadyComplained = 0; + int len = 0; + int ch = 0; + int ii = 0; + unsigned long long ival = 0; + bool enableInt64 = pp->parseContext.version >= 450 && pp->parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64); + + ppToken->ival = 0; + ppToken->i64val = 0; + ppToken->space = false; + ch = getch(); + for (;;) { + while (ch == ' ' || ch == '\t') { + ppToken->space = true; + ch = getch(); + } + + ppToken->loc = pp->parseContext.getCurrentLoc(); + len = 0; + switch (ch) { + default: + // Single character token, including EndOfInput, '#' and '\' (escaped newlines are handled at a lower level, so this is just a '\' token) + return ch; + + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': case '_': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': + do { + if (len < MaxTokenLength) { + tokenText[len++] = (char)ch; + ch = getch(); + } else { + if (! AlreadyComplained) { + pp->parseContext.ppError(ppToken->loc, "name too long", "", ""); + AlreadyComplained = 1; + } + ch = getch(); + } + } while ((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || + ch == '_'); + + // line continuation with no token before or after makes len == 0, and need to start over skipping white space, etc. + if (len == 0) + continue; + + tokenText[len] = '\0'; + ungetch(); + ppToken->atom = pp->LookUpAddString(tokenText); + return PpAtomIdentifier; + case '0': + ppToken->name[len++] = (char)ch; + ch = getch(); + if (ch == 'x' || ch == 'X') { + // must be hexidecimal + + bool isUnsigned = false; + bool isInt64 = false; + ppToken->name[len++] = (char)ch; + ch = getch(); + if ((ch >= '0' && ch <= '9') || + (ch >= 'A' && ch <= 'F') || + (ch >= 'a' && ch <= 'f')) { + + ival = 0; + do { + if (ival <= 0x0fffffff || (enableInt64 && ival <= 0x0fffffffffffffffull)) { + ppToken->name[len++] = (char)ch; + if (ch >= '0' && ch <= '9') { + ii = ch - '0'; + } else if (ch >= 'A' && ch <= 'F') { + ii = ch - 'A' + 10; + } else if (ch >= 'a' && ch <= 'f') { + ii = ch - 'a' + 10; + } else + pp->parseContext.ppError(ppToken->loc, "bad digit in hexidecimal literal", "", ""); + ival = (ival << 4) | ii; + } else { + if (! AlreadyComplained) { + pp->parseContext.ppError(ppToken->loc, "hexidecimal literal too big", "", ""); + AlreadyComplained = 1; + } + ival = 0xffffffffffffffffull; + } + ch = getch(); + } while ((ch >= '0' && ch <= '9') || + (ch >= 'A' && ch <= 'F') || + (ch >= 'a' && ch <= 'f')); + } else { + pp->parseContext.ppError(ppToken->loc, "bad digit in hexidecimal literal", "", ""); + } + if (ch == 'u' || ch == 'U') { + if (len < MaxTokenLength) + ppToken->name[len++] = (char)ch; + isUnsigned = true; + + if (enableInt64) { + int nextCh = getch(); + if ((ch == 'u' && nextCh == 'l') || (ch == 'U' && nextCh == 'L')) { + if (len < MaxTokenLength) + ppToken->name[len++] = (char)nextCh; + isInt64 = true; + } else + ungetch(); + } + } + else if (enableInt64 && (ch == 'l' || ch == 'L')) { + if (len < MaxTokenLength) + ppToken->name[len++] = (char)ch; + isInt64 = true; + } else + ungetch(); + ppToken->name[len] = '\0'; + + if (isInt64) { + ppToken->i64val = ival; + return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64; + } else { + ppToken->ival = (int)ival; + return isUnsigned ? PpAtomConstUint : PpAtomConstInt; + } + } else { + // could be octal integer or floating point, speculative pursue octal until it must be floating point + + bool isUnsigned = false; + bool isInt64 = false; + bool octalOverflow = false; + bool nonOctal = false; + ival = 0; + + // see how much octal-like stuff we can read + while (ch >= '0' && ch <= '7') { + if (len < MaxTokenLength) + ppToken->name[len++] = (char)ch; + else if (! AlreadyComplained) { + pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", ""); + AlreadyComplained = 1; + } + if (ival <= 0x1fffffff || (enableInt64 && ival <= 0x1fffffffffffffffull)) { + ii = ch - '0'; + ival = (ival << 3) | ii; + } else + octalOverflow = true; + ch = getch(); + } + + // could be part of a float... + if (ch == '8' || ch == '9') { + nonOctal = true; + do { + if (len < MaxTokenLength) + ppToken->name[len++] = (char)ch; + else if (! AlreadyComplained) { + pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", ""); + AlreadyComplained = 1; + } + ch = getch(); + } while (ch >= '0' && ch <= '9'); + } + if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F') + return pp->lFloatConst(len, ch, ppToken); + + // wasn't a float, so must be octal... + if (nonOctal) + pp->parseContext.ppError(ppToken->loc, "octal literal digit too large", "", ""); + + if (ch == 'u' || ch == 'U') { + if (len < MaxTokenLength) + ppToken->name[len++] = (char)ch; + isUnsigned = true; + + if (enableInt64) { + int nextCh = getch(); + if ((ch == 'u' && nextCh == 'l') || (ch == 'U' && nextCh == 'L')) { + if (len < MaxTokenLength) + ppToken->name[len++] = (char)nextCh; + isInt64 = true; + } else + ungetch(); + } + } + else if (enableInt64 && (ch == 'l' || ch == 'L')) { + if (len < MaxTokenLength) + ppToken->name[len++] = (char)ch; + isInt64 = true; + } else + ungetch(); + ppToken->name[len] = '\0'; + + if (octalOverflow) + pp->parseContext.ppError(ppToken->loc, "octal literal too big", "", ""); + + if (isInt64) { + ppToken->i64val = ival; + return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64; + } else { + ppToken->ival = (int)ival; + return isUnsigned ? PpAtomConstUint : PpAtomConstInt; + } + } + break; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + // can't be hexidecimal or octal, is either decimal or floating point + + do { + if (len < MaxTokenLength) + ppToken->name[len++] = (char)ch; + else if (! AlreadyComplained) { + pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", ""); + AlreadyComplained = 1; + } + ch = getch(); + } while (ch >= '0' && ch <= '9'); + if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F') { + return pp->lFloatConst(len, ch, ppToken); + } else { + // Finish handling signed and unsigned integers + int numericLen = len; + bool isUnsigned = false; + bool isInt64 = false; + if (ch == 'u' || ch == 'U') { + if (len < MaxTokenLength) + ppToken->name[len++] = (char)ch; + isUnsigned = true; + + if (enableInt64) { + int nextCh = getch(); + if ((ch == 'u' && nextCh == 'l') || (ch == 'U' && nextCh == 'L')) { + if (len < MaxTokenLength) + ppToken->name[len++] = (char)nextCh; + isInt64 = true; + } else + ungetch(); + } + } else if (enableInt64 && (ch == 'l' || ch == 'L')) { + if (len < MaxTokenLength) + ppToken->name[len++] = (char)ch; + isInt64 = true; + } else + ungetch(); + + ppToken->name[len] = '\0'; + ival = 0; + const unsigned oneTenthMaxInt = 0xFFFFFFFFu / 10; + const unsigned remainderMaxInt = 0xFFFFFFFFu - 10 * oneTenthMaxInt; + const unsigned long long oneTenthMaxInt64 = 0xFFFFFFFFFFFFFFFFull / 10; + const unsigned long long remainderMaxInt64 = 0xFFFFFFFFFFFFFFFFull - 10 * oneTenthMaxInt64; + for (int i = 0; i < numericLen; i++) { + ch = ppToken->name[i] - '0'; + if ((enableInt64 == false && ((ival > oneTenthMaxInt) || (ival == oneTenthMaxInt && (unsigned)ch > remainderMaxInt))) || + (enableInt64 && ((ival > oneTenthMaxInt64) || (ival == oneTenthMaxInt64 && (unsigned long long)ch > remainderMaxInt64)))) { + pp->parseContext.ppError(ppToken->loc, "numeric literal too big", "", ""); + ival = 0xFFFFFFFFFFFFFFFFull; + break; + } else + ival = ival * 10 + ch; + } + + if (isInt64) { + ppToken->i64val = ival; + return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64; + } else { + ppToken->ival = (int)ival; + return isUnsigned ? PpAtomConstUint : PpAtomConstInt; + } + } + break; + case '-': + ch = getch(); + if (ch == '-') { + return PpAtomDecrement; + } else if (ch == '=') { + return PpAtomSub; + } else { + ungetch(); + return '-'; + } + case '+': + ch = getch(); + if (ch == '+') { + return PpAtomIncrement; + } else if (ch == '=') { + return PpAtomAdd; + } else { + ungetch(); + return '+'; + } + case '*': + ch = getch(); + if (ch == '=') { + return PpAtomMul; + } else { + ungetch(); + return '*'; + } + case '%': + ch = getch(); + if (ch == '=') { + return PpAtomMod; + } else { + ungetch(); + return '%'; + } + case '^': + ch = getch(); + if (ch == '^') { + return PpAtomXor; + } else { + if (ch == '=') + return PpAtomXorAssign; + else{ + ungetch(); + return '^'; + } + } + + case '=': + ch = getch(); + if (ch == '=') { + return PpAtomEQ; + } else { + ungetch(); + return '='; + } + case '!': + ch = getch(); + if (ch == '=') { + return PpAtomNE; + } else { + ungetch(); + return '!'; + } + case '|': + ch = getch(); + if (ch == '|') { + return PpAtomOr; + } else if (ch == '=') { + return PpAtomOrAssign; + } else { + ungetch(); + return '|'; + } + case '&': + ch = getch(); + if (ch == '&') { + return PpAtomAnd; + } else if (ch == '=') { + return PpAtomAndAssign; + } else { + ungetch(); + return '&'; + } + case '<': + ch = getch(); + if (ch == '<') { + ch = getch(); + if (ch == '=') + return PpAtomLeftAssign; + else { + ungetch(); + return PpAtomLeft; + } + } else if (ch == '=') { + return PpAtomLE; + } else { + ungetch(); + return '<'; + } + case '>': + ch = getch(); + if (ch == '>') { + ch = getch(); + if (ch == '=') + return PpAtomRightAssign; + else { + ungetch(); + return PpAtomRight; + } + } else if (ch == '=') { + return PpAtomGE; + } else { + ungetch(); + return '>'; + } + case '.': + ch = getch(); + if (ch >= '0' && ch <= '9') { + ungetch(); + return pp->lFloatConst(0, '.', ppToken); + } else { + ungetch(); + return '.'; + } + case '/': + ch = getch(); + if (ch == '/') { + pp->inComment = true; + do { + ch = getch(); + } while (ch != '\n' && ch != EndOfInput); + ppToken->space = true; + pp->inComment = false; + + return ch; + } else if (ch == '*') { + ch = getch(); + do { + while (ch != '*') { + if (ch == EndOfInput) { + pp->parseContext.ppError(ppToken->loc, "End of input in comment", "comment", ""); + return ch; + } + ch = getch(); + } + ch = getch(); + if (ch == EndOfInput) { + pp->parseContext.ppError(ppToken->loc, "End of input in comment", "comment", ""); + return ch; + } + } while (ch != '/'); + ppToken->space = true; + // loop again to get the next token... + break; + } else if (ch == '=') { + return PpAtomDiv; + } else { + ungetch(); + return '/'; + } + break; + case '"': + ch = getch(); + while (ch != '"' && ch != '\n' && ch != EndOfInput) { + if (len < MaxTokenLength) { + tokenText[len] = (char)ch; + len++; + ch = getch(); + } else + break; + }; + tokenText[len] = '\0'; + if (ch != '"') { + ungetch(); + pp->parseContext.ppError(ppToken->loc, "End of line in string", "string", ""); + } + return PpAtomConstString; + } + + ch = getch(); + } +} + +// +// The main functional entry-point into the preprocessor, which will +// scan the source strings to figure out and return the next processing token. +// +// Return string pointer to next token. +// Return 0 when no more tokens. +// +const char* TPpContext::tokenize(TPpToken* ppToken) +{ + int token = '\n'; + + for(;;) { + token = scanToken(ppToken); + ppToken->token = token; + if (token == EndOfInput) { + missingEndifCheck(); + return nullptr; + } + if (token == '#') { + if (previous_token == '\n') { + token = readCPPline(ppToken); + if (token == EndOfInput) { + missingEndifCheck(); + return nullptr; + } + continue; + } else { + parseContext.ppError(ppToken->loc, "preprocessor directive cannot be preceded by another token", "#", ""); + return nullptr; + } + } + previous_token = token; + + if (token == '\n') + continue; + + // expand macros + if (token == PpAtomIdentifier && MacroExpand(ppToken->atom, ppToken, false, true) != 0) + continue; + + const char* tokenString = nullptr; + switch (token) { + case PpAtomIdentifier: + case PpAtomConstInt: + case PpAtomConstUint: + case PpAtomConstFloat: + case PpAtomConstInt64: + case PpAtomConstUint64: + case PpAtomConstDouble: + tokenString = ppToken->name; + break; + case PpAtomConstString: + parseContext.ppError(ppToken->loc, "string literals not supported", "\"\"", ""); + break; + case '\'': + parseContext.ppError(ppToken->loc, "character literals not supported", "\'", ""); + break; + default: + tokenString = GetAtomString(token); + break; + } + + if (tokenString) { + if (tokenString[0] != 0) + parseContext.tokensBeforeEOF = 1; + + return tokenString; + } + } +} + +// Checks if we've seen balanced #if...#endif +void TPpContext::missingEndifCheck() +{ + if (ifdepth > 0) + parseContext.ppError(parseContext.getCurrentLoc(), "missing #endif", "", ""); +} + +} // end namespace glslang diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpSymbols.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpSymbols.cpp new file mode 100644 index 00000000000..c2ab7c0a11e --- /dev/null +++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpSymbols.cpp @@ -0,0 +1,135 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//Copyright (C) 2013 LunarG, Inc. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ +// +// symbols.c +// + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "PpContext.h" + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////// Symbol Table Variables: /////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glslang { + +/* +* Allocate a new symbol node; +* +*/ +TPpContext::Symbol* TPpContext::NewSymbol(int atom) +{ + Symbol* lSymb; + char* pch; + size_t ii; + + lSymb = (Symbol *) mem_Alloc(pool, sizeof(Symbol)); + lSymb->atom = atom; + + // Clear macro + pch = (char*) &lSymb->mac; + for (ii = 0; ii < sizeof(lSymb->mac); ii++) + *pch++ = 0; + + return lSymb; +} + +TPpContext::Symbol* TPpContext::AddSymbol(int atom) +{ + Symbol *lSymb; + + lSymb = NewSymbol(atom); + symbols[lSymb->atom] = lSymb; + + return lSymb; +} + +TPpContext::Symbol* TPpContext::LookUpSymbol(int atom) +{ + TSymbolMap::iterator it = symbols.find(atom); + if (it == symbols.end()) + return nullptr; + else + return it->second; +} + +} // end namespace glslang diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpTokens.cpp b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpTokens.cpp new file mode 100644 index 00000000000..54d495e11f2 --- /dev/null +++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpTokens.cpp @@ -0,0 +1,278 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//Copyright (C) 2013 LunarG, Inc. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +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. +\****************************************************************************/ + +// +// For recording and playing back the stream of tokens in a macro definition. +// + +#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) +#define _CRT_SECURE_NO_WARNINGS +#define snprintf sprintf_s +#endif + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#include "PpContext.h" +#include "PpTokens.h" + +namespace glslang { + +void TPpContext::lAddByte(TokenStream *fTok, unsigned char fVal) +{ + fTok->data.push_back(fVal); +} + +/* +* Get the next byte from a stream. +*/ +int TPpContext::lReadByte(TokenStream *pTok) +{ + if (pTok->current < pTok->data.size()) + return pTok->data[pTok->current++]; + else + return EndOfInput; +} + +void TPpContext::lUnreadByte(TokenStream *pTok) +{ + if (pTok->current > 0) + --pTok->current; +} + +/* +* Add a token to the end of a list for later playback. +*/ +void TPpContext::RecordToken(TokenStream *pTok, int token, TPpToken* ppToken) +{ + const char* s; + char* str = NULL; + + if (token > PpAtomMaxSingle) + lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80)); + else + lAddByte(pTok, (unsigned char)(token & 0x7f)); + + switch (token) { + case PpAtomIdentifier: + case PpAtomConstString: + s = ppToken->name; + while (*s) + lAddByte(pTok, (unsigned char) *s++); + lAddByte(pTok, 0); + break; + case PpAtomConstInt: + case PpAtomConstUint: + case PpAtomConstInt64: + case PpAtomConstUint64: + case PpAtomConstFloat: + case PpAtomConstDouble: + str = ppToken->name; + while (*str) { + lAddByte(pTok, (unsigned char) *str); + str++; + } + lAddByte(pTok, 0); + break; + default: + break; + } +} + +/* +* Reset a token stream in preperation for reading. +*/ +void TPpContext::RewindTokenStream(TokenStream *pTok) +{ + pTok->current = 0; +} + +/* +* Read the next token from a token stream (not the source stream, but stream used to hold a tokenized macro). +*/ +int TPpContext::ReadToken(TokenStream *pTok, TPpToken *ppToken) +{ + char* tokenText = ppToken->name; + int ltoken, len; + int ch; + + ltoken = lReadByte(pTok); + ppToken->loc = parseContext.getCurrentLoc(); + if (ltoken > 127) + ltoken += 128; + switch (ltoken) { + case '#': + if (lReadByte(pTok) == '#') { + parseContext.requireProfile(ppToken->loc, ~EEsProfile, "token pasting (##)"); + parseContext.profileRequires(ppToken->loc, ~EEsProfile, 130, 0, "token pasting (##)"); + parseContext.error(ppToken->loc, "token pasting not implemented (internal error)", "##", ""); + //return PpAtomPaste; + return ReadToken(pTok, ppToken); + } else + lUnreadByte(pTok); + break; + case PpAtomConstString: + case PpAtomIdentifier: + case PpAtomConstFloat: + case PpAtomConstDouble: + case PpAtomConstInt: + case PpAtomConstUint: + case PpAtomConstInt64: + case PpAtomConstUint64: + len = 0; + ch = lReadByte(pTok); + while (ch != 0 && ch != EndOfInput) { + if (len < MaxTokenLength) { + tokenText[len] = (char)ch; + len++; + ch = lReadByte(pTok); + } else { + parseContext.error(ppToken->loc, "token too long", "", ""); + break; + } + } + tokenText[len] = 0; + + switch (ltoken) { + case PpAtomIdentifier: + ppToken->atom = LookUpAddString(tokenText); + break; + case PpAtomConstString: + break; + case PpAtomConstFloat: + case PpAtomConstDouble: + ppToken->dval = atof(ppToken->name); + break; + case PpAtomConstInt: + case PpAtomConstUint: + if (len > 0 && tokenText[0] == '0') { + if (len > 1 && (tokenText[1] == 'x' || tokenText[1] == 'X')) + ppToken->ival = strtol(ppToken->name, 0, 16); + else + ppToken->ival = strtol(ppToken->name, 0, 8); + } else + ppToken->ival = atoi(ppToken->name); + break; + case PpAtomConstInt64: + case PpAtomConstUint64: + if (len > 0 && tokenText[0] == '0') { + if (len > 1 && (tokenText[1] == 'x' || tokenText[1] == 'X')) + ppToken->i64val = strtoll(ppToken->name, nullptr, 16); + else + ppToken->i64val = strtoll(ppToken->name, nullptr, 8); + } else + ppToken->i64val = atoll(ppToken->name); + break; + } + } + + return ltoken; +} + +int TPpContext::tTokenInput::scan(TPpToken* ppToken) +{ + return pp->ReadToken(tokens, ppToken); +} + +void TPpContext::pushTokenStreamInput(TokenStream* ts) +{ + pushInput(new tTokenInput(this, ts)); + RewindTokenStream(ts); +} + +int TPpContext::tUngotTokenInput::scan(TPpToken* ppToken) +{ + if (done) + return EndOfInput; + + int ret = token; + *ppToken = lval; + done = true; + + return ret; +} + +void TPpContext::UngetToken(int token, TPpToken* ppToken) +{ + pushInput(new tUngotTokenInput(this, token, ppToken)); +} + +} // end namespace glslang diff --git a/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpTokens.h b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpTokens.h new file mode 100644 index 00000000000..87f0eb1a60a --- /dev/null +++ b/chromium/third_party/glslang/src/glslang/MachineIndependent/preprocessor/PpTokens.h @@ -0,0 +1,171 @@ +// +//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions +//are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +//POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +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 PARSER_H +#define PARSER_H + +namespace glslang { + +// Multi-character tokens +enum EFixedAtoms { + PpAtomMaxSingle = 256, // single character tokens get their own char value as their token, skip them + + // Operators + + PpAtomAdd, + PpAtomSub, + PpAtomMul, + PpAtomDiv, + PpAtomMod, + + PpAtomRight, + PpAtomLeft, + + PpAtomRightAssign, + PpAtomLeftAssign, + PpAtomAndAssign, + PpAtomOrAssign, + PpAtomXorAssign, + + PpAtomAnd, + PpAtomOr, + PpAtomXor, + + PpAtomEQ, + PpAtomNE, + PpAtomGE, + PpAtomLE, + + PpAtomDecrement, + PpAtomIncrement, + + PpAtomPaste, + + // Constants + + PpAtomConstInt, + PpAtomConstUint, + PpAtomConstInt64, + PpAtomConstUint64, + PpAtomConstFloat, + PpAtomConstDouble, + PpAtomConstString, + + // Indentifiers + PpAtomIdentifier, + + // preprocessor "keywords" + + PpAtomDefine, + PpAtomDefined, + PpAtomUndef, + + PpAtomIf, + PpAtomIfdef, + PpAtomIfndef, + PpAtomElse, + PpAtomElif, + PpAtomEndif, + + PpAtomLine, + PpAtomPragma, + PpAtomError, + + // #version ... + PpAtomVersion, + PpAtomCore, + PpAtomCompatibility, + PpAtomEs, + + // #extension + PpAtomExtension, + + // __LINE__, __FILE__, __VERSION__ + + PpAtomLineMacro, + PpAtomFileMacro, + PpAtomVersionMacro, + + // #include + PpAtomInclude, + + PpAtomLast, +}; + +} // end namespace glslang + +#endif /* not PARSER_H */ |