• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2013 LunarG, Inc.
3 // Copyright (C) 2015-2018 Google, Inc.
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions
8 // are met:
9 //
10 //    Redistributions of source code must retain the above copyright
11 //    notice, this list of conditions and the following disclaimer.
12 //
13 //    Redistributions in binary form must reproduce the above
14 //    copyright notice, this list of conditions and the following
15 //    disclaimer in the documentation and/or other materials provided
16 //    with the distribution.
17 //
18 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
19 //    contributors may be used to endorse or promote products derived
20 //    from this software without specific prior written permission.
21 //
22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 // POSSIBILITY OF SUCH DAMAGE.
34 //
35 /****************************************************************************\
36 Copyright (c) 2002, NVIDIA Corporation.
37 
38 NVIDIA Corporation("NVIDIA") supplies this software to you in
39 consideration of your agreement to the following terms, and your use,
40 installation, modification or redistribution of this NVIDIA software
41 constitutes acceptance of these terms.  If you do not agree with these
42 terms, please do not use, install, modify or redistribute this NVIDIA
43 software.
44 
45 In consideration of your agreement to abide by the following terms, and
46 subject to these terms, NVIDIA grants you a personal, non-exclusive
47 license, under NVIDIA's copyrights in this original NVIDIA software (the
48 "NVIDIA Software"), to use, reproduce, modify and redistribute the
49 NVIDIA Software, with or without modifications, in source and/or binary
50 forms; provided that if you redistribute the NVIDIA Software, you must
51 retain the copyright notice of NVIDIA, this notice and the following
52 text and disclaimers in all such redistributions of the NVIDIA Software.
53 Neither the name, trademarks, service marks nor logos of NVIDIA
54 Corporation may be used to endorse or promote products derived from the
55 NVIDIA Software without specific prior written permission from NVIDIA.
56 Except as expressly stated in this notice, no other rights or licenses
57 express or implied, are granted by NVIDIA herein, including but not
58 limited to any patent rights that may be infringed by your derivative
59 works or by other works in which the NVIDIA Software may be
60 incorporated. No hardware is licensed hereunder.
61 
62 THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
63 WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
64 INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
65 NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
66 ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
67 PRODUCTS.
68 
69 IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
70 INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
71 TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
72 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
73 OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
74 NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
75 TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
76 NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
77 \****************************************************************************/
78 
79 #ifndef PPCONTEXT_H
80 #define PPCONTEXT_H
81 
82 #include <stack>
83 #include <unordered_map>
84 #include <sstream>
85 
86 #include "../ParseHelper.h"
87 
88 /* windows only pragma */
89 #ifdef _MSC_VER
90     #pragma warning(disable : 4127)
91 #endif
92 
93 namespace glslang {
94 
95 class TPpToken {
96 public:
TPpToken()97     TPpToken() { clear(); }
clear()98     void clear()
99     {
100         space = false;
101         i64val = 0;
102         loc.init();
103         name[0] = 0;
104     }
105 
106     // Used for comparing macro definitions, so checks what is relevant for that.
107     bool operator==(const TPpToken& right)
108     {
109         return space == right.space &&
110                ival == right.ival && dval == right.dval && i64val == right.i64val &&
111                strncmp(name, right.name, MaxTokenLength) == 0;
112     }
113     bool operator!=(const TPpToken& right) { return ! operator==(right); }
114 
115     TSourceLoc loc;
116     // True if a space (for white space or a removed comment) should also be
117     // recognized, in front of the token returned:
118     bool space;
119     // Numeric value of the token:
120     union {
121         int ival;
122         double dval;
123         long long i64val;
124     };
125     // Text string of the token:
126     char name[MaxTokenLength + 1];
127 };
128 
129 class TStringAtomMap {
130 //
131 // Implementation is in PpAtom.cpp
132 //
133 // Maintain a bi-directional mapping between relevant preprocessor strings and
134 // "atoms" which a unique integers (small, contiguous, not hash-like) per string.
135 //
136 public:
137     TStringAtomMap();
138 
139     // Map string -> atom.
140     // Return 0 if no existing string.
getAtom(const char * s)141     int getAtom(const char* s) const
142     {
143         auto it = atomMap.find(s);
144         return it == atomMap.end() ? 0 : it->second;
145     }
146 
147     // Map a new or existing string -> atom, inventing a new atom if necessary.
getAddAtom(const char * s)148     int getAddAtom(const char* s)
149     {
150         int atom = getAtom(s);
151         if (atom == 0) {
152             atom = nextAtom++;
153             addAtomFixed(s, atom);
154         }
155         return atom;
156     }
157 
158     // Map atom -> string.
getString(int atom)159     const char* getString(int atom) const { return stringMap[atom]->c_str(); }
160 
161 protected:
162     TStringAtomMap(TStringAtomMap&);
163     TStringAtomMap& operator=(TStringAtomMap&);
164 
165     TUnorderedMap<TString, int> atomMap;
166     TVector<const TString*> stringMap;    // these point into the TString in atomMap
167     int nextAtom;
168 
169     // Bad source characters can lead to bad atoms, so gracefully handle those by
170     // pre-filling the table with them (to avoid if tests later).
171     TString badToken;
172 
173     // Add bi-directional mappings:
174     //  - string -> atom
175     //  - atom -> string
addAtomFixed(const char * s,int atom)176     void addAtomFixed(const char* s, int atom)
177     {
178         auto it = atomMap.insert(std::pair<TString, int>(s, atom)).first;
179         if (stringMap.size() < (size_t)atom + 1)
180             stringMap.resize(atom + 100, &badToken);
181         stringMap[atom] = &it->first;
182     }
183 };
184 
185 class TInputScanner;
186 
187 enum MacroExpandResult {
188     MacroExpandNotStarted, // macro not expanded, which might not be an error
189     MacroExpandError,      // a clear error occurred while expanding, no expansion
190     MacroExpandStarted,    // macro expansion process has started
191     MacroExpandUndef       // macro is undefined and will be expanded
192 };
193 
194 // This class is the result of turning a huge pile of C code communicating through globals
195 // into a class.  This was done to allowing instancing to attain thread safety.
196 // Don't expect too much in terms of OO design.
197 class TPpContext {
198 public:
199     TPpContext(TParseContextBase&, const std::string& rootFileName, TShader::Includer&);
200     virtual ~TPpContext();
201 
202     void setPreamble(const char* preamble, size_t length);
203 
204     int tokenize(TPpToken& ppToken);
205     int tokenPaste(int token, TPpToken&);
206 
207     class tInput {
208     public:
tInput(TPpContext * p)209         tInput(TPpContext* p) : done(false), pp(p) { }
~tInput()210         virtual ~tInput() { }
211 
212         virtual int scan(TPpToken*) = 0;
213         virtual int getch() = 0;
214         virtual void ungetch() = 0;
peekPasting()215         virtual bool peekPasting() { return false; }          // true when about to see ##
endOfReplacementList()216         virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define)
isMacroInput()217         virtual bool isMacroInput() { return false; }
218 
219         // Will be called when we start reading tokens from this instance
notifyActivated()220         virtual void notifyActivated() {}
221         // Will be called when we do not read tokens from this instance anymore
notifyDeleted()222         virtual void notifyDeleted() {}
223     protected:
224         bool done;
225         TPpContext* pp;
226     };
227 
228     void setInput(TInputScanner& input, bool versionWillBeError);
229 
pushInput(tInput * in)230     void pushInput(tInput* in)
231     {
232         inputStack.push_back(in);
233         in->notifyActivated();
234     }
popInput()235     void popInput()
236     {
237         inputStack.back()->notifyDeleted();
238         delete inputStack.back();
239         inputStack.pop_back();
240     }
241 
242     //
243     // From PpTokens.cpp
244     //
245 
246     class TokenStream {
247     public:
TokenStream()248         TokenStream() : current(0) { }
249 
250         void putToken(int token, TPpToken* ppToken);
251         int getToken(TParseContextBase&, TPpToken*);
atEnd()252         bool atEnd() { return current >= data.size(); }
253         bool peekTokenizedPasting(bool lastTokenPastes);
254         bool peekUntokenizedPasting();
reset()255         void reset() { current = 0; }
256 
257     protected:
258         void putSubtoken(char);
259         int getSubtoken();
260         void ungetSubtoken();
261 
262         TVector<unsigned char> data;
263         size_t current;
264     };
265 
266     //
267     // From Pp.cpp
268     //
269 
270     struct MacroSymbol {
MacroSymbolMacroSymbol271         MacroSymbol() : functionLike(0), busy(0), undef(0) { }
272         TVector<int> args;
273         TokenStream body;
274         unsigned functionLike : 1;  // 0 means object-like, 1 means function-like
275         unsigned busy         : 1;
276         unsigned undef        : 1;
277     };
278 
279     typedef TMap<int, MacroSymbol> TSymbolMap;
280     TSymbolMap macroDefs;  // map atoms to macro definitions
lookupMacroDef(int atom)281     MacroSymbol* lookupMacroDef(int atom)
282     {
283         auto existingMacroIt = macroDefs.find(atom);
284         return (existingMacroIt == macroDefs.end()) ? nullptr : &(existingMacroIt->second);
285     }
addMacroDef(int atom,MacroSymbol & macroDef)286     void addMacroDef(int atom, MacroSymbol& macroDef) { macroDefs[atom] = macroDef; }
287 
288 protected:
289     TPpContext(TPpContext&);
290     TPpContext& operator=(TPpContext&);
291 
292     TStringAtomMap atomStrings;
293     char*   preamble;               // string to parse, all before line 1 of string 0, it is 0 if no preamble
294     int     preambleLength;
295     char**  strings;                // official strings of shader, starting a string 0 line 1
296     size_t* lengths;
297     int     numStrings;             // how many official strings there are
298     int     currentString;          // which string we're currently parsing  (-1 for preamble)
299 
300     // Scanner data:
301     int previous_token;
302     TParseContextBase& parseContext;
303 
304     // Get the next token from *stack* of input sources, popping input sources
305     // that are out of tokens, down until an input source is found that has a token.
306     // Return EndOfInput when there are no more tokens to be found by doing this.
scanToken(TPpToken * ppToken)307     int scanToken(TPpToken* ppToken)
308     {
309         int token = EndOfInput;
310 
311         while (! inputStack.empty()) {
312             token = inputStack.back()->scan(ppToken);
313             if (token != EndOfInput || inputStack.empty())
314                 break;
315             popInput();
316         }
317 
318         return token;
319     }
getChar()320     int  getChar() { return inputStack.back()->getch(); }
ungetChar()321     void ungetChar() { inputStack.back()->ungetch(); }
peekPasting()322     bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); }
endOfReplacementList()323     bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); }
isMacroInput()324     bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); }
325 
326     static const int maxIfNesting = 65;
327 
328     int ifdepth;                  // current #if-#else-#endif nesting in the cpp.c file (pre-processor)
329     bool elseSeen[maxIfNesting];  // Keep a track of whether an else has been seen at a particular depth
330     int elsetracker;              // #if-#else and #endif constructs...Counter.
331 
332     class tMacroInput : public tInput {
333     public:
tMacroInput(TPpContext * pp)334         tMacroInput(TPpContext* pp) : tInput(pp), prepaste(false), postpaste(false) { }
~tMacroInput()335         virtual ~tMacroInput()
336         {
337             for (size_t i = 0; i < args.size(); ++i)
338                 delete args[i];
339             for (size_t i = 0; i < expandedArgs.size(); ++i)
340                 delete expandedArgs[i];
341         }
342 
343         virtual int scan(TPpToken*) override;
getch()344         virtual int getch() override { assert(0); return EndOfInput; }
ungetch()345         virtual void ungetch() override { assert(0); }
peekPasting()346         bool peekPasting() override { return prepaste; }
endOfReplacementList()347         bool endOfReplacementList() override { return mac->body.atEnd(); }
isMacroInput()348         bool isMacroInput() override { return true; }
349 
350         MacroSymbol *mac;
351         TVector<TokenStream*> args;
352         TVector<TokenStream*> expandedArgs;
353 
354     protected:
355         bool prepaste;         // true if we are just before ##
356         bool postpaste;        // true if we are right after ##
357     };
358 
359     class tMarkerInput : public tInput {
360     public:
tMarkerInput(TPpContext * pp)361         tMarkerInput(TPpContext* pp) : tInput(pp) { }
scan(TPpToken *)362         virtual int scan(TPpToken*) override
363         {
364             if (done)
365                 return EndOfInput;
366             done = true;
367 
368             return marker;
369         }
getch()370         virtual int getch() override { assert(0); return EndOfInput; }
ungetch()371         virtual void ungetch() override { assert(0); }
372         static const int marker = -3;
373     };
374 
375     class tZeroInput : public tInput {
376     public:
tZeroInput(TPpContext * pp)377         tZeroInput(TPpContext* pp) : tInput(pp) { }
378         virtual int scan(TPpToken*) override;
getch()379         virtual int getch() override { assert(0); return EndOfInput; }
ungetch()380         virtual void ungetch() override { assert(0); }
381     };
382 
383     std::vector<tInput*> inputStack;
384     bool errorOnVersion;
385     bool versionSeen;
386 
387     //
388     // from Pp.cpp
389     //
390 
391     // Used to obtain #include content.
392     TShader::Includer& includer;
393 
394     int CPPdefine(TPpToken * ppToken);
395     int CPPundef(TPpToken * ppToken);
396     int CPPelse(int matchelse, TPpToken * ppToken);
397     int extraTokenCheck(int atom, TPpToken* ppToken, int token);
398     int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
399     int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
400     int CPPif (TPpToken * ppToken);
401     int CPPifdef(int defined, TPpToken * ppToken);
402     int CPPinclude(TPpToken * ppToken);
403     int CPPline(TPpToken * ppToken);
404     int CPPerror(TPpToken * ppToken);
405     int CPPpragma(TPpToken * ppToken);
406     int CPPversion(TPpToken * ppToken);
407     int CPPextension(TPpToken * ppToken);
408     int readCPPline(TPpToken * ppToken);
409     int scanHeaderName(TPpToken* ppToken, char delimit);
410     TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay);
411     MacroExpandResult MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay);
412 
413     //
414     // From PpTokens.cpp
415     //
416     void pushTokenStreamInput(TokenStream&, bool pasting = false);
417     void UngetToken(int token, TPpToken*);
418 
419     class tTokenInput : public tInput {
420     public:
tTokenInput(TPpContext * pp,TokenStream * t,bool prepasting)421         tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting) : tInput(pp), tokens(t), lastTokenPastes(prepasting) { }
scan(TPpToken * ppToken)422         virtual int scan(TPpToken *ppToken) override { return tokens->getToken(pp->parseContext, ppToken); }
getch()423         virtual int getch() override { assert(0); return EndOfInput; }
ungetch()424         virtual void ungetch() override { assert(0); }
peekPasting()425         virtual bool peekPasting() override { return tokens->peekTokenizedPasting(lastTokenPastes); }
426     protected:
427         TokenStream* tokens;
428         bool lastTokenPastes;     // true if the last token in the input is to be pasted, rather than consumed as a token
429     };
430 
431     class tUngotTokenInput : public tInput {
432     public:
tUngotTokenInput(TPpContext * pp,int t,TPpToken * p)433         tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { }
434         virtual int scan(TPpToken *) override;
getch()435         virtual int getch() override { assert(0); return EndOfInput; }
ungetch()436         virtual void ungetch() override { assert(0); }
437     protected:
438         int token;
439         TPpToken lval;
440     };
441 
442     //
443     // From PpScanner.cpp
444     //
445     class tStringInput : public tInput {
446     public:
tStringInput(TPpContext * pp,TInputScanner & i)447         tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { }
448         virtual int scan(TPpToken*) override;
449 
450         // Scanner used to get source stream characters.
451         //  - Escaped newlines are handled here, invisibly to the caller.
452         //  - All forms of newline are handled, and turned into just a '\n'.
getch()453         int getch() override
454         {
455             int ch = input->get();
456 
457             if (ch == '\\') {
458                 // Move past escaped newlines, as many as sequentially exist
459                 do {
460                     if (input->peek() == '\r' || input->peek() == '\n') {
461                         bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment);
462                         if (! allowed && pp->inComment)
463                             return '\\';
464 
465                         // escape one newline now
466                         ch = input->get();
467                         int nextch = input->get();
468                         if (ch == '\r' && nextch == '\n')
469                             ch = input->get();
470                         else
471                             ch = nextch;
472                     } else
473                         return '\\';
474                 } while (ch == '\\');
475             }
476 
477             // handle any non-escaped newline
478             if (ch == '\r' || ch == '\n') {
479                 if (ch == '\r' && input->peek() == '\n')
480                     input->get();
481                 return '\n';
482             }
483 
484             return ch;
485         }
486 
487         // Scanner used to backup the source stream characters.  Newlines are
488         // handled here, invisibly to the caller, meaning have to undo exactly
489         // what getch() above does (e.g., don't leave things in the middle of a
490         // sequence of escaped newlines).
ungetch()491         void ungetch() override
492         {
493             input->unget();
494 
495             do {
496                 int ch = input->peek();
497                 if (ch == '\r' || ch == '\n') {
498                     if (ch == '\n') {
499                         // correct for two-character newline
500                         input->unget();
501                         if (input->peek() != '\r')
502                             input->get();
503                     }
504                     // now in front of a complete newline, move past an escape character
505                     input->unget();
506                     if (input->peek() == '\\')
507                         input->unget();
508                     else {
509                         input->get();
510                         break;
511                     }
512                 } else
513                     break;
514             } while (true);
515         }
516 
517     protected:
518         TInputScanner* input;
519     };
520 
521     // Holds a reference to included file data, as well as a
522     // prologue and an epilogue string. This can be scanned using the tInput
523     // interface and acts as a single source string.
524     class TokenizableIncludeFile : public tInput {
525     public:
526         // Copies prologue and epilogue. The includedFile must remain valid
527         // 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)528         TokenizableIncludeFile(const TSourceLoc& startLoc,
529                           const std::string& prologue,
530                           TShader::Includer::IncludeResult* includedFile,
531                           const std::string& epilogue,
532                           TPpContext* pp)
533             : tInput(pp),
534               prologue_(prologue),
535               epilogue_(epilogue),
536               includedFile_(includedFile),
537               scanner(3, strings, lengths, nullptr, 0, 0, true),
538               prevScanner(nullptr),
539               stringInput(pp, scanner)
540         {
541               strings[0] = prologue_.data();
542               strings[1] = includedFile_->headerData;
543               strings[2] = epilogue_.data();
544 
545               lengths[0] = prologue_.size();
546               lengths[1] = includedFile_->headerLength;
547               lengths[2] = epilogue_.size();
548 
549               scanner.setLine(startLoc.line);
550               scanner.setString(startLoc.string);
551 
552               scanner.setFile(startLoc.name->c_str(), 0);
553               scanner.setFile(startLoc.name->c_str(), 1);
554               scanner.setFile(startLoc.name->c_str(), 2);
555         }
556 
557         // tInput methods:
scan(TPpToken * t)558         int scan(TPpToken* t) override { return stringInput.scan(t); }
getch()559         int getch() override { return stringInput.getch(); }
ungetch()560         void ungetch() override { stringInput.ungetch(); }
561 
notifyActivated()562         void notifyActivated() override
563         {
564             prevScanner = pp->parseContext.getScanner();
565             pp->parseContext.setScanner(&scanner);
566             pp->push_include(includedFile_);
567         }
568 
notifyDeleted()569         void notifyDeleted() override
570         {
571             pp->parseContext.setScanner(prevScanner);
572             pp->pop_include();
573         }
574 
575     private:
576         TokenizableIncludeFile& operator=(const TokenizableIncludeFile&);
577 
578         // Stores the prologue for this string.
579         const std::string prologue_;
580 
581         // Stores the epilogue for this string.
582         const std::string epilogue_;
583 
584         // Points to the IncludeResult that this TokenizableIncludeFile represents.
585         TShader::Includer::IncludeResult* includedFile_;
586 
587         // Will point to prologue_, includedFile_->headerData and epilogue_
588         // This is passed to scanner constructor.
589         // These do not own the storage and it must remain valid until this
590         // object has been destroyed.
591         const char* strings[3];
592         // Length of str_, passed to scanner constructor.
593         size_t lengths[3];
594         // Scans over str_.
595         TInputScanner scanner;
596         // The previous effective scanner before the scanner in this instance
597         // has been activated.
598         TInputScanner* prevScanner;
599         // Delegate object implementing the tInput interface.
600         tStringInput stringInput;
601     };
602 
603     int ScanFromString(char* s);
604     void missingEndifCheck();
605     int lFloatConst(int len, int ch, TPpToken* ppToken);
606     int characterLiteral(TPpToken* ppToken);
607 
push_include(TShader::Includer::IncludeResult * result)608     void push_include(TShader::Includer::IncludeResult* result)
609     {
610         currentSourceFile = result->headerName;
611         includeStack.push(result);
612     }
613 
pop_include()614     void pop_include()
615     {
616         TShader::Includer::IncludeResult* include = includeStack.top();
617         includeStack.pop();
618         includer.releaseInclude(include);
619         if (includeStack.empty()) {
620             currentSourceFile = rootFileName;
621         } else {
622             currentSourceFile = includeStack.top()->headerName;
623         }
624     }
625 
626     bool inComment;
627     std::string rootFileName;
628     std::stack<TShader::Includer::IncludeResult*> includeStack;
629     std::string currentSourceFile;
630 
631     std::istringstream strtodStream;
632 };
633 
634 } // end namespace glslang
635 
636 #endif  // PPCONTEXT_H
637