glslang: Fix over 100 warnings from MSVC warning level 4.
[platform/upstream/glslang.git] / glslang / MachineIndependent / preprocessor / PpContext.h
1 //
2 //Copyright (C) 2013 LunarG, Inc.
3 //All rights reserved.
4 //
5 //Redistribution and use in source and binary forms, with or without
6 //modification, are permitted provided that the following conditions
7 //are met:
8 //
9 //    Redistributions of source code must retain the above copyright
10 //    notice, this list of conditions and the following disclaimer.
11 //
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.
16 //
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.
20 //
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.
33 //
34 /****************************************************************************\
35 Copyright (c) 2002, NVIDIA Corporation.
36
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
42 software.
43
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. 
60
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
66 PRODUCTS.
67
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 \****************************************************************************/
77
78 #ifndef PPCONTEXT_H
79 #define PPCONTEXT_H
80
81 #include "../ParseHelper.h"
82
83 namespace glslang {
84
85 class TPpToken {
86 public:
87     TPpToken() : token(0), ival(0), space(false), dval(0.0), atom(0)
88     { 
89         loc.line = 0; 
90         loc.string = 0; 
91         name[0] = 0;
92     }
93
94     bool operator==(const TPpToken& right)
95     {
96         return token == right.token && atom == right.atom &&
97                ival == right.ival && dval == right.dval &&
98                strcmp(name, right.name) == 0;
99     }
100     bool operator!=(const TPpToken& right) { return ! operator==(right); }
101
102     static const int maxTokenLength = 1024;
103
104     TSourceLoc loc;
105     int    token;
106     bool   space;  // true if a space (for white space or a removed comment) should also be recognized, in front of the token returned
107     int    ival;
108     double dval;
109     int    atom;
110     char   name[maxTokenLength+1];
111 };
112
113 class TInputScanner;
114
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.
118 class TPpContext {
119 public:
120     TPpContext(TParseContext&);
121     virtual ~TPpContext();
122
123     void setPreamble(const char* preamble, size_t length);
124
125     const char* tokenize(TPpToken* ppToken);
126
127     class tInput {
128     public:
129         tInput(TPpContext* p) : done(false), pp(p) { }
130         virtual ~tInput() { }
131
132         virtual int scan(TPpToken*) = 0;
133         virtual int getch() = 0;
134         virtual void ungetch() = 0;
135
136         static const int endOfInput = -2;
137
138     protected:
139         bool done;
140         TPpContext* pp;
141     };
142
143     void setInput(TInputScanner& input, bool versionWillBeError);
144
145     void pushInput(tInput* in)
146     {
147         inputStack.push_back(in);
148     }
149     void popInput()
150     {
151         delete inputStack.back();
152         inputStack.pop_back();
153     }
154
155     struct TokenStream {
156         TokenStream() : current(0) { }
157         TVector<unsigned char> data;
158         size_t current;
159     };
160
161     struct MemoryPool {
162         struct chunk        *next;
163         uintptr_t           free, end;
164         size_t              chunksize;
165         uintptr_t           alignmask;
166     };
167
168     //
169     // From Pp.cpp
170     //
171
172     struct MacroSymbol {
173         MacroSymbol() : argc(0), args(0), body(0), busy(0), undef(0) { }
174         int argc;
175         int *args;
176         TokenStream *body;
177         unsigned busy:1;
178         unsigned undef:1;
179     };
180
181     struct Symbol {
182         int atom;
183         MacroSymbol mac;
184     };
185
186     struct SymbolList {
187         struct SymbolList_Rec *next;
188         Symbol *symb;
189     };
190
191     MemoryPool *pool;
192     typedef std::map<int, Symbol*> TSymbolMap;
193     TSymbolMap symbols; // this has light use... just defined macros
194
195 protected:
196     TPpContext(TPpContext&);
197     TPpContext& operator=(TPpContext&);
198
199     char*   preamble;               // string to parse, all before line 1 of string 0, it is 0 if no preamble
200     int     preambleLength;
201     char**  strings;                // official strings of shader, starting a string 0 line 1
202     size_t* lengths;
203     int     numStrings;             // how many official strings there are
204     int     currentString;          // which string we're currently parsing  (-1 for preamble)
205
206     // Scanner data:
207     int previous_token;
208     TParseContext& parseContext;
209
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)
214     {
215         int token = EOF;
216
217         while (! inputStack.empty()) {
218             token = inputStack.back()->scan(ppToken);
219             if (token != tInput::endOfInput)
220                 break;
221             popInput();
222         }
223
224         if (token == tInput::endOfInput)
225             return EOF;
226
227         return token;
228     }
229     int  getChar() { return inputStack.back()->getch(); }
230     void ungetChar() { inputStack.back()->ungetch(); }
231
232     static const int maxMacroArgs = 64;
233     static const int maxIfNesting = 64;
234
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.
238     const char* ErrMsg;
239
240     class tMacroInput : public tInput {
241     public:
242         tMacroInput(TPpContext* pp) : tInput(pp) { }
243         virtual ~tMacroInput()
244         {
245             for (size_t i = 0; i < args.size(); ++i)
246                 delete args[i];
247         }
248
249         virtual int scan(TPpToken*);
250         virtual int getch() { assert(0); return endOfInput; }
251         virtual void ungetch() { assert(0); }
252         MacroSymbol *mac;
253         TVector<TokenStream*> args;
254     };
255
256     class tMarkerInput : public tInput {
257     public:
258         tMarkerInput(TPpContext* pp) : tInput(pp) { }
259         virtual int scan(TPpToken*)
260         {
261             if (done)
262                 return endOfInput;
263             done = true;
264
265             return marker;
266         }
267         virtual int getch() { assert(0); return endOfInput; }
268         virtual void ungetch() { assert(0); }
269         static const int marker = -3;
270     };
271
272     class tZeroInput : public tInput {
273     public:
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); }
278     };
279
280     std::vector<tInput*> inputStack;
281     bool errorOnVersion;
282     bool versionSeen;
283
284     //
285     // from Pp.cpp
286     //
287     int bindAtom;
288     int constAtom;
289     int defaultAtom;
290     int defineAtom;
291     int definedAtom;
292     int elseAtom;
293     int elifAtom;
294     int endifAtom;
295     int ifAtom;
296     int ifdefAtom;
297     int ifndefAtom;
298     int includeAtom;
299     int lineAtom;
300     int pragmaAtom;
301     int texunitAtom;
302     int undefAtom;
303     int errorAtom;
304     int __LINE__Atom;
305     int __FILE__Atom;
306     int __VERSION__Atom;
307     int versionAtom;
308     int coreAtom;
309     int compatibilityAtom;
310     int esAtom;
311     int extensionAtom;
312     TSourceLoc ifloc; /* outermost #if */
313
314     int InitCPP();
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);
331
332     //
333     // from PpSymbols.cpp
334     //
335     Symbol *NewSymbol(int name);
336     Symbol *AddSymbol(int atom);
337     Symbol *LookUpSymbol(int atom);
338
339     //
340     // From PpTokens.cpp
341     //
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);
350     
351     class tTokenInput : public tInput {
352     public:
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); }
357     protected:
358         TokenStream *tokens;
359     };
360
361     class tUngotTokenInput : public tInput {
362     public:
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); }
367     protected:
368         int token;
369         TPpToken lval;
370     };
371
372     //
373     // From PpScanner.cpp
374     //
375     class tStringInput : public tInput {
376     public:
377         tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { }
378         virtual int scan(TPpToken*);
379
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'.
383         int getch()
384         {
385             int ch = input->get();
386
387             if (ch == '\\') {
388                 // Move past escaped newlines, as many as sequentially exist
389                 do {
390                     if (input->peek() == '\r' || input->peek() == '\n') {
391                         bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment);
392                         if (! allowed && pp->inComment)
393                             return '\\';
394
395                         // escape one newline now
396                         ch = input->get();
397                         int nextch = input->get();
398                         if (ch == '\r' && nextch == '\n')
399                             ch = input->get();
400                         else
401                             ch = nextch;
402                     } else
403                         return '\\';
404                 } while (ch == '\\');
405             }
406     
407             // handle any non-escaped newline
408             if (ch == '\r' || ch == '\n') {
409                 if (ch == '\r' && input->peek() == '\n')
410                     ch = input->get();
411                 return '\n';
412             }
413
414             return ch;
415         }
416
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).
421         void ungetch()
422         {
423             input->unget();
424
425             do {
426                 int ch = input->peek();
427                 if (ch == '\r' || ch == '\n') {
428                     if (ch == '\n') {
429                         // correct for two-character newline
430                         input->unget();
431                         if (input->peek() != '\r')
432                             input->get();
433                     }
434                     // now in front of a complete newline, move past an escape character
435                     input->unget();
436                     if (input->peek() == '\\')
437                         input->unget();
438                     else {
439                         input->get();
440                         break;
441                     }
442                 } else
443                     break;
444             } while (true);
445         }
446
447     protected:
448         TInputScanner* input;
449     };
450
451     int InitScanner();
452     int ScanFromString(char* s);
453     void missingEndifCheck();
454     int lFloatConst(int len, int ch, TPpToken* ppToken);
455
456     bool inComment;
457
458     //
459     // From PpAtom.cpp
460     //
461     typedef std::map<const TString, int> TAtomMap;
462     typedef TVector<const TString*> TStringMap;
463     TAtomMap atomMap;
464     TStringMap stringMap;
465     int nextAtom;
466     void InitAtomTable();
467     int AddAtomFixed(const char* s, int atom);
468     int LookUpAddString(const char* s);
469     const char* GetAtomString(int atom);
470
471     //
472     // From PpMemory.cpp
473     //
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);
478 };
479
480 } // end namespace glslang
481
482 #endif  // PPCONTEXT_H