2 //Copyright (C) 2013 LunarG, Inc.
5 //Redistribution and use in source and binary forms, with or without
6 //modification, are permitted provided that the following conditions
9 // Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
12 // Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following
14 // disclaimer in the documentation and/or other materials provided
15 // with the distribution.
17 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
18 // contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
21 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 //POSSIBILITY OF SUCH DAMAGE.
34 /****************************************************************************\
35 Copyright (c) 2002, NVIDIA Corporation.
37 NVIDIA Corporation("NVIDIA") supplies this software to you in
38 consideration of your agreement to the following terms, and your use,
39 installation, modification or redistribution of this NVIDIA software
40 constitutes acceptance of these terms. If you do not agree with these
41 terms, please do not use, install, modify or redistribute this NVIDIA
44 In consideration of your agreement to abide by the following terms, and
45 subject to these terms, NVIDIA grants you a personal, non-exclusive
46 license, under NVIDIA's copyrights in this original NVIDIA software (the
47 "NVIDIA Software"), to use, reproduce, modify and redistribute the
48 NVIDIA Software, with or without modifications, in source and/or binary
49 forms; provided that if you redistribute the NVIDIA Software, you must
50 retain the copyright notice of NVIDIA, this notice and the following
51 text and disclaimers in all such redistributions of the NVIDIA Software.
52 Neither the name, trademarks, service marks nor logos of NVIDIA
53 Corporation may be used to endorse or promote products derived from the
54 NVIDIA Software without specific prior written permission from NVIDIA.
55 Except as expressly stated in this notice, no other rights or licenses
56 express or implied, are granted by NVIDIA herein, including but not
57 limited to any patent rights that may be infringed by your derivative
58 works or by other works in which the NVIDIA Software may be
59 incorporated. No hardware is licensed hereunder.
61 THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
62 WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
63 INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
64 NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
65 ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
68 IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
69 INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
70 TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
71 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
72 OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
73 NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
74 TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
75 NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
76 \****************************************************************************/
81 #include "../ParseHelper.h"
87 TPpToken() : token(0), ival(0), space(false), dval(0.0), atom(0)
94 bool operator==(const TPpToken& right)
96 return token == right.token && atom == right.atom &&
97 ival == right.ival && dval == right.dval &&
98 strcmp(name, right.name) == 0;
100 bool operator!=(const TPpToken& right) { return ! operator==(right); }
102 static const int maxTokenLength = 1024;
106 bool space; // true if a space (for white space or a removed comment) should also be recognized, in front of the token returned
110 char name[maxTokenLength+1];
115 // This class is the result of turning a huge pile of C code communicating through globals
116 // into a class. This was done to allowing instancing to attain thread safety.
117 // Don't expect too much in terms of OO design.
120 TPpContext(TParseContext&);
121 virtual ~TPpContext();
123 void setPreamble(const char* preamble, size_t length);
125 const char* tokenize(TPpToken* ppToken);
129 tInput(TPpContext* p) : done(false), pp(p) { }
130 virtual ~tInput() { }
132 virtual int scan(TPpToken*) = 0;
133 virtual int getch() = 0;
134 virtual void ungetch() = 0;
136 static const int endOfInput = -2;
143 void setInput(TInputScanner& input, bool versionWillBeError);
145 void pushInput(tInput* in)
147 inputStack.push_back(in);
151 delete inputStack.back();
152 inputStack.pop_back();
156 TokenStream() : current(0) { }
157 TVector<unsigned char> data;
173 MacroSymbol() : argc(0), args(0), body(0), busy(0), undef(0) { }
187 struct SymbolList_Rec *next;
192 typedef std::map<int, Symbol*> TSymbolMap;
193 TSymbolMap symbols; // this has light use... just defined macros
196 TPpContext(TPpContext&);
197 TPpContext& operator=(TPpContext&);
199 char* preamble; // string to parse, all before line 1 of string 0, it is 0 if no preamble
201 char** strings; // official strings of shader, starting a string 0 line 1
203 int numStrings; // how many official strings there are
204 int currentString; // which string we're currently parsing (-1 for preamble)
208 TParseContext& parseContext;
210 // Get the next token from *stack* of input sources, popping input sources
211 // that are out of tokens, down until an input sources is found that has a token.
212 // Return EOF when there are no more tokens to be found by doing this.
213 int scanToken(TPpToken* ppToken)
217 while (! inputStack.empty()) {
218 token = inputStack.back()->scan(ppToken);
219 if (token != tInput::endOfInput)
224 if (token == tInput::endOfInput)
229 int getChar() { return inputStack.back()->getch(); }
230 void ungetChar() { inputStack.back()->ungetch(); }
232 static const int maxMacroArgs = 64;
233 static const int maxIfNesting = 64;
235 int ifdepth; // current #if-#else-#endif nesting in the cpp.c file (pre-processor)
236 bool elseSeen[maxIfNesting]; // Keep a track of whether an else has been seen at a particular depth
237 int elsetracker; // #if-#else and #endif constructs...Counter.
240 class tMacroInput : public tInput {
242 tMacroInput(TPpContext* pp) : tInput(pp) { }
243 virtual ~tMacroInput()
245 for (size_t i = 0; i < args.size(); ++i)
249 virtual int scan(TPpToken*);
250 virtual int getch() { assert(0); return endOfInput; }
251 virtual void ungetch() { assert(0); }
253 TVector<TokenStream*> args;
256 class tMarkerInput : public tInput {
258 tMarkerInput(TPpContext* pp) : tInput(pp) { }
259 virtual int scan(TPpToken*)
267 virtual int getch() { assert(0); return endOfInput; }
268 virtual void ungetch() { assert(0); }
269 static const int marker = -3;
272 class tZeroInput : public tInput {
274 tZeroInput(TPpContext* pp) : tInput(pp) { }
275 virtual int scan(TPpToken*);
276 virtual int getch() { assert(0); return endOfInput; }
277 virtual void ungetch() { assert(0); }
280 std::vector<tInput*> inputStack;
309 int compatibilityAtom;
312 TSourceLoc ifloc; /* outermost #if */
315 int CPPdefine(TPpToken * ppToken);
316 int CPPundef(TPpToken * ppToken);
317 int CPPelse(int matchelse, TPpToken * ppToken);
318 int extraTokenCheck(int atom, TPpToken* ppToken, int token);
319 int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
320 int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
321 int CPPif (TPpToken * ppToken);
322 int CPPifdef(int defined, TPpToken * ppToken);
323 int CPPline(TPpToken * ppToken);
324 int CPPerror(TPpToken * ppToken);
325 int CPPpragma(TPpToken * ppToken);
326 int CPPversion(TPpToken * ppToken);
327 int CPPextension(TPpToken * ppToken);
328 int readCPPline(TPpToken * ppToken);
329 TokenStream* PrescanMacroArg(TokenStream *a, TPpToken * ppToken, bool newLineOkay);
330 int MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool newLineOkay);
333 // from PpSymbols.cpp
335 Symbol *NewSymbol(int name);
336 Symbol *AddSymbol(int atom);
337 Symbol *LookUpSymbol(int atom);
342 void lAddByte(TokenStream *fTok, unsigned char fVal);
343 int lReadByte(TokenStream *pTok);
344 void lUnreadByte(TokenStream *pTok);
345 void RecordToken(TokenStream* pTok, int token, TPpToken* ppToken);
346 void RewindTokenStream(TokenStream *pTok);
347 int ReadToken(TokenStream* pTok, TPpToken* ppToken);
348 void pushTokenStreamInput(TokenStream *ts);
349 void UngetToken(int token, TPpToken* ppToken);
351 class tTokenInput : public tInput {
353 tTokenInput(TPpContext* pp, TokenStream* t) : tInput(pp), tokens(t) { }
354 virtual int scan(TPpToken *);
355 virtual int getch() { assert(0); return endOfInput; }
356 virtual void ungetch() { assert(0); }
361 class tUngotTokenInput : public tInput {
363 tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { }
364 virtual int scan(TPpToken *);
365 virtual int getch() { assert(0); return endOfInput; }
366 virtual void ungetch() { assert(0); }
373 // From PpScanner.cpp
375 class tStringInput : public tInput {
377 tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { }
378 virtual int scan(TPpToken*);
380 // Scanner used to get source stream characters.
381 // - Escaped newlines are handled here, invisibly to the caller.
382 // - All forms of newline are handled, and turned into just a '\n'.
385 int ch = input->get();
388 // Move past escaped newlines, as many as sequentially exist
390 if (input->peek() == '\r' || input->peek() == '\n') {
391 bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment);
392 if (! allowed && pp->inComment)
395 // escape one newline now
397 int nextch = input->get();
398 if (ch == '\r' && nextch == '\n')
404 } while (ch == '\\');
407 // handle any non-escaped newline
408 if (ch == '\r' || ch == '\n') {
409 if (ch == '\r' && input->peek() == '\n')
417 // Scanner used to backup the source stream characters. Newlines are
418 // handled here, invisibly to the caller, meaning have to undo exactly
419 // what getch() above does (e.g., don't leave things in the middle of a
420 // sequence of escaped newlines).
426 int ch = input->peek();
427 if (ch == '\r' || ch == '\n') {
429 // correct for two-character newline
431 if (input->peek() != '\r')
434 // now in front of a complete newline, move past an escape character
436 if (input->peek() == '\\')
448 TInputScanner* input;
452 int ScanFromString(char* s);
453 void missingEndifCheck();
454 int lFloatConst(int len, int ch, TPpToken* ppToken);
461 typedef std::map<const TString, int> TAtomMap;
462 typedef TVector<const TString*> TStringMap;
464 TStringMap stringMap;
466 void InitAtomTable();
467 int AddAtomFixed(const char* s, int atom);
468 int LookUpAddString(const char* s);
469 const char* GetAtomString(int atom);
474 MemoryPool *mem_CreatePool(size_t chunksize, unsigned align);
475 void mem_FreePool(MemoryPool*);
476 void *mem_Alloc(MemoryPool* p, size_t size);
477 int mem_AddCleanup(MemoryPool* p, void (*fn)(void *, void*), void* arg1, void* arg2);
480 } // end namespace glslang
482 #endif // PPCONTEXT_H