blob: ab7019b04b7c0257b1543ba31383a363179c9fc1 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001/****************************************************************************\
2Copyright (c) 2002, NVIDIA Corporation.
3
4NVIDIA Corporation("NVIDIA") supplies this software to you in
5consideration of your agreement to the following terms, and your use,
6installation, modification or redistribution of this NVIDIA software
7constitutes acceptance of these terms. If you do not agree with these
8terms, please do not use, install, modify or redistribute this NVIDIA
9software.
10
11In consideration of your agreement to abide by the following terms, and
12subject to these terms, NVIDIA grants you a personal, non-exclusive
13license, under NVIDIA's copyrights in this original NVIDIA software (the
14"NVIDIA Software"), to use, reproduce, modify and redistribute the
15NVIDIA Software, with or without modifications, in source and/or binary
16forms; provided that if you redistribute the NVIDIA Software, you must
17retain the copyright notice of NVIDIA, this notice and the following
18text and disclaimers in all such redistributions of the NVIDIA Software.
19Neither the name, trademarks, service marks nor logos of NVIDIA
20Corporation may be used to endorse or promote products derived from the
21NVIDIA Software without specific prior written permission from NVIDIA.
22Except as expressly stated in this notice, no other rights or licenses
23express or implied, are granted by NVIDIA herein, including but not
24limited to any patent rights that may be infringed by your derivative
25works or by other works in which the NVIDIA Software may be
26incorporated. No hardware is licensed hereunder.
27
28THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
29WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
30INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
31NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
32ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
33PRODUCTS.
34
35IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
36INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
37TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
38USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
39OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
40NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
41TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
42NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43\****************************************************************************/
44//
45// scanner.c
46//
47
alokp@chromium.org43668cd2010-10-20 20:55:53 +000048#include <assert.h>
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000049#include <stdarg.h>
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53
54#if 0
55 #include <ieeefp.h>
alokp@chromium.org43668cd2010-10-20 20:55:53 +000056#else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000057 #define isinff(x) (((*(int *)&(x) & 0x7f800000L)==0x7f800000L) && \
58 ((*(int *)&(x) & 0x007fffffL)==0000000000L))
59#endif
60
daniel@transgaming.come6842292010-04-20 18:52:50 +000061#include "compiler/preprocessor/slglobals.h"
daniel@transgaming.com91ed1492010-10-29 03:11:43 +000062#include "compiler/util.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000063
64typedef struct StringInputSrc {
65 InputSrc base;
66 char *p;
67} StringInputSrc;
68
69static int eof_scan(InputSrc *is, yystypepp * yylvalpp)
70{
71 return EOF;
72} // eof_scan
73
74static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) {}
75
76static InputSrc eof_inputsrc = { 0, &eof_scan, &eof_scan, &noop };
77
78static int byte_scan(InputSrc *, yystypepp * yylvalpp);
79
80#define EOL_SY '\n'
81
alokp@chromium.org01b666f2010-07-16 19:27:45 +000082#if defined(_MSC_VER)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000083 #define DBG_BREAKPOINT() __asm int 3
alokp@chromium.org01b666f2010-07-16 19:27:45 +000084#elif defined(_M_AMD64)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085 #define DBG_BREAKPOINT() assert(!"Dbg_Breakpoint");
alokp@chromium.org01b666f2010-07-16 19:27:45 +000086#else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000087 #define DBG_BREAKPOINT()
alokp@chromium.org01b666f2010-07-16 19:27:45 +000088#endif
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000089
alokp@chromium.org01b666f2010-07-16 19:27:45 +000090#if defined(_MSC_VER) && !defined(_M_AMD64)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000091 __int64 RDTSC ( void ) {
92
93 __int64 v;
94
95 __asm __emit 0x0f
96 __asm __emit 0x31
97 __asm mov dword ptr v, eax
98 __asm mov dword ptr v+4, edx
99
100 return v;
101 }
102#endif
103
104
105int InitScanner(CPPStruct *cpp)
106{
107 // Add various atoms needed by the CPP line scanner:
108 if (!InitCPP())
109 return 0;
110
111 cpp->mostRecentToken = 0;
112 cpp->tokenLoc = &cpp->ltokenLoc;
113
114 cpp->ltokenLoc.file = 0;
115 cpp->ltokenLoc.line = 0;
116
117 cpp->currentInput = &eof_inputsrc;
118 cpp->previous_token = '\n';
daniel@transgaming.comdec19e22010-04-29 03:35:42 +0000119 cpp->pastFirstStatement = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000120
121 return 1;
122} // InitScanner
123
124int FreeScanner(void)
125{
126 return (FreeCPP());
127}
128
129/*
130 * str_getch()
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.
134 */
135static int str_getch(StringInputSrc *in)
136{
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000137 for(;;){
138 if (*in->p){
139 if (*in->p == '\n') {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000140 in->base.line++;
141 IncLineNumber();
142 }
143 return *in->p++;
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000144 }
145 if(++(cpp->PaWhichStr) < cpp->PaArgc){
146 free(in);
147 SetStringNumber(cpp->PaWhichStr);
148 SetLineNumber(1);
149 ScanFromString(cpp->PaArgv[cpp->PaWhichStr]);
150 in=(StringInputSrc*)cpp->currentInput;
151 continue;
152 }
153 else{
154 cpp->currentInput = in->base.prev;
155 cpp->PaWhichStr=0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156 free(in);
157 return EOF;
158 }
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000159 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000160} // str_getch
161
162static void str_ungetch(StringInputSrc *in, int ch, yystypepp *type) {
163 if (in->p[-1] == ch)in->p--;
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000164 else {
165 *(in->p)='\0'; //this would take care of shifting to the previous string.
166 cpp->PaWhichStr--;
167 }
168 if (ch == '\n') {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000169 in->base.line--;
170 DecLineNumber();
171 }
172} // str_ungetch
173
alokp@chromium.org07620a52010-09-23 17:53:56 +0000174int ScanFromString(const char *s)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175{
176
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000177 StringInputSrc *in = malloc(sizeof(StringInputSrc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000178 memset(in, 0, sizeof(StringInputSrc));
kbr@chromium.org3bd9d902011-01-19 03:27:39 +0000179 in->p = (char*) s;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000180 in->base.line = 1;
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;
186
187 return 1;
188} // ScanFromString;
189
190
191///////////////////////////////////////////////////////////////////////////////////////////////
192/////////////////////////////////// Floating point constants: /////////////////////////////////
193///////////////////////////////////////////////////////////////////////////////////////////////
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000194
alokp@chromium.org88609092010-10-27 19:42:44 +0000195#define APPEND_CHAR_S(ch, str, len, max_len) \
196 if (len < max_len) { \
197 str[len++] = ch; \
198 } else if (!alreadyComplained) { \
199 CPPErrorToInfoLog("BUFFER OVERFLOW"); \
200 alreadyComplained = 1; \
201 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202
203/*
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
206 * letter 'e'.
alokp@chromium.org88609092010-10-27 19:42:44 +0000207 * ch - '.' or 'e'
208 * len - length of string already copied into yylvalpp->symbol_name.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000209 */
210
alokp@chromium.org88609092010-10-27 19:42:44 +0000211static int lFloatConst(int ch, int len, yystypepp * yylvalpp)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000212{
alokp@chromium.org88609092010-10-27 19:42:44 +0000213 int alreadyComplained = 0;
214 assert((ch == '.') || (ch == 'e') || (ch == 'E'));
215
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000216 if (ch == '.') {
alokp@chromium.org88609092010-10-27 19:42:44 +0000217 do {
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');
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221 }
222
223 // Exponent:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224 if (ch == 'e' || ch == 'E') {
alokp@chromium.org88609092010-10-27 19:42:44 +0000225 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000226 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
227 if (ch == '+') {
alokp@chromium.org88609092010-10-27 19:42:44 +0000228 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000229 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000230 } else if (ch == '-') {
alokp@chromium.org88609092010-10-27 19:42:44 +0000231 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000232 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
233 }
234 if (ch >= '0' && ch <= '9') {
235 while (ch >= '0' && ch <= '9') {
alokp@chromium.org88609092010-10-27 19:42:44 +0000236 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000237 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
238 }
239 } else {
alokp@chromium.org88609092010-10-27 19:42:44 +0000240 CPPErrorToInfoLog("EXPONENT INVALID");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242 }
alokp@chromium.org88609092010-10-27 19:42:44 +0000243 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
244
245 assert(len <= MAX_SYMBOL_NAME_LEN);
246 yylvalpp->symbol_name[len] = '\0';
daniel@transgaming.com91ed1492010-10-29 03:11:43 +0000247 yylvalpp->sc_fval = (float) atof_dot(yylvalpp->symbol_name);
alokp@chromium.org88609092010-10-27 19:42:44 +0000248 if (isinff(yylvalpp->sc_fval)) {
249 CPPErrorToInfoLog("FLOAT CONSTANT OVERFLOW");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251 return CPP_FLOATCONSTANT;
252} // lFloatConst
253
254///////////////////////////////////////////////////////////////////////////////////////////////
255///////////////////////////////////////// Normal Scanner //////////////////////////////////////
256///////////////////////////////////////////////////////////////////////////////////////////////
257
258static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
259{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260 char string_val[MAX_STRING_LEN + 1];
alokp@chromium.org88609092010-10-27 19:42:44 +0000261 int alreadyComplained = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262 int len, ch, ii, ival = 0;
263
264 for (;;) {
265 yylvalpp->sc_int = 0;
266 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
alokp@chromium.org88609092010-10-27 19:42:44 +0000267
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000268 while (ch == ' ' || ch == '\t' || ch == '\r') {
269 yylvalpp->sc_int = 1;
270 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
271 }
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000272
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000273 cpp->ltokenLoc.file = cpp->currentInput->name;
274 cpp->ltokenLoc.line = cpp->currentInput->line;
alokp@chromium.org88609092010-10-27 19:42:44 +0000275 alreadyComplained = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000276 len = 0;
277 switch (ch) {
278 default:
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000279 return ch; // Single character token
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000280 case EOF:
281 return -1;
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000282 case 'A': case 'B': case 'C': case 'D': case 'E':
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000283 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':
287 case 'Z': case '_':
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':
293 case 'z':
294 do {
alokp@chromium.org88609092010-10-27 19:42:44 +0000295 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000296 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000297 } while ((ch >= 'a' && ch <= 'z') ||
298 (ch >= 'A' && ch <= 'Z') ||
299 (ch >= '0' && ch <= '9') ||
300 ch == '_');
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000301 assert(len <= MAX_SYMBOL_NAME_LEN);
alokp@chromium.org88609092010-10-27 19:42:44 +0000302 yylvalpp->symbol_name[len] = '\0';
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
alokp@chromium.org88609092010-10-27 19:42:44 +0000304 yylvalpp->sc_ident = LookUpAddString(atable, yylvalpp->symbol_name);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000305 return CPP_IDENTIFIER;
306 break;
307 case '0':
alokp@chromium.org88609092010-10-27 19:42:44 +0000308 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000309 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
alokp@chromium.org88609092010-10-27 19:42:44 +0000310 if (ch == 'x' || ch == 'X') { // hexadecimal integer constants
311 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000312 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
313 if ((ch >= '0' && ch <= '9') ||
314 (ch >= 'A' && ch <= 'F') ||
315 (ch >= 'a' && ch <= 'f'))
316 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317 ival = 0;
318 do {
alokp@chromium.org88609092010-10-27 19:42:44 +0000319 if ((ival <= 0x0fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
320 yylvalpp->symbol_name[len++] = ch;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000321 if (ch >= '0' && ch <= '9') {
322 ii = ch - '0';
323 } else if (ch >= 'A' && ch <= 'F') {
324 ii = ch - 'A' + 10;
325 } else {
326 ii = ch - 'a' + 10;
327 }
328 ival = (ival << 4) | ii;
alokp@chromium.org88609092010-10-27 19:42:44 +0000329 } else if (!alreadyComplained) {
330 CPPErrorToInfoLog("HEX CONSTANT OVERFLOW");
331 alreadyComplained = 1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000332 }
333 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
334 } while ((ch >= '0' && ch <= '9') ||
335 (ch >= 'A' && ch <= 'F') ||
336 (ch >= 'a' && ch <= 'f'));
337 } else {
alokp@chromium.org88609092010-10-27 19:42:44 +0000338 CPPErrorToInfoLog("HEX CONSTANT INVALID");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339 }
alokp@chromium.org88609092010-10-27 19:42:44 +0000340 assert(len <= MAX_SYMBOL_NAME_LEN);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341 yylvalpp->symbol_name[len] = '\0';
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000342 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
343 yylvalpp->sc_int = ival;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000344 return CPP_INTCONSTANT;
345 } else if (ch >= '0' && ch <= '7') { // octal integer constants
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000346 ival = 0;
347 do {
alokp@chromium.org88609092010-10-27 19:42:44 +0000348 if ((ival <= 0x1fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
349 yylvalpp->symbol_name[len++] = ch;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000350 ii = ch - '0';
351 ival = (ival << 3) | ii;
alokp@chromium.org88609092010-10-27 19:42:44 +0000352 } else if (!alreadyComplained) {
353 CPPErrorToInfoLog("OCT CONSTANT OVERFLOW");
354 alreadyComplained = 1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000355 }
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')
alokp@chromium.org88609092010-10-27 19:42:44 +0000359 return lFloatConst(ch, len, yylvalpp);
360 assert(len <= MAX_SYMBOL_NAME_LEN);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000361 yylvalpp->symbol_name[len] = '\0';
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000362 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
363 yylvalpp->sc_int = ival;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000364 return CPP_INTCONSTANT;
365 } else {
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000366 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
367 ch = '0';
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000368 }
369 // Fall through...
370 case '1': case '2': case '3': case '4':
371 case '5': case '6': case '7': case '8': case '9':
372 do {
alokp@chromium.org88609092010-10-27 19:42:44 +0000373 APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
374 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000375 } while (ch >= '0' && ch <= '9');
376 if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') {
alokp@chromium.org88609092010-10-27 19:42:44 +0000377 return lFloatConst(ch, len, yylvalpp);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000378 } else {
alokp@chromium.org88609092010-10-27 19:42:44 +0000379 assert(len <= MAX_SYMBOL_NAME_LEN);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000380 yylvalpp->symbol_name[len] = '\0';
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000381 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000382 ival = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000383 for (ii = 0; ii < len; ii++) {
384 ch = yylvalpp->symbol_name[ii] - '0';
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000385 ival = ival*10 + ch;
alokp@chromium.org88609092010-10-27 19:42:44 +0000386 if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) {
387 CPPErrorToInfoLog("INTEGER CONSTANT OVERFLOW");
388 break;
389 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000390 }
391 yylvalpp->sc_int = ival;
392 if(ival==0)
393 strcpy(yylvalpp->symbol_name,"0");
394 return CPP_INTCONSTANT;
395 }
396 break;
397 case '-':
398 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
399 if (ch == '-') {
400 return CPP_DEC_OP;
401 } else if (ch == '=') {
402 return CPP_SUB_ASSIGN;
403 } else {
404 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
405 return '-';
406 }
407 case '+':
408 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
409 if (ch == '+') {
410 return CPP_INC_OP;
411 } else if (ch == '=') {
412 return CPP_ADD_ASSIGN;
413 } else {
414 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
415 return '+';
416 }
417 case '*':
418 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
419 if (ch == '=') {
420 return CPP_MUL_ASSIGN;
421 } else {
422 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
423 return '*';
424 }
425 case '%':
426 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
427 if (ch == '=') {
428 return CPP_MOD_ASSIGN;
429 } else if (ch == '>'){
430 return CPP_RIGHT_BRACE;
431 } else {
432 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
433 return '%';
434 }
435 case ':':
436 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
437 if (ch == '>') {
438 return CPP_RIGHT_BRACKET;
439 } else {
440 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
441 return ':';
442 }
443 case '^':
444 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
445 if (ch == '^') {
446 return CPP_XOR_OP;
447 } else {
448 if (ch == '=')
449 return CPP_XOR_ASSIGN;
450 else{
451 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
452 return '^';
453 }
454 }
455
456 case '=':
457 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
458 if (ch == '=') {
459 return CPP_EQ_OP;
460 } else {
461 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
462 return '=';
463 }
464 case '!':
465 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
466 if (ch == '=') {
467 return CPP_NE_OP;
468 } else {
469 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
470 return '!';
471 }
472 case '|':
473 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
474 if (ch == '|') {
475 return CPP_OR_OP;
476 } else {
477 if (ch == '=')
478 return CPP_OR_ASSIGN;
479 else{
480 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
481 return '|';
482 }
483 }
484 case '&':
485 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
486 if (ch == '&') {
487 return CPP_AND_OP;
488 } else {
489 if (ch == '=')
490 return CPP_AND_ASSIGN;
491 else{
492 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
493 return '&';
494 }
495 }
496 case '<':
497 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
498 if (ch == '<') {
499 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
500 if(ch == '=')
501 return CPP_LEFT_ASSIGN;
502 else{
503 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
504 return CPP_LEFT_OP;
505 }
506 } else {
507 if (ch == '=') {
508 return CPP_LE_OP;
509 } else {
510 if (ch == '%')
511 return CPP_LEFT_BRACE;
512 else if (ch == ':')
513 return CPP_LEFT_BRACKET;
514 else{
515 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
516 return '<';
517 }
518 }
519 }
520 case '>':
521 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
522 if (ch == '>') {
523 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
524 if(ch == '=')
525 return CPP_RIGHT_ASSIGN;
526 else{
527 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
528 return CPP_RIGHT_OP;
529 }
530 } else {
531 if (ch == '=') {
532 return CPP_GE_OP;
533 } else {
534 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
535 return '>';
536 }
537 }
538 case '.':
539 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
540 if (ch >= '0' && ch <= '9') {
541 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
alokp@chromium.org88609092010-10-27 19:42:44 +0000542 return lFloatConst('.', 0, yylvalpp);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000543 } else {
544 if (ch == '.') {
545 return -1; // Special EOF hack
546 } else {
547 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
548 return '.';
549 }
550 }
551 case '/':
552 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
553 if (ch == '/') {
554 do {
555 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
556 } while (ch != '\n' && ch != EOF);
557 if (ch == EOF)
558 return -1;
559 return '\n';
560 } else if (ch == '*') {
561 int nlcount = 0;
562 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
563 do {
564 while (ch != '*') {
565 if (ch == '\n') nlcount++;
566 if (ch == EOF) {
alokp@chromium.org88609092010-10-27 19:42:44 +0000567 CPPErrorToInfoLog("EOF IN COMMENT");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000568 return -1;
569 }
570 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
571 }
572 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
573 if (ch == EOF) {
alokp@chromium.org88609092010-10-27 19:42:44 +0000574 CPPErrorToInfoLog("EOF IN COMMENT");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000575 return -1;
576 }
577 } while (ch != '/');
578 if (nlcount) {
579 return '\n';
580 }
581 // Go try it again...
582 } else if (ch == '=') {
583 return CPP_DIV_ASSIGN;
584 } else {
585 cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
586 return '/';
587 }
588 break;
589 case '"':
590 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
591 while (ch != '"' && ch != '\n' && ch != EOF) {
592 if (ch == '\\') {
daniel@transgaming.comedff8dc2010-05-14 17:30:27 +0000593 CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
594 return -1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000595 }
alokp@chromium.org88609092010-10-27 19:42:44 +0000596 APPEND_CHAR_S(ch, string_val, len, MAX_STRING_LEN);
597 ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000598 };
alokp@chromium.org88609092010-10-27 19:42:44 +0000599 assert(len <= MAX_STRING_LEN);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000600 string_val[len] = '\0';
601 if (ch == '"') {
602 yylvalpp->sc_ident = LookUpAddString(atable, string_val);
603 return CPP_STRCONSTANT;
604 } else {
alokp@chromium.org88609092010-10-27 19:42:44 +0000605 CPPErrorToInfoLog("EOL IN STRING");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000606 return ERROR_SY;
607 }
alokp@chromium.org88609092010-10-27 19:42:44 +0000608 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000609 }
610 }
611} // byte_scan
612
613int yylex_CPP(char* buf, int maxSize)
614{
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000615 yystypepp yylvalpp;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000616 int token = '\n';
617
618 for(;;) {
619
620 char* tokenString = 0;
621 token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp);
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000622 if(check_EOF(token))
623 return 0;
kbr@chromium.org55d0be02011-01-28 22:05:31 +0000624 if (token < 0) {
625 // This check may need to be improved to support UTF-8
626 // characters in comments.
627 CPPErrorToInfoLog("preprocessor encountered non-ASCII character in shader source");
628 return 0;
629 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000630 if (token == '#') {
631 if (cpp->previous_token == '\n'|| cpp->previous_token == 0) {
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000632 token = readCPPline(&yylvalpp);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000633 if(check_EOF(token))
634 return 0;
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000635 continue;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000636 } else {
637 CPPErrorToInfoLog("preprocessor command must not be preceded by any other statement in that line");
638 return 0;
639 }
640 }
641 cpp->previous_token = token;
642 // expand macros
643 if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp.sc_ident, &yylvalpp)) {
daniel@transgaming.comdec19e22010-04-29 03:35:42 +0000644 cpp->pastFirstStatement = 1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000645 continue;
646 }
alokp@chromium.org88609092010-10-27 19:42:44 +0000647
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000648 if (token == '\n')
649 continue;
alokp@chromium.org88609092010-10-27 19:42:44 +0000650 cpp->pastFirstStatement = 1;
651
652 if (token == CPP_IDENTIFIER) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000653 tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident);
alokp@chromium.org88609092010-10-27 19:42:44 +0000654 } else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000655 tokenString = yylvalpp.symbol_name;
alokp@chromium.org88609092010-10-27 19:42:44 +0000656 } else {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000657 tokenString = GetStringOfAtom(atable,token);
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000658 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000659
660 if (tokenString) {
alokp@chromium.org88609092010-10-27 19:42:44 +0000661 int len = strlen(tokenString);
662 cpp->tokensBeforeEOF = 1;
663 if (len >= maxSize) {
664 return maxSize;
665 } else if (len > 0) {
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000666 strcpy(buf, tokenString);
alokp@chromium.org88609092010-10-27 19:42:44 +0000667 return len;
668 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000669
670 return 0;
671 }
672 }
673
674 return 0;
675} // yylex
676
677//Checks if the token just read is EOF or not.
678int check_EOF(int token)
679{
680 if(token==-1){
681 if(cpp->ifdepth >0){
alokp@chromium.org43668cd2010-10-20 20:55:53 +0000682 CPPErrorToInfoLog("#endif missing!! Compilation stopped");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000683 cpp->CompileError=1;
684 }
685 return 1;
686 }
687 return 0;
688}
689
690///////////////////////////////////////////////////////////////////////////////////////////////
691/////////////////////////////////////// End of scanner.c //////////////////////////////////////
692///////////////////////////////////////////////////////////////////////////////////////////////
693