1 /****************************************************************************\
2 Copyright (c) 2002, NVIDIA Corporation.
4 NVIDIA Corporation("NVIDIA") supplies this software to you in
5 consideration of your agreement to the following terms, and your use,
6 installation, modification or redistribution of this NVIDIA software
7 constitutes acceptance of these terms. If you do not agree with these
8 terms, please do not use, install, modify or redistribute this NVIDIA
11 In consideration of your agreement to abide by the following terms, and
12 subject to these terms, NVIDIA grants you a personal, non-exclusive
13 license, under NVIDIA's copyrights in this original NVIDIA software (the
14 "NVIDIA Software"), to use, reproduce, modify and redistribute the
15 NVIDIA Software, with or without modifications, in source and/or binary
16 forms; provided that if you redistribute the NVIDIA Software, you must
17 retain the copyright notice of NVIDIA, this notice and the following
18 text and disclaimers in all such redistributions of the NVIDIA Software.
19 Neither the name, trademarks, service marks nor logos of NVIDIA
20 Corporation may be used to endorse or promote products derived from the
21 NVIDIA Software without specific prior written permission from NVIDIA.
22 Except as expressly stated in this notice, no other rights or licenses
23 express or implied, are granted by NVIDIA herein, including but not
24 limited to any patent rights that may be infringed by your derivative
25 works or by other works in which the NVIDIA Software may be
26 incorporated. No hardware is licensed hereunder.
28 THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
29 WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
30 INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
31 NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
32 ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
35 IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
36 INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
37 TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
38 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
39 OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
40 NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
41 TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
42 NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 \****************************************************************************/
57 #define isinff(x) (((*(int *)&(x) & 0x7f800000L)==0x7f800000L) && \
58 ((*(int *)&(x) & 0x007fffffL)==0000000000L))
61 #include "compiler/preprocessor/slglobals.h"
62 #include "compiler/util.h"
64 typedef struct StringInputSrc {
69 static int eof_scan(InputSrc *is, yystypepp * yylvalpp)
74 static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) {}
76 static InputSrc eof_inputsrc = { 0, &eof_scan, &eof_scan, &noop };
78 static int byte_scan(InputSrc *, yystypepp * yylvalpp);
83 #define DBG_BREAKPOINT() __asm int 3
84 #elif defined(_M_AMD64)
85 #define DBG_BREAKPOINT() assert(!"Dbg_Breakpoint");
87 #define DBG_BREAKPOINT()
90 #if defined(_MSC_VER) && !defined(_M_AMD64)
91 __int64 RDTSC ( void ) {
97 __asm mov dword ptr v, eax
98 __asm mov dword ptr v+4, edx
105 int InitScanner(CPPStruct *cpp)
107 // Add various atoms needed by the CPP line scanner:
111 cpp->mostRecentToken = 0;
112 cpp->tokenLoc = &cpp->ltokenLoc;
114 cpp->ltokenLoc.file = 0;
115 cpp->ltokenLoc.line = 0;
117 cpp->currentInput = &eof_inputsrc;
118 cpp->previous_token = '\n';
119 cpp->pastFirstStatement = 0;
124 int FreeScanner(void)
131 * takes care of reading from multiple strings.
132 * returns the next-char from the input stream.
133 * returns EOF when the complete shader is parsed.
135 static int str_getch(StringInputSrc *in)
139 if (*in->p == '\n') {
145 if(++(cpp->PaWhichStr) < cpp->PaArgc){
147 SetStringNumber(cpp->PaWhichStr);
149 ScanFromString(cpp->PaArgv[cpp->PaWhichStr]);
150 in=(StringInputSrc*)cpp->currentInput;
154 cpp->currentInput = in->base.prev;
162 static void str_ungetch(StringInputSrc *in, int ch, yystypepp *type) {
163 if (in->p[-1] == ch)in->p--;
165 *(in->p)='\0'; //this would take care of shifting to the previous string.
174 int ScanFromString(const char *s)
177 StringInputSrc *in = malloc(sizeof(StringInputSrc));
178 memset(in, 0, sizeof(StringInputSrc));
181 in->base.scan = byte_scan;
182 in->base.getch = (int (*)(InputSrc *, yystypepp *))str_getch;
183 in->base.ungetch = (void (*)(InputSrc *, int, yystypepp *))str_ungetch;
184 in->base.prev = cpp->currentInput;
185 cpp->currentInput = &in->base;
191 ///////////////////////////////////////////////////////////////////////////////////////////////
192 /////////////////////////////////// Floating point constants: /////////////////////////////////
193 ///////////////////////////////////////////////////////////////////////////////////////////////
195 #define APPEND_CHAR_S(ch, str, len, max_len) \
196 if (len < max_len) { \
198 } else if (!alreadyComplained) { \
199 CPPErrorToInfoLog("BUFFER OVERFLOW"); \
200 alreadyComplained = 1; \
204 * lFloatConst() - Scan a floating point constant. Assumes that the scanner
205 * has seen at least one digit, followed by either a decimal '.' or the
208 * len - length of string already copied into yylvalpp->symbol_name.
211 static int lFloatConst(int ch, int len, yystypepp * yylvalpp)
213 int alreadyComplained = 0;
214 assert((ch == '.') || (ch == 'e') || (ch == 'E'));
218 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
219 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
220 } while (ch >= '0' && ch <= '9');
224 if (ch == 'e' || ch == 'E') {
225 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
226 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
228 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
229 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
230 } else if (ch == '-') {
231 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
232 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
234 if (ch >= '0' && ch <= '9') {
235 while (ch >= '0' && ch <= '9') {
236 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
237 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
240 CPPErrorToInfoLog("EXPONENT INVALID");
243 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
245 assert(len <= MAX_SYMBOL_NAME_LEN);
246 yylvalpp->symbol_name[len] = '\0';
247 yylvalpp->sc_fval = (float) atof_dot(yylvalpp->symbol_name);
248 if (isinff(yylvalpp->sc_fval)) {
249 CPPErrorToInfoLog("FLOAT CONSTANT OVERFLOW");
251 return CPP_FLOATCONSTANT;
254 ///////////////////////////////////////////////////////////////////////////////////////////////
255 ///////////////////////////////////////// Normal Scanner //////////////////////////////////////
256 ///////////////////////////////////////////////////////////////////////////////////////////////
258 static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
260 char string_val[MAX_STRING_LEN + 1];
261 int alreadyComplained = 0;
262 int len, ch, ii, ival = 0;
265 yylvalpp->sc_int = 0;
266 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
268 while (ch == ' ' || ch == '\t' || ch == '\r') {
269 yylvalpp->sc_int = 1;
270 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
273 cpp->ltokenLoc.file = cpp->currentInput->name;
274 cpp->ltokenLoc.line = cpp->currentInput->line;
275 alreadyComplained = 0;
279 return ch; // Single character token
282 case 'A': case 'B': case 'C': case 'D': case 'E':
283 case 'F': case 'G': case 'H': case 'I': case 'J':
284 case 'K': case 'L': case 'M': case 'N': case 'O':
285 case 'P': case 'Q': case 'R': case 'S': case 'T':
286 case 'U': case 'V': case 'W': case 'X': case 'Y':
288 case 'a': case 'b': case 'c': case 'd': case 'e':
289 case 'f': case 'g': case 'h': case 'i': case 'j':
290 case 'k': case 'l': case 'm': case 'n': case 'o':
291 case 'p': case 'q': case 'r': case 's': case 't':
292 case 'u': case 'v': case 'w': case 'x': case 'y':
295 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
296 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
297 } while ((ch >= 'a' && ch <= 'z') ||
298 (ch >= 'A' && ch <= 'Z') ||
299 (ch >= '0' && ch <= '9') ||
301 assert(len <= MAX_SYMBOL_NAME_LEN);
302 yylvalpp->symbol_name[len] = '\0';
303 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
304 yylvalpp->sc_ident = LookUpAddString(atable, yylvalpp->symbol_name);
305 return CPP_IDENTIFIER;
308 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
309 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
310 if (ch == 'x' || ch == 'X') { // hexadecimal integer constants
311 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
312 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
313 if ((ch >= '0' && ch <= '9') ||
314 (ch >= 'A' && ch <= 'F') ||
315 (ch >= 'a' && ch <= 'f'))
319 if ((ival <= 0x0fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
320 yylvalpp->symbol_name[len++] = ch;
321 if (ch >= '0' && ch <= '9') {
323 } else if (ch >= 'A' && ch <= 'F') {
328 ival = (ival << 4) | ii;
329 } else if (!alreadyComplained) {
330 CPPErrorToInfoLog("HEX CONSTANT OVERFLOW");
331 alreadyComplained = 1;
333 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
334 } while ((ch >= '0' && ch <= '9') ||
335 (ch >= 'A' && ch <= 'F') ||
336 (ch >= 'a' && ch <= 'f'));
338 CPPErrorToInfoLog("HEX CONSTANT INVALID");
340 assert(len <= MAX_SYMBOL_NAME_LEN);
341 yylvalpp->symbol_name[len] = '\0';
342 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
343 yylvalpp->sc_int = ival;
344 return CPP_INTCONSTANT;
345 } else if (ch >= '0' && ch <= '7') { // octal integer constants
348 if ((ival <= 0x1fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
349 yylvalpp->symbol_name[len++] = ch;
351 ival = (ival << 3) | ii;
352 } else if (!alreadyComplained) {
353 CPPErrorToInfoLog("OCT CONSTANT OVERFLOW");
354 alreadyComplained = 1;
356 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
357 } while (ch >= '0' && ch <= '7');
358 if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E')
359 return lFloatConst(ch, len, yylvalpp);
360 assert(len <= MAX_SYMBOL_NAME_LEN);
361 yylvalpp->symbol_name[len] = '\0';
362 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
363 yylvalpp->sc_int = ival;
364 return CPP_INTCONSTANT;
366 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
370 case '1': case '2': case '3': case '4':
371 case '5': case '6': case '7': case '8': case '9':
373 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
374 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
375 } while (ch >= '0' && ch <= '9');
376 if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') {
377 return lFloatConst(ch, len, yylvalpp);
379 assert(len <= MAX_SYMBOL_NAME_LEN);
380 yylvalpp->symbol_name[len] = '\0';
381 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
383 for (ii = 0; ii < len; ii++) {
384 ch = yylvalpp->symbol_name[ii] - '0';
386 if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) {
387 CPPErrorToInfoLog("INTEGER CONSTANT OVERFLOW");
391 yylvalpp->sc_int = ival;
393 strcpy(yylvalpp->symbol_name,"0");
394 return CPP_INTCONSTANT;
398 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
401 } else if (ch == '=') {
402 return CPP_SUB_ASSIGN;
404 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
408 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
411 } else if (ch == '=') {
412 return CPP_ADD_ASSIGN;
414 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
418 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
420 return CPP_MUL_ASSIGN;
422 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
426 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
428 return CPP_MOD_ASSIGN;
429 } else if (ch == '>'){
430 return CPP_RIGHT_BRACE;
432 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
436 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
438 return CPP_RIGHT_BRACKET;
440 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
444 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
449 return CPP_XOR_ASSIGN;
451 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
457 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
461 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
465 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
469 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
473 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
478 return CPP_OR_ASSIGN;
480 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
485 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
490 return CPP_AND_ASSIGN;
492 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
497 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
499 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
501 return CPP_LEFT_ASSIGN;
503 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
511 return CPP_LEFT_BRACE;
513 return CPP_LEFT_BRACKET;
515 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
521 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
523 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
525 return CPP_RIGHT_ASSIGN;
527 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
534 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
539 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
540 if (ch >= '0' && ch <= '9') {
541 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
542 return lFloatConst('.', 0, yylvalpp);
545 return -1; // Special EOF hack
547 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
552 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
555 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
556 } while (ch != '\n' && ch != EOF);
560 } else if (ch == '*') {
562 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
565 if (ch == '\n') nlcount++;
567 CPPErrorToInfoLog("EOF IN COMMENT");
570 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
572 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
574 CPPErrorToInfoLog("EOF IN COMMENT");
581 // Go try it again...
582 } else if (ch == '=') {
583 return CPP_DIV_ASSIGN;
585 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
590 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
591 while (ch != '"' && ch != '\n' && ch != EOF) {
593 CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
596 APPEND_CHAR_S(ch, string_val, len, MAX_STRING_LEN);
597 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
599 assert(len <= MAX_STRING_LEN);
600 string_val[len] = '\0';
602 yylvalpp->sc_ident = LookUpAddString(atable, string_val);
603 return CPP_STRCONSTANT;
605 CPPErrorToInfoLog("EOL IN STRING");
613 int yylex_CPP(char* buf, int maxSize)
620 char* tokenString = 0;
621 token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp);
625 if (cpp->previous_token == '\n'|| cpp->previous_token == 0) {
626 token = readCPPline(&yylvalpp);
631 CPPErrorToInfoLog("preprocessor command must not be preceded by any other statement in that line");
635 cpp->previous_token = token;
637 if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp.sc_ident, &yylvalpp)) {
638 cpp->pastFirstStatement = 1;
644 cpp->pastFirstStatement = 1;
646 if (token == CPP_IDENTIFIER) {
647 tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident);
648 } else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
649 tokenString = yylvalpp.symbol_name;
651 tokenString = GetStringOfAtom(atable,token);
655 int len = strlen(tokenString);
656 cpp->tokensBeforeEOF = 1;
657 if (len >= maxSize) {
659 } else if (len > 0) {
660 strcpy(buf, tokenString);
671 //Checks if the token just read is EOF or not.
672 int check_EOF(int token)
676 CPPErrorToInfoLog("#endif missing!! Compilation stopped");
684 ///////////////////////////////////////////////////////////////////////////////////////////////
685 /////////////////////////////////////// End of scanner.c //////////////////////////////////////
686 ///////////////////////////////////////////////////////////////////////////////////////////////