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