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// tokens.c
46//
47
48#include <stdlib.h>
49#include <stdio.h>
50#include <string.h>
51#include <ctype.h>
52
53#include "compiler/debug.h"
54#include "compiler/preprocessor/slglobals.h"
55#include "compiler/util.h"
56
57///////////////////////////////////////////////////////////////////////////////////////////////
58//////////////////////// Preprocessor and Token Recorder and Playback: ////////////////////////
59///////////////////////////////////////////////////////////////////////////////////////////////
60
61/*
62 * idstr()
63 * Copy a string to a malloc'ed block and convert it into something suitable
64 * for an ID
65 *
66 */
67
68static char *idstr(const char *fstr, MemoryPool *pool)
69{
70    size_t len;
71    char *str, *t;
72    const char *f;
73
74    len = strlen(fstr);
75    if (!pool)
76        str = (char *) malloc(len + 1);
77    else
78        str = (char *) mem_Alloc(pool, len + 1);
79
80    for (f=fstr, t=str; *f; f++) {
81        if (isalnum(*f)) *t++ = *f;
82        else if (*f == '.' || *f == '/') *t++ = '_';
83    }
84    *t = 0;
85    return str;
86} // idstr
87
88
89/*
90 * lNewBlock()
91 *
92 */
93
94static TokenBlock *lNewBlock(TokenStream *fTok, MemoryPool *pool)
95{
96    TokenBlock *lBlock;
97
98    if (!pool)
99        lBlock = (TokenBlock *) malloc(sizeof(TokenBlock) + 256);
100    else
101        lBlock = (TokenBlock *) mem_Alloc(pool, sizeof(TokenBlock) + 256);
102    lBlock->count = 0;
103    lBlock->current = 0;
104    lBlock->data = (unsigned char *) lBlock + sizeof(TokenBlock);
105    lBlock->max = 256;
106    lBlock->next = NULL;
107    if (fTok->head) {
108        fTok->current->next = lBlock;
109    } else {
110        fTok->head = lBlock;
111    }
112    fTok->current = lBlock;
113    return lBlock;
114} // lNewBlock
115
116/*
117 * lAddByte()
118 *
119 */
120
121static void lAddByte(TokenStream *fTok, unsigned char fVal)
122{
123    TokenBlock *lBlock;
124    lBlock = fTok->current;
125    if (lBlock->count >= lBlock->max)
126        lBlock = lNewBlock(fTok, 0);
127    lBlock->data[lBlock->count++] = fVal;
128} // lAddByte
129
130
131
132/*
133 * lReadByte() - Get the next byte from a stream.
134 *
135 */
136
137static int lReadByte(TokenStream *pTok)
138{
139    TokenBlock *lBlock;
140    int lval = -1;
141
142    lBlock = pTok->current;
143    if (lBlock) {
144        if (lBlock->current >= lBlock->count) {
145            lBlock = lBlock->next;
146            if (lBlock)
147                lBlock->current = 0;
148            pTok->current = lBlock;
149        }
150        if (lBlock)
151            lval = lBlock->data[lBlock->current++];
152    }
153    return lval;
154} // lReadByte
155
156/////////////////////////////////////// Global Functions://////////////////////////////////////
157
158/*
159 * NewTokenStream()
160 *
161 */
162
163TokenStream *NewTokenStream(const char *name, MemoryPool *pool)
164{
165    TokenStream *pTok;
166
167    if (!pool)
168        pTok = (TokenStream *) malloc(sizeof(TokenStream));
169    else
170        pTok = (TokenStream*)mem_Alloc(pool, sizeof(TokenStream));
171    pTok->next = NULL;
172    pTok->name = idstr(name, pool);
173    pTok->head = NULL;
174    pTok->current = NULL;
175    lNewBlock(pTok, pool);
176    return pTok;
177} // NewTokenStream
178
179/*
180 * DeleteTokenStream()
181 *
182 */
183
184void DeleteTokenStream(TokenStream *pTok)
185{
186    TokenBlock *pBlock, *nBlock;
187
188    if (pTok) {
189        pBlock = pTok->head;
190        while (pBlock) {
191            nBlock = pBlock->next;
192            free(pBlock);
193            pBlock = nBlock;
194        }
195        if (pTok->name)
196            free(pTok->name);
197        free(pTok);
198    }
199} // DeleteTokenStream
200
201/*
202 * RecordToken() - Add a token to the end of a list for later playback or printout.
203 *
204 */
205
206void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp)
207{
208    const char *s;
209    char *str=NULL;
210
211    if (token > 256)
212        lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80));
213    else
214        lAddByte(pTok, (unsigned char)(token & 0x7f));
215    switch (token) {
216    case CPP_IDENTIFIER:
217    case CPP_TYPEIDENTIFIER:
218    case CPP_STRCONSTANT:
219        s = GetAtomString(atable, yylvalpp->sc_ident);
220        while (*s)
221            lAddByte(pTok, (unsigned char) *s++);
222        lAddByte(pTok, 0);
223        break;
224    case CPP_FLOATCONSTANT:
225    case CPP_INTCONSTANT:
226         str=yylvalpp->symbol_name;
227         while (*str){
228            lAddByte(pTok, (unsigned char) *str++);
229         }
230         lAddByte(pTok, 0);
231         break;
232    case '(':
233        lAddByte(pTok, (unsigned char)(yylvalpp->sc_int ? 1 : 0));
234    default:
235        break;
236    }
237} // RecordToken
238
239/*
240 * RewindTokenStream() - Reset a token stream in preperation for reading.
241 *
242 */
243
244void RewindTokenStream(TokenStream *pTok)
245{
246    if (pTok->head) {
247        pTok->current = pTok->head;
248        pTok->current->current = 0;
249    }
250} // RewindTokenStream
251
252/*
253 * ReadToken() - Read the next token from a stream.
254 *
255 */
256
257int ReadToken(TokenStream *pTok, yystypepp * yylvalpp)
258{
259    char symbol_name[MAX_SYMBOL_NAME_LEN + 1];
260    char string_val[MAX_STRING_LEN + 1];
261    int ltoken, len;
262    char ch;
263
264    ltoken = lReadByte(pTok);
265    if (ltoken >= 0) {
266        if (ltoken > 127)
267            ltoken += 128;
268        switch (ltoken) {
269        case CPP_IDENTIFIER:
270        case CPP_TYPEIDENTIFIER:
271            len = 0;
272            ch = lReadByte(pTok);
273            while ((ch >= 'a' && ch <= 'z') ||
274                     (ch >= 'A' && ch <= 'Z') ||
275                     (ch >= '0' && ch <= '9') ||
276                     ch == '_')
277            {
278                if (len < MAX_SYMBOL_NAME_LEN) {
279                    symbol_name[len++] = ch;
280                    ch = lReadByte(pTok);
281                }
282            }
283            symbol_name[len] = '\0';
284            assert(ch == '\0');
285            yylvalpp->sc_ident = LookUpAddString(atable, symbol_name);
286            return CPP_IDENTIFIER;
287            break;
288        case CPP_STRCONSTANT:
289            len = 0;
290            while ((ch = lReadByte(pTok)) != 0)
291                if (len < MAX_STRING_LEN)
292                    string_val[len++] = ch;
293            string_val[len] = '\0';
294            yylvalpp->sc_ident = LookUpAddString(atable, string_val);
295            break;
296        case CPP_FLOATCONSTANT:
297            len = 0;
298            ch = lReadByte(pTok);
299            while ((ch >= '0' && ch <= '9')||(ch=='e'||ch=='E'||ch=='.')||(ch=='+'||ch=='-'))
300            {
301                if (len < MAX_SYMBOL_NAME_LEN) {
302                    symbol_name[len++] = ch;
303                    ch = lReadByte(pTok);
304                }
305            }
306            symbol_name[len] = '\0';
307            assert(ch == '\0');
308            strcpy(yylvalpp->symbol_name,symbol_name);
309            yylvalpp->sc_fval=(float)atof_dot(yylvalpp->symbol_name);
310            break;
311        case CPP_INTCONSTANT:
312            len = 0;
313            ch = lReadByte(pTok);
314            while ((ch >= '0' && ch <= '9'))
315            {
316                if (len < MAX_SYMBOL_NAME_LEN) {
317                    symbol_name[len++] = ch;
318                    ch = lReadByte(pTok);
319                }
320            }
321            symbol_name[len] = '\0';
322            assert(ch == '\0');
323            strcpy(yylvalpp->symbol_name,symbol_name);
324            yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
325            break;
326        case '(':
327            yylvalpp->sc_int = lReadByte(pTok);
328            break;
329        }
330        return ltoken;
331    }
332    return EOF_SY;
333} // ReadToken
334
335typedef struct TokenInputSrc {
336    InputSrc            base;
337    TokenStream         *tokens;
338    int                 (*final)(CPPStruct *);
339} TokenInputSrc;
340
341static int scan_token(TokenInputSrc *in, yystypepp * yylvalpp)
342{
343    int token = ReadToken(in->tokens, yylvalpp);
344    int (*final)(CPPStruct *);
345    cpp->tokenLoc->file = cpp->currentInput->name;
346    cpp->tokenLoc->line = cpp->currentInput->line;
347    if (token == '\n') {
348        in->base.line++;
349        return token;
350    }
351    if (token > 0) return token;
352    cpp->currentInput = in->base.prev;
353    final = in->final;
354    free(in);
355    if (final && !final(cpp)) return -1;
356    return cpp->currentInput->scan(cpp->currentInput, yylvalpp);
357}
358
359int ReadFromTokenStream(TokenStream *ts, int name, int (*final)(CPPStruct *))
360{
361    TokenInputSrc *in = malloc(sizeof(TokenInputSrc));
362    memset(in, 0, sizeof(TokenInputSrc));
363    in->base.name = name;
364    in->base.prev = cpp->currentInput;
365    in->base.scan = (int (*)(InputSrc *, yystypepp *))scan_token;
366    in->base.line = 1;
367    in->tokens = ts;
368    in->final = final;
369    RewindTokenStream(ts);
370    cpp->currentInput = &in->base;
371    return 1;
372}
373
374typedef struct UngotToken {
375    InputSrc    base;
376    int         token;
377    yystypepp     lval;
378} UngotToken;
379
380static int reget_token(UngotToken *t, yystypepp * yylvalpp)
381{
382    int token = t->token;
383    *yylvalpp = t->lval;
384    cpp->currentInput = t->base.prev;
385    free(t);
386    return token;
387}
388
389void UngetToken(int token, yystypepp * yylvalpp) {
390    UngotToken *t = malloc(sizeof(UngotToken));
391    memset(t, 0, sizeof(UngotToken));
392    t->token = token;
393    t->lval = *yylvalpp;
394    t->base.scan = (void *)reget_token;
395    t->base.prev = cpp->currentInput;
396    t->base.name = cpp->currentInput->name;
397    t->base.line = cpp->currentInput->line;
398    cpp->currentInput = &t->base;
399}
400
401
402void DumpTokenStream(FILE *fp, TokenStream *s, yystypepp * yylvalpp) {
403    int token;
404    char str[100];
405
406    if (fp == 0) fp = stdout;
407    RewindTokenStream(s);
408    while ((token = ReadToken(s, yylvalpp)) > 0) {
409        switch (token) {
410        case CPP_IDENTIFIER:
411        case CPP_TYPEIDENTIFIER:
412            sprintf(str, "%s ", GetAtomString(atable, yylvalpp->sc_ident));
413            break;
414        case CPP_STRCONSTANT:
415            sprintf(str, "\"%s\"", GetAtomString(atable, yylvalpp->sc_ident));
416            break;
417        case CPP_FLOATCONSTANT:
418            //printf("%g9.6 ", yylvalpp->sc_fval);
419            break;
420        case CPP_INTCONSTANT:
421            //printf("%d ", yylvalpp->sc_int);
422            break;
423        default:
424            if (token >= 127)
425                sprintf(str, "%s ", GetAtomString(atable, token));
426            else
427                sprintf(str, "%c", token);
428            break;
429        }
430        CPPDebugLogMsg(str);
431    }
432}
433
434///////////////////////////////////////////////////////////////////////////////////////////////
435/////////////////////////////////////// End of tokens.c ///////////////////////////////////////
436///////////////////////////////////////////////////////////////////////////////////////////////
437