1/****************************************************************************\
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
48#include <assert.h>
49#include <stdarg.h>
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53
54#if 0
55    #include <ieeefp.h>
56#else
57    #define isinff(x) (((*(int *)&(x) & 0x7f800000L)==0x7f800000L) && \
58                       ((*(int *)&(x) & 0x007fffffL)==0000000000L))
59#endif
60
61#include "compiler/preprocessor/slglobals.h"
62#include "compiler/util.h"
63
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
82#if defined(_MSC_VER)
83    #define DBG_BREAKPOINT() __asm int 3
84#elif defined(_M_AMD64)
85    #define DBG_BREAKPOINT() assert(!"Dbg_Breakpoint");
86#else
87    #define DBG_BREAKPOINT()
88#endif
89
90#if defined(_MSC_VER) && !defined(_M_AMD64)
91    __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';
119    cpp->pastFirstStatement = 0;
120
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{
137    for(;;){
138       if (*in->p){
139          if (*in->p == '\n') {
140             in->base.line++;
141             IncLineNumber();
142          }
143          return *in->p++;
144       }
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;
156          free(in);
157          return EOF;
158       }
159    }
160} // str_getch
161
162static void str_ungetch(StringInputSrc *in, int ch, yystypepp *type) {
163    if (in->p[-1] == ch)in->p--;
164    else {
165        *(in->p)='\0'; //this would take care of shifting to the previous string.
166        cpp->PaWhichStr--;
167    }
168    if (ch == '\n') {
169        in->base.line--;
170        DecLineNumber();
171    }
172} // str_ungetch
173
174int ScanFromString(const char *s)
175{
176
177    StringInputSrc *in = malloc(sizeof(StringInputSrc));
178    memset(in, 0, sizeof(StringInputSrc));
179    in->p = (char*) s;
180    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///////////////////////////////////////////////////////////////////////////////////////////////
194
195#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      }
202
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'.
207 * ch - '.' or 'e'
208 * len - length of string already copied into yylvalpp->symbol_name.
209 */
210
211static int lFloatConst(int ch, int len, yystypepp * yylvalpp)
212{
213    int alreadyComplained = 0;
214    assert((ch == '.') || (ch == 'e') || (ch == 'E'));
215
216    if (ch == '.') {
217        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');
221    }
222
223    // Exponent:
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);
227        if (ch == '+') {
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);
233        }
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);
238            }
239        } else {
240            CPPErrorToInfoLog("EXPONENT INVALID");
241        }
242    }
243    cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
244
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");
250    }
251    return CPP_FLOATCONSTANT;
252} // lFloatConst
253
254///////////////////////////////////////////////////////////////////////////////////////////////
255///////////////////////////////////////// Normal Scanner //////////////////////////////////////
256///////////////////////////////////////////////////////////////////////////////////////////////
257
258static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
259{
260    char string_val[MAX_STRING_LEN + 1];
261    int alreadyComplained = 0;
262    int len, ch, ii, ival = 0;
263
264    for (;;) {
265        yylvalpp->sc_int = 0;
266        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
267
268        while (ch == ' ' || ch == '\t' || ch == '\r') {
269            yylvalpp->sc_int = 1;
270            ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
271        }
272
273        cpp->ltokenLoc.file = cpp->currentInput->name;
274        cpp->ltokenLoc.line = cpp->currentInput->line;
275        alreadyComplained = 0;
276        len = 0;
277        switch (ch) {
278        default:
279            return ch; // Single character token
280        case EOF:
281            return -1;
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':
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 {
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') ||
300                     ch == '_');
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;
306            break;
307        case '0':
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'))
316                {
317                    ival = 0;
318                    do {
319                        if ((ival <= 0x0fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
320                            yylvalpp->symbol_name[len++] = ch;
321                            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;
329                        } else if (!alreadyComplained) {
330                            CPPErrorToInfoLog("HEX CONSTANT OVERFLOW");
331                            alreadyComplained = 1;
332                        }
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 {
338                    CPPErrorToInfoLog("HEX CONSTANT INVALID");
339                }
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
346                ival = 0;
347                do {
348                    if ((ival <= 0x1fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
349                        yylvalpp->symbol_name[len++] = ch;
350                        ii = ch - '0';
351                        ival = (ival << 3) | ii;
352                    } else if (!alreadyComplained) {
353                        CPPErrorToInfoLog("OCT CONSTANT OVERFLOW");
354                        alreadyComplained = 1;
355                    }
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;
365            } else {
366                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
367                ch = '0';
368            }
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 {
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);
378            } else {
379                assert(len <= MAX_SYMBOL_NAME_LEN);
380                yylvalpp->symbol_name[len] = '\0';
381                cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
382                ival = 0;
383                for (ii = 0; ii < len; ii++) {
384                    ch = yylvalpp->symbol_name[ii] - '0';
385                    ival = ival*10 + ch;
386                    if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) {
387                        CPPErrorToInfoLog("INTEGER CONSTANT OVERFLOW");
388                        break;
389                    }
390                }
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);
542                return lFloatConst('.', 0, yylvalpp);
543            } 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) {
567                            CPPErrorToInfoLog("EOF IN COMMENT");
568                            return -1;
569                        }
570                        ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
571                    }
572                    ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
573                    if (ch == EOF) {
574                        CPPErrorToInfoLog("EOF IN COMMENT");
575                        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 == '\\') {
593                    CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
594                    return -1;
595                }
596                APPEND_CHAR_S(ch, string_val, len, MAX_STRING_LEN);
597                ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
598            };
599            assert(len <= MAX_STRING_LEN);
600            string_val[len] = '\0';
601            if (ch == '"') {
602                yylvalpp->sc_ident = LookUpAddString(atable, string_val);
603                return CPP_STRCONSTANT;
604            } else {
605                CPPErrorToInfoLog("EOL IN STRING");
606                return ERROR_SY;
607            }
608            break;
609        }
610    }
611} // byte_scan
612
613int yylex_CPP(char* buf, int maxSize)
614{
615    yystypepp yylvalpp;
616    int token = '\n';
617
618    for(;;) {
619
620        char* tokenString = 0;
621        token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp);
622        if(check_EOF(token))
623            return 0;
624        if (token == '#') {
625            if (cpp->previous_token == '\n'|| cpp->previous_token == 0) {
626                token = readCPPline(&yylvalpp);
627                if(check_EOF(token))
628                    return 0;
629                continue;
630            } else {
631                CPPErrorToInfoLog("preprocessor command must not be preceded by any other statement in that line");
632                return 0;
633            }
634        }
635        cpp->previous_token = token;
636        // expand macros
637        if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp.sc_ident, &yylvalpp)) {
638            cpp->pastFirstStatement = 1;
639            continue;
640        }
641
642        if (token == '\n')
643            continue;
644        cpp->pastFirstStatement = 1;
645
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;
650        } else {
651            tokenString = GetStringOfAtom(atable,token);
652        }
653
654        if (tokenString) {
655            int len = strlen(tokenString);
656            cpp->tokensBeforeEOF = 1;
657            if (len >= maxSize) {
658                return maxSize;
659            } else  if (len > 0) {
660                strcpy(buf, tokenString);
661                return len;
662            }
663
664            return 0;
665        }
666    }
667
668    return 0;
669} // yylex
670
671//Checks if the token just read is EOF or not.
672int check_EOF(int token)
673{
674   if(token==-1){
675       if(cpp->ifdepth >0){
676        CPPErrorToInfoLog("#endif missing!! Compilation stopped");
677        cpp->CompileError=1;
678       }
679      return 1;
680   }
681   return 0;
682}
683
684///////////////////////////////////////////////////////////////////////////////////////////////
685/////////////////////////////////////// End of scanner.c //////////////////////////////////////
686///////////////////////////////////////////////////////////////////////////////////////////////
687
688