OSDN Git Service

2004-06-28 Paolo Bonzini <bonzini@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / gengtype-lex.l
1 /* -*- indented-text -*- */
2 /* Process source files and output type information.
3    Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING.  If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.  */
21
22 %{
23 #include "bconfig.h"
24 #include "coretypes.h"
25 #include "system.h"
26
27 #define malloc xmalloc
28 #define realloc xrealloc
29
30 #include "gengtype.h"
31 #include "gengtype-yacc.h"
32
33 #define YY_INPUT(BUF,RESULT,SIZE) ((RESULT) = macro_input (BUF,SIZE))
34
35 static unsigned macro_input (char *buffer, unsigned);
36 static void push_macro_expansion (const char *, unsigned,
37                                   const char *, unsigned);
38 static void update_lineno (const char *l, size_t len);
39
40 struct fileloc lexer_line;
41 int lexer_toplevel_done;
42
43 static void 
44 update_lineno (const char *l, size_t len)
45 {
46   while (len-- > 0)
47     if (*l++ == '\n')
48       lexer_line.line++;
49 }
50
51 %}
52
53 ID      [[:alpha:]_][[:alnum:]_]*
54 WS      [[:space:]]+
55 IWORD   short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD
56 ITYPE   {IWORD}({WS}{IWORD})*
57
58 %x in_struct in_struct_comment in_comment in_yacc_escape
59 %option warn noyywrap nounput nodefault perf-report
60 %option 8bit never-interactive
61 %%
62
63 [^[:alnum:]_]typedef{WS}(struct|union){WS}{ID}{WS}?[*[:space:]]{WS}?{ID}{WS}?";" {
64   char *tagstart;
65   size_t taglen;
66   char *namestart;
67   size_t namelen;
68   int is_pointer = 0;
69   struct type *t;
70   int union_p;
71
72   tagstart = yytext + strlen (" typedef ");
73   while (ISSPACE (*tagstart))
74     tagstart++;
75   union_p = tagstart[0] == 'u';
76   tagstart += strlen ("union ");
77   while (ISSPACE (*tagstart))
78     tagstart++;
79   for (taglen = 1; ISIDNUM (tagstart[taglen]); taglen++)
80     ;
81   for (namestart = tagstart + taglen; 
82        ! ISIDNUM (*namestart);
83        namestart++)
84     if (*namestart == '*')
85       is_pointer = 1;
86   for (namelen = 1; ISIDNUM (namestart[namelen]); namelen++)
87     ;
88   t = find_structure (xmemdup (tagstart, taglen, taglen+1), union_p);
89   if (is_pointer)
90     t = create_pointer (t);
91   do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
92   update_lineno (yytext, yyleng);
93 }
94
95 [^[:alnum:]_]typedef{WS}{ITYPE}{WS}{ID}{WS}?";" {
96
97   char *namestart;
98   size_t namelen;
99   struct type *t;
100   char *typestart;
101   size_t typelen;
102
103   for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--)
104     ;
105   for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
106     ;
107   namestart -= namelen - 1;
108   for (typestart = yytext + strlen (" typedef "); 
109        ISSPACE(*typestart);
110        typestart++)
111     ;
112   for (typelen = namestart - typestart; 
113        ISSPACE(typestart[typelen-1]); 
114        typelen--)
115     ;
116
117   t = create_scalar_type (typestart, typelen);
118   do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
119   update_lineno (yytext, yyleng);
120 }
121
122 [^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}PARAMS {
123   char *namestart;
124   size_t namelen;
125   struct type *t;
126
127   for (namestart = yytext + yyleng - 7; ISSPACE (*namestart); namestart--)
128     ;
129   for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
130     ;
131   namestart -= namelen - 1;
132
133   t = create_scalar_type ("function type", sizeof ("function type")-1);
134   do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
135   update_lineno (yytext, yyleng);
136 }
137
138 [^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}"(" {
139   char *namestart;
140   size_t namelen;
141   struct type *t;
142
143   for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--)
144     ;
145   for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
146     ;
147   namestart -= namelen - 1;
148
149   t = create_scalar_type ("function type", sizeof ("function type")-1);
150   do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
151   update_lineno (yytext, yyleng);
152 }
153
154 [^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?PARAMS {
155   char *namestart;
156   size_t namelen;
157   struct type *t;
158
159   for (namestart = yytext + yyleng - 7; !ISIDNUM (*namestart); namestart--)
160     ;
161   for (namelen = 1; ISIDNUM (namestart[-namelen]); namelen++)
162     ;
163   namestart -= namelen - 1;
164
165   t = create_scalar_type ("function type", sizeof ("function type")-1);
166   do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
167   update_lineno (yytext, yyleng);
168 }
169
170 [^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?"(" {
171   char *namestart;
172   size_t namelen;
173   struct type *t;
174
175   for (namestart = yytext + yyleng - 2; !ISIDNUM (*namestart); namestart--)
176     ;
177   for (namelen = 1; ISIDNUM (namestart[-namelen]); namelen++)
178     ;
179   namestart -= namelen - 1;
180
181   t = create_scalar_type ("function type", sizeof ("function type")-1);
182   do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
183   update_lineno (yytext, yyleng);
184 }
185
186 [^[:alnum:]_](typedef{WS})?(struct|union){WS}{ID}{WS}/"GTY" {
187   char *tagstart;
188   size_t taglen;
189   int typedef_p;
190   int union_p;
191
192   typedef_p = yytext[1] == 't';
193   if (typedef_p)
194     for (tagstart = yytext + strlen (" typedef "); 
195          ISSPACE(*tagstart);
196          tagstart++)
197       ;
198   else
199     tagstart = yytext + 1;
200
201   union_p = tagstart[0] == 'u';
202   tagstart += strlen ("union ");
203   while (ISSPACE (*tagstart))
204     tagstart++;
205   for (taglen = 1; ISIDNUM (tagstart[taglen]); taglen++)
206     ;
207
208   yylval.t = find_structure (xmemdup (tagstart, taglen, taglen + 1), union_p);
209   BEGIN(in_struct);
210   update_lineno (yytext, yyleng);
211   return typedef_p ? ENT_TYPEDEF_STRUCT : ENT_STRUCT;
212 }
213
214 [^[:alnum:]_](extern|static){WS}/"GTY" {
215   BEGIN(in_struct);
216   update_lineno (yytext, yyleng);
217   return ENT_EXTERNSTATIC;
218 }
219
220 ^"%union"{WS}"{"{WS}/"GTY" {
221   BEGIN(in_struct);
222   update_lineno (yytext, yyleng);
223   return ENT_YACCUNION;
224 }
225
226 ^"DEF_VEC_"[[:alnum:]_]*{WS}?"("{WS}?{ID}{WS}?")" {
227   char *macro, *arg;
228   unsigned macro_len, arg_len;
229   char *ptr = yytext;
230   type_p t;
231
232   /* Locate the macro and argument strings.  */
233   macro = ptr;
234   while (*ptr != '(' && !ISSPACE (*ptr))
235     ptr++;
236   macro_len = ptr - macro;
237   while (*ptr == '(' || ISSPACE (*ptr))
238     ptr++;
239   arg = ptr;
240   while (*ptr != ')' && !ISSPACE (*ptr))
241     ptr++;
242   arg_len = ptr - arg;
243
244   /* Push the macro for later expansion.  */
245   push_macro_expansion (macro, macro_len, arg, arg_len);
246
247   /* Create the struct and typedef.  */
248   ptr = xmemdup ("VEC_", 4, 4 + arg_len + 1);
249   memcpy (&ptr[4], arg, arg_len);
250   ptr[4 + arg_len] = 0;
251   t = find_structure (ptr, 0);
252   do_typedef (ptr, t, &lexer_line);
253 }
254
255 <in_struct>{
256
257 "/*"                            { BEGIN(in_struct_comment); }
258
259 ^"%{"                           { BEGIN(in_yacc_escape); }
260
261 ^"@@".*                         /* Used for c-parse.in C/ObjC demarcation.  */
262
263 {WS}                            { update_lineno (yytext, yyleng); }
264
265 "const"/[^[:alnum:]_]           /* don't care */
266 "GTY"/[^[:alnum:]_]             { return GTY_TOKEN; }
267 "union"/[^[:alnum:]_]           { return UNION; }
268 "struct"/[^[:alnum:]_]          { return STRUCT; }
269 "enum"/[^[:alnum:]_]            { return ENUM; }
270 "ptr_alias"/[^[:alnum:]_]       { return ALIAS; }
271 "nested_ptr"/[^[:alnum:]_]      { return NESTED_PTR; }
272 [0-9]+                          { return NUM; }
273 "param"[0-9]*"_is"/[^[:alnum:]_]                { 
274   yylval.s = xmemdup (yytext, yyleng, yyleng+1);
275   return PARAM_IS;
276 }
277
278 {IWORD}({WS}{IWORD})*/[^[:alnum:]_]             |
279 "ENUM_BITFIELD"{WS}?"("{WS}?{ID}{WS}?")"        {
280   size_t len;
281
282   for (len = yyleng; ISSPACE (yytext[len-1]); len--)
283     ;
284
285   yylval.t = create_scalar_type (yytext, len);
286   update_lineno (yytext, yyleng);
287   return SCALAR;
288 }
289
290 "VEC"{WS}?"("{WS}?{ID}{WS}?")" {
291   char *macro, *arg;
292   unsigned macro_len, arg_len;
293   char *ptr = yytext;
294
295   macro = ptr;
296   while (*ptr != '(' && !ISSPACE (*ptr))
297     ptr++;
298   macro_len = ptr - macro;
299   while (*ptr == '(' || ISSPACE (*ptr))
300     ptr++;
301   arg = ptr;
302   while (*ptr != ')' && !ISSPACE (*ptr))
303     ptr++;
304   arg_len = ptr - arg;
305   ptr = xmemdup (macro, macro_len, macro_len + arg_len + 2);
306   ptr[macro_len] = '_';
307   memcpy (&ptr[macro_len+1], arg, arg_len);
308   yylval.s = ptr;
309   return ID;
310 }
311
312 {ID}/[^[:alnum:]_]              {
313   yylval.s = xmemdup (yytext, yyleng, yyleng+1);
314   return ID;
315 }
316
317 \"([^"\\]|\\.)*\"               {
318   yylval.s = xmemdup (yytext+1, yyleng-2, yyleng-1);
319   return STRING;
320 }
321 "["[^\[\]]*"]"                  {
322   yylval.s = xmemdup (yytext+1, yyleng-2, yyleng-1);
323   return ARRAY;
324 }
325 ^"%"{ID}                        {
326   yylval.s = xmemdup (yytext+1, yyleng-1, yyleng);
327   return PERCENT_ID;
328 }
329 "'"("\\".|[^\\])"'"             {
330   yylval.s = xmemdup (yytext+1, yyleng-2, yyleng);
331   return CHAR;
332 }
333
334 [(){},*:<>]                     { return yytext[0]; }
335
336 [;=]                            {
337   if (lexer_toplevel_done)
338     {
339       BEGIN(INITIAL);
340       lexer_toplevel_done = 0;
341     }
342   return yytext[0];
343 }
344
345 ^"%%"                           {
346   BEGIN(INITIAL);
347   return PERCENTPERCENT;
348 }
349
350 .                               {
351   error_at_line (&lexer_line, "unexpected character `%s'", yytext);
352 }
353 }
354
355 "/*"                    { BEGIN(in_comment); }
356 \n                      { lexer_line.line++; }
357 {ID}                    |
358 "'"("\\".|[^\\])"'"     |
359 [^"/\n]                 /* do nothing */
360 \"([^"\\]|\\.|\\\n)*\"  { update_lineno (yytext, yyleng); }
361 "/"/[^*]                /* do nothing */
362
363 <in_comment,in_struct_comment>{
364 \n              { lexer_line.line++; }
365 [^*\n]{16}      |
366 [^*\n]          /* do nothing */
367 "*"/[^/]        /* do nothing */
368 }
369 <in_comment>"*/"        { BEGIN(INITIAL); } 
370 <in_struct_comment>"*/" { BEGIN(in_struct); }
371
372 <in_yacc_escape>{
373 \n              { lexer_line.line++; }
374 [^%]{16}        |
375 [^%]            /* do nothing */
376 "%"/[^}]        /* do nothing */
377 "%}"            { BEGIN(in_struct); }
378 "%"             {
379   error_at_line (&lexer_line, 
380                  "unterminated %%{; unexpected EOF");
381 }
382 }
383
384
385 ["/]                    |
386 <in_struct_comment,in_comment>"*"       {
387   error_at_line (&lexer_line, 
388                  "unterminated comment or string; unexpected EOF");
389 }
390
391 ^"#define"{WS}"GTY(" /* do nothing */
392 {WS}"GTY"{WS}?"("       {
393   error_at_line (&lexer_line, "stray GTY marker");
394 }
395
396 %%
397
398 /* Deal with the expansion caused by the DEF_VEC_x macros.  */
399
400 typedef struct macro
401 {
402   const char *name;
403   const char *expansion;
404   struct macro *next;
405 } macro_t;
406
407 static const macro_t macro_defs[] = 
408 {
409 #define IN_GENGTYPE 1
410 #include "vec.h"
411   {NULL, NULL, NULL}
412 };
413
414 /* Chain of macro expansions to do at end of scanning.  */
415 static macro_t *macro_expns;
416
417 /* Push macro NAME (NAME_LEN) with argument ARG (ARG_LEN) onto the
418    expansion queue.  We ensure NAME is known at this point.  */
419
420 static void
421 push_macro_expansion (const char *name, unsigned name_len,
422                       const char *arg, unsigned arg_len)
423 {
424   unsigned ix;
425
426   for (ix = 0; macro_defs[ix].name; ix++)
427     if (strlen (macro_defs[ix].name) == name_len
428         && !memcmp (name, macro_defs[ix].name, name_len))
429       {
430         macro_t *expansion = xmalloc (sizeof (*expansion));
431
432         expansion->next = macro_expns;
433         expansion->name = xmemdup (arg, arg_len, arg_len+1);
434         expansion->expansion = macro_defs[ix].expansion;
435         macro_expns = expansion;
436         return;
437       }
438   error_at_line (&lexer_line, "unrecognized macro `%.*s(%.*s)'",
439                  name_len, name, arg_len, arg);
440 }
441
442 /* Attempt to read some input.  Use fread until we're at the end of
443    file.  At end of file expand the next queued macro.  We presume the
444    buffer is large enough for the entire expansion.  */
445
446 static unsigned
447 macro_input (char *buffer, unsigned size)
448 {
449   unsigned result;
450
451   result = fread (buffer, 1, size, yyin);
452   if (result)
453     /*NOP*/;
454   else if (ferror (yyin))
455     YY_FATAL_ERROR ("read of source file failed");
456   else if (macro_expns)
457     {
458       const char *expn;
459       unsigned len;
460
461       for (expn = macro_expns->expansion; *expn; expn++)
462         {
463           if (*expn == '#')
464             {
465               if (buffer[result-1] == ' ' && buffer[result-2] == '_')
466                 result--;
467               len = strlen (macro_expns->name);
468               memcpy (&buffer[result], macro_expns->name, len);
469               result += len;
470             }
471           else
472             {
473               buffer[result++] = *expn;
474               if (*expn == ';' || *expn == '{')
475                 buffer[result++] = '\n';
476             }
477         }
478       if (result > size)
479         YY_FATAL_ERROR ("buffer too small to expand macro");
480       macro_expns = macro_expns->next;
481     }
482   return result;
483 }
484
485 void
486 yyerror (const char *s)
487 {
488   error_at_line (&lexer_line, s);
489 }
490
491 void
492 parse_file (const char *fname)
493 {
494   yyin = fopen (fname, "r");
495   lexer_line.file = fname;
496   lexer_line.line = 1;
497   if (yyin == NULL)
498     {
499       perror (fname);
500       exit (1);
501     }
502   if (yyparse() != 0)
503     exit (1);
504   fclose (yyin);
505 }