gcc/ChangeLog ---------------------------------------------------------
[official-gcc.git] / gcc / gengtype-lex.l
blob51cd95a6310392966daadec2546525f26c2883f2
1 /* -*- indented-text -*- */
2 /* Process source files and output type information.
3    Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
5 This file is part of GCC.
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.
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.
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, 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA.  */
23 #include "bconfig.h"
24 #include "coretypes.h"
25 #include "system.h"
27 #define malloc xmalloc
28 #define realloc xrealloc
30 #include "gengtype.h"
31 #include "gengtype-yacc.h"
33 #define YY_INPUT(BUF,RESULT,SIZE) ((RESULT) = macro_input (BUF,SIZE))
35 static unsigned macro_input (char *buffer, unsigned);
36 static const char *push_macro_expansion (const char *, unsigned,
37                                          const char *, unsigned);
38 static char *mangle_macro_name (const char *, unsigned,
39                                 const char *, unsigned);
40 static void update_lineno (const char *l, size_t len);
42 struct fileloc lexer_line;
43 int lexer_toplevel_done;
45 static void 
46 update_lineno (const char *l, size_t len)
48   while (len-- > 0)
49     if (*l++ == '\n')
50       lexer_line.line++;
55 ID      [[:alpha:]_][[:alnum:]_]*
56 WS      [[:space:]]+
57 IWORD   short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD
58 ITYPE   {IWORD}({WS}{IWORD})*
60 %x in_struct in_struct_comment in_comment in_yacc_escape
61 %option warn noyywrap nounput nodefault perf-report
62 %option 8bit never-interactive
65 [^[:alnum:]_]typedef{WS}(struct|union){WS}{ID}{WS}?[*[:space:]]{WS}?{ID}{WS}?";" {
66   char *tagstart;
67   size_t taglen;
68   char *namestart;
69   size_t namelen;
70   int is_pointer = 0;
71   struct type *t;
72   int union_p;
74   tagstart = yytext + strlen (" typedef ");
75   while (ISSPACE (*tagstart))
76     tagstart++;
77   union_p = tagstart[0] == 'u';
78   tagstart += strlen ("union ");
79   while (ISSPACE (*tagstart))
80     tagstart++;
81   for (taglen = 1; ISIDNUM (tagstart[taglen]); taglen++)
82     ;
83   for (namestart = tagstart + taglen; 
84        ! ISIDNUM (*namestart);
85        namestart++)
86     if (*namestart == '*')
87       is_pointer = 1;
88   for (namelen = 1; ISIDNUM (namestart[namelen]); namelen++)
89     ;
90   t = find_structure ((const char *) xmemdup (tagstart, taglen, taglen+1),
91                       union_p);
92   if (is_pointer)
93     t = create_pointer (t);
94   namestart = (char *) xmemdup (namestart, namelen, namelen+1);
95 #ifdef USE_MAPPED_LOCATION
96   /* temporary kludge - gentype doesn't handle cpp conditionals */
97   if (strcmp (namestart, "location_t") != 0
98       && strcmp (namestart, "expanded_location") != 0)
99 #endif
100   do_typedef (namestart, t, &lexer_line);
101   update_lineno (yytext, yyleng);
104 [^[:alnum:]_]typedef{WS}{ITYPE}{WS}{ID}{WS}?";" {
106   char *namestart;
107   size_t namelen;
108   struct type *t;
109   char *typestart;
110   size_t typelen;
112   for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--)
113     ;
114   for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
115     ;
116   namestart -= namelen - 1;
117   for (typestart = yytext + strlen (" typedef "); 
118        ISSPACE(*typestart);
119        typestart++)
120     ;
121   for (typelen = namestart - typestart;
122        ISSPACE (typestart[typelen-1]);
123        typelen--)
124     ;
126   t = create_scalar_type (typestart, typelen);
127   do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
128               &lexer_line);
129   update_lineno (yytext, yyleng);
132 [^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}PARAMS {
133   char *namestart;
134   size_t namelen;
135   struct type *t;
137   for (namestart = yytext + yyleng - 7; ISSPACE (*namestart); namestart--)
138     ;
139   for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
140     ;
141   namestart -= namelen - 1;
143   t = create_scalar_type ("function type", sizeof ("function type")-1);
144   do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
145               &lexer_line);
146   update_lineno (yytext, yyleng);
149 [^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}"(" {
150   char *namestart;
151   size_t namelen;
152   struct type *t;
154   for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--)
155     ;
156   for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
157     ;
158   namestart -= namelen - 1;
160   t = create_scalar_type ("function type", sizeof ("function type")-1);
161   do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
162               &lexer_line);
163   update_lineno (yytext, yyleng);
166 [^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?PARAMS {
167   char *namestart;
168   size_t namelen;
169   struct type *t;
171   for (namestart = yytext + yyleng - 7; !ISIDNUM (*namestart); namestart--)
172     ;
173   for (namelen = 1; ISIDNUM (namestart[-namelen]); namelen++)
174     ;
175   namestart -= namelen - 1;
177   t = create_scalar_type ("function type", sizeof ("function type")-1);
178   do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
179               &lexer_line);
180   update_lineno (yytext, yyleng);
183 [^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?"(" {
184   char *namestart;
185   size_t namelen;
186   struct type *t;
188   for (namestart = yytext + yyleng - 2; !ISIDNUM (*namestart); namestart--)
189     ;
190   for (namelen = 1; ISIDNUM (namestart[-namelen]); namelen++)
191     ;
192   namestart -= namelen - 1;
194   t = create_scalar_type ("function type", sizeof ("function type")-1);
195   do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
196               &lexer_line);
197   update_lineno (yytext, yyleng);
200 [^[:alnum:]_](typedef{WS})?(struct|union){WS}{ID}{WS}/"GTY" {
201   char *tagstart;
202   size_t taglen;
203   int typedef_p;
204   int union_p;
206   typedef_p = yytext[1] == 't';
207   if (typedef_p)
208     for (tagstart = yytext + strlen (" typedef "); 
209          ISSPACE(*tagstart);
210          tagstart++)
211       ;
212   else
213     tagstart = yytext + 1;
215   union_p = tagstart[0] == 'u';
216   tagstart += strlen ("union ");
217   while (ISSPACE (*tagstart))
218     tagstart++;
219   for (taglen = 1; ISIDNUM (tagstart[taglen]); taglen++)
220     ;
222   yylval.t = find_structure ((const char *) xmemdup (tagstart, taglen,
223                                                      taglen + 1),
224                              union_p);
225   BEGIN(in_struct);
226   update_lineno (yytext, yyleng);
227   return typedef_p ? ENT_TYPEDEF_STRUCT : ENT_STRUCT;
230 [^[:alnum:]_](extern|static){WS}/"GTY" {
231   BEGIN(in_struct);
232   update_lineno (yytext, yyleng);
233   return ENT_EXTERNSTATIC;
236 ^"%union"{WS}"{"{WS}/"GTY" {
237   BEGIN(in_struct);
238   update_lineno (yytext, yyleng);
239   return ENT_YACCUNION;
242 ^"DEF_VEC_"[[:alnum:]_]*{WS}?"("{WS}?{ID}{WS}?(","{WS}?{ID}{WS}?)*")" {
243   char *macro, *arg;
244   unsigned macro_len, arg_len;
245   char *ptr = yytext;
246   const char *additional;
247   type_p t;
249   /* Find the macro name.  */
250   for (macro = ptr; *ptr != '(' && !ISSPACE (*ptr); ptr++)
251     continue;
252   for (macro_len = ptr - macro; !(ISALNUM (*ptr) || *ptr == '_'); ptr++)
253     continue;
255   /* Find the argument(s).  */
256   for (arg = ptr; *ptr != ')'; ptr++)
257     continue;
258   arg_len = ptr - arg;
260   /* Create the struct and typedef.  */
261   ptr = mangle_macro_name ("VEC", 3, arg, arg_len);
263   t = find_structure (ptr, 0);
264   do_typedef (ptr, t, &lexer_line);
266   /* Push the macro for later expansion.  */
267   additional = push_macro_expansion (macro, macro_len, arg, arg_len);
269   if (additional)
270     {
271       ptr = mangle_macro_name (ptr, strlen (ptr),
272                                additional, strlen (additional));
273       t = find_structure (ptr, 0);
274       do_typedef (ptr, t, &lexer_line);
275     }
278 <in_struct>{
280 "/*"                            { BEGIN(in_struct_comment); }
282 ^"%{"                           { BEGIN(in_yacc_escape); } /* } */
284 {WS}                            { update_lineno (yytext, yyleng); }
286 "const"/[^[:alnum:]_]           /* don't care */
287 "GTY"/[^[:alnum:]_]             { return GTY_TOKEN; }
288 "union"/[^[:alnum:]_]           { return UNION; }
289 "struct"/[^[:alnum:]_]          { return STRUCT; }
290 "enum"/[^[:alnum:]_]            { return ENUM; }
291 "ptr_alias"/[^[:alnum:]_]       { return ALIAS; }
292 "nested_ptr"/[^[:alnum:]_]      { return NESTED_PTR; }
293 [0-9]+                          { return NUM; }
294 "param"[0-9]*"_is"/[^[:alnum:]_]                {
295   yylval.s = (const char *) xmemdup (yytext, yyleng, yyleng+1);
296   return PARAM_IS;
299 {IWORD}({WS}{IWORD})*/[^[:alnum:]_]             |
300 "ENUM_BITFIELD"{WS}?"("{WS}?{ID}{WS}?")"        {
301   size_t len;
303   for (len = yyleng; ISSPACE (yytext[len-1]); len--)
304     ;
306   yylval.t = create_scalar_type (yytext, len);
307   update_lineno (yytext, yyleng);
308   return SCALAR;
311 "VEC"{WS}?"("{WS}?{ID}{WS}?(","{WS}?{ID}{WS}?)*")" {
312   char *macro, *arg;
313   unsigned macro_len, arg_len;
314   char *ptr = yytext;
316   /* Find the macro name */
317   for (macro = ptr; *ptr != '(' && !ISSPACE (*ptr); ptr++)
318     continue;
319   for (macro_len = ptr - macro; !(ISALNUM(*ptr) || *ptr == '_'); ptr++)
320     continue;
322   /* Find the arguments.  */
323   for (arg = ptr; *ptr != ')'; ptr++)
324     continue;
325   arg_len = ptr - arg;
327   ptr = mangle_macro_name (macro, macro_len, arg, arg_len);
328   yylval.s = ptr;
329   return ID;
332 {ID}/[^[:alnum:]_]              {
333   yylval.s = (const char *) xmemdup (yytext, yyleng, yyleng+1);
334   return ID;
337 \"([^"\\]|\\.)*\"               {
338   yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng-1);
339   return STRING;
341 "["[^\[\]]*"]"                  {
342   yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng-1);
343   return ARRAY;
345 ^"%"{ID}                        {
346   yylval.s = (const char *) xmemdup (yytext+1, yyleng-1, yyleng);
347   return PERCENT_ID;
349 "'"("\\".|[^\\])"'"             {
350   yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng);
351   return CHAR;
354 [(){},*:<>]                     { return yytext[0]; }
356 [;=]                            {
357   if (lexer_toplevel_done)
358     {
359       BEGIN(INITIAL);
360       lexer_toplevel_done = 0;
361     }
362   return yytext[0];
365 ^"%%"                           {
366   BEGIN(INITIAL);
367   return PERCENTPERCENT;
370 "#define"[^\n]*\n               {lexer_line.line++;}
372 .                               {
373   error_at_line (&lexer_line, "unexpected character `%s'", yytext);
377 "/*"                    { BEGIN(in_comment); }
378 \n                      { lexer_line.line++; }
379 {ID}                    |
380 "'"("\\".|[^\\])"'"     |
381 [^"/\n]                 /* do nothing */
382 \"([^"\\]|\\.|\\\n)*\"  { update_lineno (yytext, yyleng); }
383 "/"/[^*]                /* do nothing */
385 <in_comment,in_struct_comment>{
386 \n              { lexer_line.line++; }
387 [^*\n]{16}      |
388 [^*\n]          /* do nothing */
389 "*"/[^/]        /* do nothing */
391 <in_comment>"*/"        { BEGIN(INITIAL); } 
392 <in_struct_comment>"*/" { BEGIN(in_struct); }
394 <in_yacc_escape>{
395 \n              { lexer_line.line++; }
396 [^%]{16}        |
397 [^%]            /* do nothing */
398 "%"/[^}]        /* do nothing */
399 "%}"            { BEGIN(in_struct); }
400 "%"             {
401   error_at_line (&lexer_line, 
402                  "unterminated %%{; unexpected EOF");
407 ["/]                    |
408 <in_struct_comment,in_comment>"*"       {
409   error_at_line (&lexer_line, 
410                  "unterminated comment or string; unexpected EOF");
413 ^"#define"{WS}"GTY(" /* do nothing */
414 {WS}"GTY"{WS}?"("       {
415   error_at_line (&lexer_line, "stray GTY marker");
420 /* Deal with the expansion caused by the DEF_VEC_x macros.  */
422 /* Mangle a macro and argument list as done by cpp concatenation in
423    the compiler proper.  */
424 static char *
425 mangle_macro_name (const char *macro, unsigned macro_len,
426                    const char *arg, unsigned arg_len)
428   char *ptr = (char *) xmemdup (macro, macro_len, macro_len + arg_len + 2);
430   /* Now copy and concatenate each argument */
431   while (arg_len)
432     {
433       ptr[macro_len++] = '_';
434       for (; arg_len && (ISALNUM(*arg) || *arg == '_'); arg_len--)
435         ptr[macro_len++] = *arg++;
436       for (; arg_len && !(ISALNUM(*arg) || *arg == '_'); arg_len--)
437         arg++;
438     }
439   ptr[macro_len] = 0;
441   return ptr;
444 typedef struct macro_def
446   const char *name;
447   const char *expansion;
448   const char *additional;
449 } macro_def_t;
451 typedef struct macro
453   const macro_def_t *def;
454   struct macro *next;
455   const char *args[10];
456 } macro_t;
458 static const macro_def_t macro_defs[] = 
460 #define IN_GENGTYPE 1
461 #include "vec.h"
462   {NULL, NULL, NULL}
465 /* Chain of macro expansions to do at end of scanning.  */
466 static macro_t *macro_expns;
467 static macro_t *macro_expns_end;
469 /* Push macro NAME (NAME_LEN) with argument ARG (ARG_LEN) onto the
470    expansion queue.  We ensure NAME is known at this point.  */
472 static const char *
473 push_macro_expansion (const char *name, unsigned name_len,
474                       const char *arg, unsigned arg_len)
476   unsigned ix;
478   for (ix = 0; macro_defs[ix].name; ix++)
479     if (strlen (macro_defs[ix].name) == name_len
480         && !memcmp (name, macro_defs[ix].name, name_len))
481       {
482         macro_t *expansion = XNEW (macro_t);
483         char *args;
484         unsigned argno, last_arg;
486         expansion->def = &macro_defs[ix];
487         expansion->next = NULL;
488         args = (char *) xmemdup (arg, arg_len, arg_len+1);
489         args[arg_len] = 0;
490         for (argno = 0; *args;)
491           {
492             expansion->args[argno++] = args;
493             while (*args && (ISALNUM (*args) || *args == '_'))
494               args++;
495             if (argno == 1)
496               expansion->args[argno++] = "base";
497             if (!*args)
498               break;
499             *args++ = 0;
500             while (*args && !(ISALNUM (*args) || *args == '_'))
501               args++;
502           }
503         last_arg = argno;
504         for (; argno != 10; argno++)
505           expansion->args[argno] = NULL;
506         if (macro_expns_end)
507           macro_expns_end->next = expansion;
508         else
509           macro_expns = expansion;
510         macro_expns_end = expansion;
511         if (macro_defs[ix].additional)
512           {
513             macro_t *expn2 = XNEW (macro_t);
514             memcpy (expn2, expansion, sizeof (*expn2));
515             expansion = expn2;
516             expansion->def += 1;
517             expansion->args[last_arg++] = macro_defs[ix].additional;
518             macro_expns_end->next = expansion;
519             macro_expns_end = expansion;
520           }
521         if (last_arg > 2 && strcmp (expansion->args[last_arg - 1], "heap"))
522           expansion->args[last_arg++] = "GTY (())";
523         return macro_defs[ix].additional;
524       }
525   error_at_line (&lexer_line, "unrecognized macro `%.*s(%.*s)'",
526                  name_len, name, arg_len, arg);
527   return NULL;
530 /* Attempt to read some input.  Use fread until we're at the end of
531    file.  At end of file expand the next queued macro.  We presume the
532    buffer is large enough for the entire expansion.  */
534 static unsigned
535 macro_input (char *buffer, unsigned size)
537   unsigned result;
539   result = fread (buffer, 1, size, yyin);
540   if (result)
541     /*NOP*/;
542   else if (ferror (yyin))
543     YY_FATAL_ERROR ("read of source file failed");
544   else if (macro_expns)
545     {
546       const char *expn;
547       unsigned len;
549       for (expn = macro_expns->def->expansion; *expn; expn++)
550         {
551           if (*expn == '#')
552             {
553               int argno;
555               argno = expn[1] - '0';
556               expn += 1;
558               /* Remove inserted space? */
559               if (buffer[result-1] == ' ' && buffer[result-2] == '_')
560                 result--;
562               /* Insert the argument value */
563               if (macro_expns->args[argno])
564                 {
565                   len = strlen (macro_expns->args[argno]);
566                   memcpy (&buffer[result], macro_expns->args[argno], len);
567                   result += len;
568                 }
570               /* Skip next space? */
571               if (expn[1] == ' ' && expn[2] == '_')
572                 expn++;
573             }
574           else
575             {
576               buffer[result++] = *expn;
577               if (*expn == ';' || *expn == '{')
578                 buffer[result++] = '\n';
579             }
580         }
581       if (result > size)
582         YY_FATAL_ERROR ("buffer too small to expand macro");
583       macro_expns = macro_expns->next;
584       if (!macro_expns)
585         macro_expns_end = NULL;
586     }
587   return result;
590 void
591 yyerror (const char *s)
593   error_at_line (&lexer_line, s);
596 void
597 parse_file (const char *fname)
599   yyin = fopen (fname, "r");
600   lexer_line.file = fname;
601   lexer_line.line = 1;
602   if (yyin == NULL)
603     {
604       perror (fname);
605       exit (1);
606     }
607   if (yyparse() != 0)
608     exit (1);
609   fclose (yyin);