From 1abc4045ce297742ba3693701179f653025cc289 Mon Sep 17 00:00:00 2001 From: John Kessenich <cepheus@frii.com> Date: Tue, 3 Dec 2013 17:19:03 +0000 Subject: [PATCH] Add #line functionality to allow expressions instead of just literals. Also made some preprocessor code slightly more clear. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24294 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- Test/baseResults/cppSimple.vert.out | 13 +- Test/cppSimple.vert | 23 ++++ .../MachineIndependent/preprocessor/Pp.cpp | 122 ++++++++++-------- .../preprocessor/PpContext.h | 2 +- 4 files changed, 101 insertions(+), 59 deletions(-) diff --git a/Test/baseResults/cppSimple.vert.out b/Test/baseResults/cppSimple.vert.out index d47c52bdb..f41a1e28f 100644 --- a/Test/baseResults/cppSimple.vert.out +++ b/Test/baseResults/cppSimple.vert.out @@ -61,8 +61,17 @@ ERROR: 0:235: 'line continuation' : not supported for this version or the enable ERROR: 0:236: '#error' : good continuation ERROR: 0:238: '#' : invalid directive: flizbit ERROR: 0:242: '#' : invalid directive: directive -ERROR: 0:246: '' : missing #endif -ERROR: 62 compilation errors. No code generated. +ERROR: 0:12001: '#error' : line should be 12001 +ERROR: 7:13001: '#error' : line should be 13001 , string 7 +ERROR: 7:14014: '#error' : line should be 14014 , string 7 +ERROR: 12:14014: '#error' : line should be 14014 , string 12 +ERROR: 12:14026: '#error' : line should be 14026 , string 12 +ERROR: 12:1234: '#line' : unexpected tokens following directive +ERROR: 12:20001: '#error' : line should be 20001 +ERROR: 12:20011: '#error' : line should be 20011 +ERROR: 12:20021: '#error' : line should be 20021 +ERROR: 12:10003: '' : missing #endif +ERROR: 71 compilation errors. No code generated. ERROR: node is still EOpNull! diff --git a/Test/cppSimple.vert b/Test/cppSimple.vert index 73604e20b..1344c8d6c 100644 --- a/Test/cppSimple.vert +++ b/Test/cppSimple.vert @@ -241,6 +241,29 @@ double f = f1; #directive directive was expanded +#line 12000 +#error line should be 12001 +#line 13000 7 +#error line should be 13001, string 7 +#define L1 14000 +#define L2 13 +#define F1 5 +#define F2 7 +#line L1 + L2 +#error line should be 14014, string 7 +#line L1 + L2 F1 + F2 +#error line should be 14014, string 12 +#line L1 + L2 + F1 + F2 +#error line should be 14026, string 12 +#line 1234 F1 + F2 extra +#line (20000) +#error line should be 20001 +#line (20000+10) +#error line should be 20011 +#line +20020 +#error line should be 20021 + +#line 10000 #if 1 #else // ERROR, missing #endif \ No newline at end of file diff --git a/glslang/MachineIndependent/preprocessor/Pp.cpp b/glslang/MachineIndependent/preprocessor/Pp.cpp index ead5dc4f4..faad6565c 100644 --- a/glslang/MachineIndependent/preprocessor/Pp.cpp +++ b/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -125,6 +125,7 @@ int TPpContext::InitCPP() return 1; } +// Handle #define int TPpContext::CPPdefine(TPpToken* ppToken) { int token, atom, args[maxMacroArgs], argc; @@ -237,6 +238,7 @@ int TPpContext::CPPdefine(TPpToken* ppToken) return '\n'; } +// Handle #undef int TPpContext::CPPundef(TPpToken* ppToken) { int token = currentInput->scan(this, currentInput, ppToken); @@ -261,6 +263,7 @@ int TPpContext::CPPundef(TPpToken* ppToken) 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. @@ -334,6 +337,7 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken) 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') { @@ -348,6 +352,8 @@ int TPpContext::extraTokenCheck(int atom, TPpToken* ppToken, int token) label = "#endif"; else if (atom == ifAtom) label = "#if"; + else if (atom == lineAtom) + label = "#line"; else label = ""; @@ -364,9 +370,9 @@ int TPpContext::extraTokenCheck(int atom, TPpToken* ppToken, int token) } enum eval_prec { - MIN_PREC, + MIN_PRECEDENCE, COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY, - MAX_PREC + MAX_PRECEDENCE }; namespace { @@ -397,7 +403,7 @@ namespace { }; struct Tbinops { - int token, prec, (*op)(int, int); + int token, precedence, (*op)(int, int); } binop[] = { { CPP_OR_OP, LOGOR, op_logor }, { CPP_AND_OP, LOGAND, op_logand }, @@ -430,7 +436,7 @@ struct tunops { #define ALEN(A) (sizeof(A)/sizeof(A[0])) -int TPpContext::eval(int token, int prec, int *res, int *err, TPpToken* ppToken) +int TPpContext::eval(int token, int precedence, int& res, bool& err, TPpToken* ppToken) { int i, val; Symbol *s; @@ -445,19 +451,18 @@ int TPpContext::eval(int token, int prec, int *res, int *err, TPpToken* ppToken) } if (token != CPP_IDENTIFIER) { parseContext.error(ppToken->loc, "incorrect directive, expected identifier", "preprocessor evaluation", ""); - *err = 1; - *res = 0; + err = true; + res = 0; return token; } - *res = (s = LookUpSymbol(ppToken->atom)) - ? !s->mac.undef : 0; + res = (s = LookUpSymbol(ppToken->atom)) ? !s->mac.undef : 0; token = currentInput->scan(this, currentInput, ppToken); if (needclose) { if (token != ')') { parseContext.error(ppToken->loc, "#else after #else", "preprocessor evaluation", ""); - *err = 1; - *res = 0; + err = true; + res = 0; return token; } @@ -467,8 +472,8 @@ int TPpContext::eval(int token, int prec, int *res, int *err, TPpToken* ppToken) int macroReturn = MacroExpand(ppToken->atom, ppToken, 1); if (macroReturn == 0) { parseContext.error(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", ""); - *err = 1; - *res = 0; + err = true; + res = 0; return token; } else { @@ -479,26 +484,26 @@ int TPpContext::eval(int token, int prec, int *res, int *err, TPpToken* ppToken) else { parseContext.error(ppToken->loc, "undefined macro in expression", "preprocessor evaluation", ""); - *err = 1; + err = true; } } } token = currentInput->scan(this, currentInput, ppToken); - return eval(token, prec, res, err, ppToken); + return eval(token, precedence, res, err, ppToken); } } } else if (token == CPP_INTCONSTANT) { - *res = ppToken->ival; + res = ppToken->ival; token = currentInput->scan(this, currentInput, ppToken); } else if (token == '(') { token = currentInput->scan(this, currentInput, ppToken); - token = eval(token, MIN_PREC, res, err, ppToken); - if (!*err) { + token = eval(token, MIN_PRECEDENCE, res, err, ppToken); + if (! err) { if (token != ')') { parseContext.error(ppToken->loc, "expected ')'", "preprocessor evaluation", ""); - *err = 1; - *res = 0; + err = true; + res = 0; return token; } @@ -512,37 +517,37 @@ int TPpContext::eval(int token, int prec, int *res, int *err, TPpToken* ppToken) if (i >= 0) { token = currentInput->scan(this, currentInput, ppToken); token = eval(token, UNARY, res, err, ppToken); - *res = unop[i].op(*res); + res = unop[i].op(res); } else { parseContext.error(ppToken->loc, "bad expression", "preprocessor evaluation", ""); - *err = 1; - *res = 0; + err = true; + res = 0; return token; } } - while (!*err) { + while (! err) { if (token == ')' || token == '\n') break; for (i = ALEN(binop) - 1; i >= 0; i--) { if (binop[i].token == token) break; } - if (i < 0 || binop[i].prec <= prec) + if (i < 0 || binop[i].precedence <= precedence) break; - val = *res; + val = res; token = currentInput->scan(this, currentInput, ppToken); - token = eval(token, binop[i].prec, res, err, ppToken); - *res = binop[i].op(val, *res); + token = eval(token, binop[i].precedence, res, err, ppToken); + res = binop[i].op(val, res); } return token; -} // eval +} +// Handle #if int TPpContext::CPPif(TPpToken* ppToken) { int token = currentInput->scan(this, currentInput, ppToken); - int res = 0, err = 0; elsetracker++; if (! ifdepth++) ifloc = ppToken->loc; @@ -550,7 +555,9 @@ int TPpContext::CPPif(TPpToken* ppToken) parseContext.error(ppToken->loc, "maximum nesting depth exceeded", "#if", ""); return 0; } - token = eval(token, MIN_PREC, &res, &err, ppToken); + int res = 0; + bool err = false; + token = eval(token, MIN_PRECEDENCE, res, err, ppToken); token = extraTokenCheck(ifAtom, ppToken, token); if (!res && !err) token = CPPelse(1, ppToken); @@ -558,7 +565,8 @@ int TPpContext::CPPif(TPpToken* ppToken) return token; } -int TPpContext::CPPifdef(int defined, TPpToken * ppToken) +// Handle #ifdef +int TPpContext::CPPifdef(int defined, TPpToken* ppToken) { int token = currentInput->scan(this, currentInput, ppToken); int name = ppToken->atom; @@ -588,35 +596,36 @@ int TPpContext::CPPifdef(int defined, TPpToken * ppToken) } // Handle #line -int TPpContext::CPPline(TPpToken * ppToken) +int TPpContext::CPPline(TPpToken* ppToken) { int token = currentInput->scan(this, currentInput, ppToken); if (token == '\n') { parseContext.error(ppToken->loc, "must by followed by an integral literal", "#line", ""); return token; } - else if (token == CPP_INTCONSTANT) { - parseContext.setCurrentLine(atoi(ppToken->name)); - token = currentInput->scan(this, currentInput, ppToken); - - if (token == CPP_INTCONSTANT) { - parseContext.setCurrentString(atoi(ppToken->name)); - token = currentInput->scan(this, currentInput, ppToken); - if (token != '\n') - parseContext.error(parseContext.getCurrentLoc(), "cannot be followed by more than two integral literals", "#line", ""); - } else if (token == '\n') - return token; - else - parseContext.error(parseContext.getCurrentLoc(), "second argument can only be an integral literal", "#line", ""); - } else - parseContext.error(parseContext.getCurrentLoc(), "first argument can only be an integral literal", "#line", ""); + int lineRes = 0; + bool lineErr = false; + token = eval(token, MIN_PRECEDENCE, lineRes, lineErr, ppToken); + if (! lineErr) { + if (token == '\n') + ++lineRes; + parseContext.setCurrentLine(lineRes); + if (token != '\n') { + int fileRes = 0; + bool fileErr = false; + token = eval(token, MIN_PRECEDENCE, fileRes, fileErr, ppToken); + if (! fileErr) + parseContext.setCurrentString(fileRes); + } + } + token = extraTokenCheck(lineAtom, ppToken, token); return token; } // Handle #error -int TPpContext::CPPerror(TPpToken * ppToken) +int TPpContext::CPPerror(TPpToken* ppToken) { int token = currentInput->scan(this, currentInput, ppToken); std::string message; @@ -640,6 +649,7 @@ int TPpContext::CPPerror(TPpToken * ppToken) return '\n'; } +// Handle #pragma int TPpContext::CPPpragma(TPpToken* ppToken) { char SrcStrName[2]; @@ -679,8 +689,8 @@ int TPpContext::CPPpragma(TPpToken* ppToken) return token; } -// This is just for error checking: the version and profile are decided before preprocessing starts -int TPpContext::CPPversion(TPpToken * ppToken) +// #version: This is just for error checking: the version and profile are decided before preprocessing starts +int TPpContext::CPPversion(TPpToken* ppToken) { int token = currentInput->scan(this, currentInput, ppToken); @@ -717,11 +727,11 @@ int TPpContext::CPPversion(TPpToken * ppToken) } return token; -} // CPPversion +} -int TPpContext::CPPextension(TPpToken * ppToken) +// Handle #extension +int TPpContext::CPPextension(TPpToken* ppToken) { - int token = currentInput->scan(this, currentInput, ppToken); char extensionName[80]; @@ -756,9 +766,9 @@ int TPpContext::CPPextension(TPpToken * ppToken) parseContext.error(ppToken->loc, "extra tokens -- expected newline", "#extension",""); return token; -} // CPPextension +} -int TPpContext::readCPPline(TPpToken * ppToken) +int TPpContext::readCPPline(TPpToken* ppToken) { int token = currentInput->scan(this, currentInput, ppToken); bool isVersion = false; @@ -847,7 +857,7 @@ void TPpContext::PopEofSrc() } } -TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream *a, TPpToken * ppToken) +TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream *a, TPpToken* ppToken) { int token; TokenStream *n; diff --git a/glslang/MachineIndependent/preprocessor/PpContext.h b/glslang/MachineIndependent/preprocessor/PpContext.h index d1cb6e830..cf9ac8a6b 100644 --- a/glslang/MachineIndependent/preprocessor/PpContext.h +++ b/glslang/MachineIndependent/preprocessor/PpContext.h @@ -244,7 +244,7 @@ protected: int CPPundef(TPpToken * ppToken); int CPPelse(int matchelse, TPpToken * ppToken); int extraTokenCheck(int atom, TPpToken* ppToken, int token); - int eval(int token, int prec, int *res, int *err, TPpToken * ppToken); + int eval(int token, int precedence, int& res, bool& err, TPpToken * ppToken); int CPPif (TPpToken * ppToken); int CPPifdef(int defined, TPpToken * ppToken); int CPPline(TPpToken * ppToken); -- GitLab