OSDN Git Service

2004-07-14 Paolo Carlini <pcarlini@suse.de>
[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   namestart = xmemdup (namestart, namelen, namelen+1);
92 #ifdef USE_MAPPED_LOCATION
93   /* temporary kludge - gentype doesn't handle cpp conditionals */
94   if (strcmp (namestart, "location_t") != 0)
95 #endif
96   do_typedef (namestart, t, &lexer_line);
97   update_lineno (yytext, yyleng);
98 }
99
100 [^[:alnum:]_]typedef{WS}{ITYPE}{WS}{ID}{WS}?";" {
101
102   char *namestart;
103   size_t namelen;
104   struct type *t;
105   char *typestart;
106   size_t typelen;
107
108   for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--)
109     ;
110   for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
111     ;
112   namestart -= namelen - 1;
113   for (typestart = yytext + strlen (" typedef "); 
114        ISSPACE(*typestart);
115        typestart++)
116     ;
117   for (typelen = namestart - typestart; 
118        ISSPACE(typestart[typelen-1]); 
119        typelen--)
120     ;
121
122   t = create_scalar_type (typestart, typelen);
123   do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
124   update_lineno (yytext, yyleng);
125 }
126
127 [^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}PARAMS {
128   char *namestart;
129   size_t namelen;
130   struct type *t;
131
132   for (namestart = yytext + yyleng - 7; ISSPACE (*namestart); namestart--)
133     ;
134   for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
135     ;
136   namestart -= namelen - 1;
137
138   t = create_scalar_type ("function type", sizeof ("function type")-1);
139   do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
140   update_lineno (yytext, yyleng);
141 }
142
143 [^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}"(" {
144   char *namestart;
145   size_t namelen;
146   struct type *t;
147
148   for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--)
149     ;
150   for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
151     ;
152   namestart -= namelen - 1;
153
154   t = create_scalar_type ("function type", sizeof ("function type")-1);
155   do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
156   update_lineno (yytext, yyleng);
157 }
158
159 [^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?PARAMS {
160   char *namestart;
161   size_t namelen;
162   struct type *t;
163
164   for (namestart = yytext + yyleng - 7; !ISIDNUM (*namestart); namestart--)
165     ;
166   for (namelen = 1; ISIDNUM (namestart[-namelen]); namelen++)
167     ;
168   namestart -= namelen - 1;
169
170   t = create_scalar_type ("function type", sizeof ("function type")-1);
171   do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
172   update_lineno (yytext, yyleng);
173 }
174
175 [^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?"(" {
176   char *namestart;
177   size_t namelen;
178   struct type *t;
179
180   for (namestart = yytext + yyleng - 2; !ISIDNUM (*namestart); namestart--)
181     ;
182   for (namelen = 1; ISIDNUM (namestart[-namelen]); namelen++)
183     ;
184   namestart -= namelen - 1;
185
186   t = create_scalar_type ("function type", sizeof ("function type")-1);
187   do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
188   update_lineno (yytext, yyleng);
189 }
190
191 [^[:alnum:]_](typedef{WS})?(struct|union){WS}{ID}{WS}/"GTY" {
192   char *tagstart;
193   size_t taglen;
194   int typedef_p;
195   int union_p;
196
197   typedef_p = yytext[1] == 't';
198   if (typedef_p)
199     for (tagstart = yytext + strlen (" typedef "); 
200          ISSPACE(*tagstart);
201          tagstart++)
202       ;
203   else
204     tagstart = yytext + 1;
205
206   union_p = tagstart[0] == 'u';
207   tagstart += strlen ("union ");
208   while (ISSPACE (*tagstart))
209     tagstart++;
210   for (taglen = 1; ISIDNUM (tagstart[taglen]); taglen++)
211     ;
212
213   yylval.t = find_structure (xmemdup (tagstart, taglen, taglen + 1), union_p);
214   BEGIN(in_struct);
215   update_lineno (yytext, yyleng);
216   return typedef_p ? ENT_TYPEDEF_STRUCT : ENT_STRUCT;
217 }
218
219 [^[:alnum:]_](extern|static){WS}/"GTY" {
220   BEGIN(in_struct);
221   update_lineno (yytext, yyleng);
222   return ENT_EXTERNSTATIC;
223 }
224
225 ^"%union"{WS}"{"{WS}/"GTY" {
226   BEGIN(in_struct);
227   update_lineno (yytext, yyleng);
228   return ENT_YACCUNION;
229 }
230
231 ^"DEF_VEC_"[[:alnum:]_]*{WS}?"("{WS}?{ID}{WS}?")" {
232   char *macro, *arg;
233   unsigned macro_len, arg_len;
234   char *ptr = yytext;
235   type_p t;
236
237   /* Locate the macro and argument strings.  */
238   macro = ptr;
239   while (*ptr != '(' && !ISSPACE (*ptr))
240     ptr++;
241   macro_len = ptr - macro;
242   while (*ptr == '(' || ISSPACE (*ptr))
243     ptr++;
244   arg = ptr;
245   while (*ptr != ')' && !ISSPACE (*ptr))
246     ptr++;
247   arg_len = ptr - arg;
248
249   /* Push the macro for later expansion.  */
250   push_macro_expansion (macro, macro_len, arg, arg_len);
251
252   /* Create the struct and typedef.  */
253   ptr = xmemdup ("VEC_", 4, 4 + arg_len + 1);
254   memcpy (&ptr[4], arg, arg_len);
255   ptr[4 + arg_len] = 0;
256   t = find_structure (ptr, 0);
257   do_typedef (ptr, t, &lexer_line);
258 }
259
260 <in_struct>{
261
262 "/*"                            { BEGIN(in_struct_comment); }
263
264 ^"%{"                           { BEGIN(in_yacc_escape); }
265
266 ^"@@".*                         /* Used for c-parse.in C/ObjC demarcation.  */
267
268 {WS}                            { update_lineno (yytext, yyleng); }
269
270 "const"/[^[:alnum:]_]           /* don't care */
271 "GTY"/[^[:alnum:]_]             { return GTY_TOKEN; }
272 "union"/[^[:alnum:]_]           { return UNION; }
273 "struct"/[^[:alnum:]_]          { return STRUCT; }
274 "enum"/[^[:alnum:]_]            { return ENUM; }
275 "ptr_alias"/[^[:alnum:]_]       { return ALIAS; }
276 "nested_ptr"/[^[:alnum:]_]      { return NESTED_PTR; }
277 [0-9]+                          { return NUM; }
278 "param"[0-9]*"_is"/[^[:alnum:]_]                { 
279   yylval.s = xmemdup (yytext, yyleng, yyleng+1);
280   return PARAM_IS;
281 }
282
283 {IWORD}({WS}{IWORD})*/[^[:alnum:]_]             |
284 "ENUM_BITFIELD"{WS}?"("{WS}?{ID}{WS}?")"        {
285   size_t len;
286
287   for (len = yyleng; ISSPACE (yytext[len-1]); len--)
288     ;
289
290   yylval.t = create_scalar_type (yytext, len);
291   update_lineno (yytext, yyleng);
292   return SCALAR;
293 }
294
295 "VEC"{WS}?"("{WS}?{ID}{WS}?")" {
296   char *macro, *arg;
297   unsigned macro_len, arg_len;
298   char *ptr = yytext;
299
300   macro = ptr;
301   while (*ptr != '(' && !ISSPACE (*ptr))
302     ptr++;
303   macro_len = ptr - macro;
304   while (*ptr == '(' || ISSPACE (*ptr))
305     ptr++;
306   arg = ptr;
307   while (*ptr != ')' && !ISSPACE (*ptr))
308     ptr++;
309   arg_len = ptr - arg;
310   ptr = xmemdup (macro, macro_len, macro_len + arg_len + 2);
311   ptr[macro_len] = '_';
312   memcpy (&ptr[macro_len+1], arg, arg_len);
313   yylval.s = ptr;
314   return ID;
315 }
316
317 {ID}/[^[:alnum:]_]              {
318   yylval.s = xmemdup (yytext, yyleng, yyleng+1);
319   return ID;
320 }
321
322 \"([^"\\]|\\.)*\"               {
323   yylval.s = xmemdup (yytext+1, yyleng-2, yyleng-1);
324   return STRING;
325 }
326 "["[^\[\]]*"]"                  {
327   yylval.s = xmemdup (yytext+1, yyleng-2, yyleng-1);
328   return ARRAY;
329 }
330 ^"%"{ID}                        {
331   yylval.s = xmemdup (yytext+1, yyleng-1, yyleng);
332   return PERCENT_ID;
333 }
334 "'"("\\".|[^\\])"'"             {
335   yylval.s = xmemdup (yytext+1, yyleng-2, yyleng);
336   return CHAR;
337 }
338
339 [(){},*:<>]                     { return yytext[0]; }
340
341 [;=]                            {
342   if (lexer_toplevel_done)
343     {
344       BEGIN(INITIAL);
345       lexer_toplevel_done = 0;
346     }
347   return yytext[0];
348 }
349
350 ^"%%"                           {
351   BEGIN(INITIAL);
352   return PERCENTPERCENT;
353 }
354
355 .                               {
356   error_at_line (&lexer_line, "unexpected character `%s'", yytext);
357 }
358 }
359
360 "/*"                    { BEGIN(in_comment); }
361 \n                      { lexer_line.line++; }
362 {ID}                    |
363 "'"("\\".|[^\\])"'"     |
364 [^"/\n]                 /* do nothing */
365 \"([^"\\]|\\.|\\\n)*\"  { update_lineno (yytext, yyleng); }
366 "/"/[^*]                /* do nothing */
367
368 <in_comment,in_struct_comment>{
369 \n              { lexer_line.line++; }
370 [^*\n]{16}      |
371 [^*\n]          /* do nothing */
372 "*"/[^/]        /* do nothing */
373 }
374 <in_comment>"*/"        { BEGIN(INITIAL); } 
375 <in_struct_comment>"*/" { BEGIN(in_struct); }
376
377 <in_yacc_escape>{
378 \n              { lexer_line.line++; }
379 [^%]{16}        |
380 [^%]            /* do nothing */
381 "%"/[^}]        /* do nothing */
382 "%}"            { BEGIN(in_struct); }
383 "%"             {
384   error_at_line (&lexer_line, 
385                  "unterminated %%{; unexpected EOF");
386 }
387 }
388
389
390 ["/]                    |
391 <in_struct_comment,in_comment>"*"       {
392   error_at_line (&lexer_line, 
393                  "unterminated comment or string; unexpected EOF");
394 }
395
396 ^"#define"{WS}"GTY(" /* do nothing */
397 {WS}"GTY"{WS}?"("       {
398   error_at_line (&lexer_line, "stray GTY marker");
399 }
400
401 %%
402
403 /* Deal with the expansion caused by the DEF_VEC_x macros.  */
404
405 typedef struct macro
406 {
407   const char *name;
408   const char *expansion;
409   struct macro *next;
410 } macro_t;
411
412 static const macro_t macro_defs[] = 
413 {
414 #define IN_GENGTYPE 1
415 #include "vec.h"
416   {NULL, NULL, NULL}
417 };
418
419 /* Chain of macro expansions to do at end of scanning.  */
420 static macro_t *macro_expns;
421
422 /* Push macro NAME (NAME_LEN) with argument ARG (ARG_LEN) onto the
423    expansion queue.  We ensure NAME is known at this point.  */
424
425 static void
426 push_macro_expansion (const char *name, unsigned name_len,
427                       const char *arg, unsigned arg_len)
428 {
429   unsigned ix;
430
431   for (ix = 0; macro_defs[ix].name; ix++)
432     if (strlen (macro_defs[ix].name) == name_len
433         && !memcmp (name, macro_defs[ix].name, name_len))
434       {
435         macro_t *expansion = xmalloc (sizeof (*expansion));
436
437         expansion->next = macro_expns;
438         expansion->name = xmemdup (arg, arg_len, arg_len+1);
439         expansion->expansion = macro_defs[ix].expansion;
440         macro_expns = expansion;
441         return;
442       }
443   error_at_line (&lexer_line, "unrecognized macro `%.*s(%.*s)'",
444                  name_len, name, arg_len, arg);
445 }
446
447 /* Attempt to read some input.  Use fread until we're at the end of
448    file.  At end of file expand the next queued macro.  We presume the
449    buffer is large enough for the entire expansion.  */
450
451 static unsigned
452 macro_input (char *buffer, unsigned size)
453 {
454   unsigned result;
455
456   result = fread (buffer, 1, size, yyin);
457   if (result)
458     /*NOP*/;
459   else if (ferror (yyin))
460     YY_FATAL_ERROR ("read of source file failed");
461   else if (macro_expns)
462     {
463       const char *expn;
464       unsigned len;
465
466       for (expn = macro_expns->expansion; *expn; expn++)
467         {
468           if (*expn == '#')
469             {
470               if (buffer[result-1] == ' ' && buffer[result-2] == '_')
471                 result--;
472               len = strlen (macro_expns->name);
473               memcpy (&buffer[result], macro_expns->name, len);
474               result += len;
475             }
476           else
477             {
478               buffer[result++] = *expn;
479               if (*expn == ';' || *expn == '{')
480                 buffer[result++] = '\n';
481             }
482         }
483       if (result > size)
484         YY_FATAL_ERROR ("buffer too small to expand macro");
485       macro_expns = macro_expns->next;
486     }
487   return result;
488 }
489
490 void
491 yyerror (const char *s)
492 {
493   error_at_line (&lexer_line, s);
494 }
495
496 void
497 parse_file (const char *fname)
498 {
499   yyin = fopen (fname, "r");
500   lexer_line.file = fname;
501   lexer_line.line = 1;
502   if (yyin == NULL)
503     {
504       perror (fname);
505       exit (1);
506     }
507   if (yyparse() != 0)
508     exit (1);
509   fclose (yyin);
510 }