• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 // Copyright (C) 2013 LunarG, Inc.
4 // Copyright (C) 2015-2018 Google, Inc.
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions
10 // are met:
11 //
12 //    Redistributions of source code must retain the above copyright
13 //    notice, this list of conditions and the following disclaimer.
14 //
15 //    Redistributions in binary form must reproduce the above
16 //    copyright notice, this list of conditions and the following
17 //    disclaimer in the documentation and/or other materials provided
18 //    with the distribution.
19 //
20 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
21 //    contributors may be used to endorse or promote products derived
22 //    from this software without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 // POSSIBILITY OF SUCH DAMAGE.
36 //
37 /****************************************************************************\
38 Copyright (c) 2002, NVIDIA Corporation.
39 
40 NVIDIA Corporation("NVIDIA") supplies this software to you in
41 consideration of your agreement to the following terms, and your use,
42 installation, modification or redistribution of this NVIDIA software
43 constitutes acceptance of these terms.  If you do not agree with these
44 terms, please do not use, install, modify or redistribute this NVIDIA
45 software.
46 
47 In consideration of your agreement to abide by the following terms, and
48 subject to these terms, NVIDIA grants you a personal, non-exclusive
49 license, under NVIDIA's copyrights in this original NVIDIA software (the
50 "NVIDIA Software"), to use, reproduce, modify and redistribute the
51 NVIDIA Software, with or without modifications, in source and/or binary
52 forms; provided that if you redistribute the NVIDIA Software, you must
53 retain the copyright notice of NVIDIA, this notice and the following
54 text and disclaimers in all such redistributions of the NVIDIA Software.
55 Neither the name, trademarks, service marks nor logos of NVIDIA
56 Corporation may be used to endorse or promote products derived from the
57 NVIDIA Software without specific prior written permission from NVIDIA.
58 Except as expressly stated in this notice, no other rights or licenses
59 express or implied, are granted by NVIDIA herein, including but not
60 limited to any patent rights that may be infringed by your derivative
61 works or by other works in which the NVIDIA Software may be
62 incorporated. No hardware is licensed hereunder.
63 
64 THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
65 WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
66 INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
67 NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
68 ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
69 PRODUCTS.
70 
71 IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
72 INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
73 TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
74 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
75 OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
76 NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
77 TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
78 NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
79 \****************************************************************************/
80 
81 //
82 // For recording and playing back the stream of tokens in a macro definition.
83 //
84 
85 #ifndef _CRT_SECURE_NO_WARNINGS
86 #define _CRT_SECURE_NO_WARNINGS
87 #endif
88 #if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/)
89 #define snprintf sprintf_s
90 #endif
91 
92 #include <cassert>
93 #include <cstdlib>
94 #include <cstring>
95 #include <cctype>
96 
97 #include "PpContext.h"
98 #include "PpTokens.h"
99 
100 namespace glslang {
101 
102 
103 namespace {
104 
105     // When recording (and playing back) should the backing name string
106     // be saved (restored)?
SaveName(int atom)107     bool SaveName(int atom)
108     {
109         switch (atom) {
110         case PpAtomIdentifier:
111         case PpAtomConstString:
112         case PpAtomConstInt:
113         case PpAtomConstUint:
114         case PpAtomConstInt64:
115         case PpAtomConstUint64:
116     #ifdef AMD_EXTENSIONS
117         case PpAtomConstInt16:
118         case PpAtomConstUint16:
119     #endif
120         case PpAtomConstFloat:
121         case PpAtomConstDouble:
122         case PpAtomConstFloat16:
123             return true;
124         default:
125             return false;
126         }
127     }
128 
129     // When recording (and playing back) should the numeric value
130     // be saved (restored)?
SaveValue(int atom)131     bool SaveValue(int atom)
132     {
133         switch (atom) {
134         case PpAtomConstInt:
135         case PpAtomConstUint:
136         case PpAtomConstInt64:
137         case PpAtomConstUint64:
138     #ifdef AMD_EXTENSIONS
139         case PpAtomConstInt16:
140         case PpAtomConstUint16:
141     #endif
142         case PpAtomConstFloat:
143         case PpAtomConstDouble:
144         case PpAtomConstFloat16:
145             return true;
146         default:
147             return false;
148         }
149     }
150 }
151 
152 // push onto back of stream
putSubtoken(char subtoken)153 void TPpContext::TokenStream::putSubtoken(char subtoken)
154 {
155     data.push_back(static_cast<unsigned char>(subtoken));
156 }
157 
158 // get the next token in stream
getSubtoken()159 int TPpContext::TokenStream::getSubtoken()
160 {
161     if (current < data.size())
162         return data[current++];
163     else
164         return EndOfInput;
165 }
166 
167 // back up one position in the stream
ungetSubtoken()168 void TPpContext::TokenStream::ungetSubtoken()
169 {
170     if (current > 0)
171         --current;
172 }
173 
174 // Add a complete token (including backing string) to the end of a list
175 // for later playback.
putToken(int atom,TPpToken * ppToken)176 void TPpContext::TokenStream::putToken(int atom, TPpToken* ppToken)
177 {
178     // save the atom
179     assert((atom & ~0xff) == 0);
180     putSubtoken(static_cast<char>(atom));
181 
182     // save the backing name string
183     if (SaveName(atom)) {
184         const char* s = ppToken->name;
185         while (*s)
186             putSubtoken(*s++);
187         putSubtoken(0);
188     }
189 
190     // save the numeric value
191     if (SaveValue(atom)) {
192         const char* n = reinterpret_cast<const char*>(&ppToken->i64val);
193         for (size_t i = 0; i < sizeof(ppToken->i64val); ++i)
194             putSubtoken(*n++);
195     }
196 }
197 
198 // Read the next token from a token stream.
199 // (Not the source stream, but a stream used to hold a tokenized macro).
getToken(TParseContextBase & parseContext,TPpToken * ppToken)200 int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken *ppToken)
201 {
202     // get the atom
203     int atom = getSubtoken();
204     if (atom == EndOfInput)
205         return atom;
206 
207     // init the token
208     ppToken->clear();
209     ppToken->loc = parseContext.getCurrentLoc();
210 
211     // get the backing name string
212     if (SaveName(atom)) {
213         int ch = getSubtoken();
214         int len = 0;
215         while (ch != 0 && ch != EndOfInput) {
216             if (len < MaxTokenLength) {
217                 ppToken->name[len] = (char)ch;
218                 len++;
219                 ch = getSubtoken();
220             } else {
221                 parseContext.error(ppToken->loc, "token too long", "", "");
222                 break;
223             }
224         }
225         ppToken->name[len] = 0;
226     }
227 
228     // Check for ##, unless the current # is the last character
229     if (atom == '#') {
230         if (current < data.size()) {
231             if (getSubtoken() == '#') {
232                 parseContext.requireProfile(ppToken->loc, ~EEsProfile, "token pasting (##)");
233                 parseContext.profileRequires(ppToken->loc, ~EEsProfile, 130, 0, "token pasting (##)");
234                 atom = PpAtomPaste;
235             } else
236                 ungetSubtoken();
237         }
238     }
239 
240     // get the numeric value
241     if (SaveValue(atom)) {
242         char* n = reinterpret_cast<char*>(&ppToken->i64val);
243         for (size_t i = 0; i < sizeof(ppToken->i64val); ++i)
244             *n++ = (char)getSubtoken();
245     }
246 
247     return atom;
248 }
249 
250 // We are pasting if
251 //   1. we are preceding a pasting operator within this stream
252 // or
253 //   2. the entire macro is preceding a pasting operator (lastTokenPastes)
254 //      and we are also on the last token
peekTokenizedPasting(bool lastTokenPastes)255 bool TPpContext::TokenStream::peekTokenizedPasting(bool lastTokenPastes)
256 {
257     // 1. preceding ##?
258 
259     size_t savePos = current;
260     int subtoken;
261     // skip white space
262     do {
263         subtoken = getSubtoken();
264     } while (subtoken == ' ');
265     current = savePos;
266     if (subtoken == PpAtomPaste)
267         return true;
268 
269     // 2. last token and we've been told after this there will be a ##
270 
271     if (! lastTokenPastes)
272         return false;
273     // Getting here means the last token will be pasted, after this
274 
275     // Are we at the last non-whitespace token?
276     savePos = current;
277     bool moreTokens = false;
278     do {
279         subtoken = getSubtoken();
280         if (subtoken == EndOfInput)
281             break;
282         if (subtoken != ' ') {
283             moreTokens = true;
284             break;
285         }
286     } while (true);
287     current = savePos;
288 
289     return !moreTokens;
290 }
291 
292 // See if the next non-white-space tokens are two consecutive #
peekUntokenizedPasting()293 bool TPpContext::TokenStream::peekUntokenizedPasting()
294 {
295     // don't return early, have to restore this
296     size_t savePos = current;
297 
298     // skip white-space
299     int subtoken;
300     do {
301         subtoken = getSubtoken();
302     } while (subtoken == ' ');
303 
304     // check for ##
305     bool pasting = false;
306     if (subtoken == '#') {
307         subtoken = getSubtoken();
308         if (subtoken == '#')
309             pasting = true;
310     }
311 
312     current = savePos;
313 
314     return pasting;
315 }
316 
pushTokenStreamInput(TokenStream & ts,bool prepasting)317 void TPpContext::pushTokenStreamInput(TokenStream& ts, bool prepasting)
318 {
319     pushInput(new tTokenInput(this, &ts, prepasting));
320     ts.reset();
321 }
322 
scan(TPpToken * ppToken)323 int TPpContext::tUngotTokenInput::scan(TPpToken* ppToken)
324 {
325     if (done)
326         return EndOfInput;
327 
328     int ret = token;
329     *ppToken = lval;
330     done = true;
331 
332     return ret;
333 }
334 
UngetToken(int token,TPpToken * ppToken)335 void TPpContext::UngetToken(int token, TPpToken* ppToken)
336 {
337     pushInput(new tUngotTokenInput(this, token, ppToken));
338 }
339 
340 } // end namespace glslang
341