1/* -*- indented-text -*- */
2/* Process source files and output type information.
3   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING.  If not, write to the Free
19Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2002110-1301, 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
35static unsigned macro_input (char *buffer, unsigned);
36static const char *push_macro_expansion (const char *, unsigned,
37					 const char *, unsigned);
38static char *mangle_macro_name (const char *, unsigned,
39       			        const char *, unsigned);
40static void update_lineno (const char *l, size_t len);
41
42struct fileloc lexer_line;
43int lexer_toplevel_done;
44
45static void
46update_lineno (const char *l, size_t len)
47{
48  while (len-- > 0)
49    if (*l++ == '\n')
50      lexer_line.line++;
51}
52
53%}
54
55ID	[[:alpha:]_][[:alnum:]_]*
56WS	[[:space:]]+
57IWORD	short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD
58ITYPE	{IWORD}({WS}{IWORD})*
59
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
63%%
64
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;
73
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);
102}
103
104[^[:alnum:]_]typedef{WS}{ITYPE}{WS}{ID}{WS}?";" {
105
106  char *namestart;
107  size_t namelen;
108  struct type *t;
109  char *typestart;
110  size_t typelen;
111
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    ;
125
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);
130}
131
132[^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}PARAMS {
133  char *namestart;
134  size_t namelen;
135  struct type *t;
136
137  for (namestart = yytext + yyleng - 7; ISSPACE (*namestart); namestart--)
138    ;
139  for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
140    ;
141  namestart -= namelen - 1;
142
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);
147}
148
149[^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}"(" {
150  char *namestart;
151  size_t namelen;
152  struct type *t;
153
154  for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--)
155    ;
156  for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
157    ;
158  namestart -= namelen - 1;
159
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);
164}
165
166[^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?PARAMS {
167  char *namestart;
168  size_t namelen;
169  struct type *t;
170
171  for (namestart = yytext + yyleng - 7; !ISIDNUM (*namestart); namestart--)
172    ;
173  for (namelen = 1; ISIDNUM (namestart[-namelen]); namelen++)
174    ;
175  namestart -= namelen - 1;
176
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);
181}
182
183[^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?"(" {
184  char *namestart;
185  size_t namelen;
186  struct type *t;
187
188  for (namestart = yytext + yyleng - 2; !ISIDNUM (*namestart); namestart--)
189    ;
190  for (namelen = 1; ISIDNUM (namestart[-namelen]); namelen++)
191    ;
192  namestart -= namelen - 1;
193
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);
198}
199
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;
205
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;
214
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    ;
221
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;
228}
229
230[^[:alnum:]_](extern|static){WS}/"GTY" {
231  BEGIN(in_struct);
232  update_lineno (yytext, yyleng);
233  return ENT_EXTERNSTATIC;
234}
235
236^"%union"{WS}"{"{WS}/"GTY" {
237  BEGIN(in_struct);
238  update_lineno (yytext, yyleng);
239  return ENT_YACCUNION;
240}
241
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;
248
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;
254
255  /* Find the argument(s).  */
256  for (arg = ptr; *ptr != ')'; ptr++)
257    continue;
258  arg_len = ptr - arg;
259
260  /* Create the struct and typedef.  */
261  ptr = mangle_macro_name ("VEC", 3, arg, arg_len);
262
263  t = find_structure (ptr, 0);
264  do_typedef (ptr, t, &lexer_line);
265
266  /* Push the macro for later expansion.  */
267  additional = push_macro_expansion (macro, macro_len, arg, arg_len);
268
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    }
276}
277
278<in_struct>{
279
280"/*"				{ BEGIN(in_struct_comment); }
281
282^"%{"				{ BEGIN(in_yacc_escape); } /* } */
283
284{WS}				{ update_lineno (yytext, yyleng); }
285
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;
297}
298
299{IWORD}({WS}{IWORD})*/[^[:alnum:]_]		|
300"ENUM_BITFIELD"{WS}?"("{WS}?{ID}{WS}?")"	{
301  size_t len;
302
303  for (len = yyleng; ISSPACE (yytext[len-1]); len--)
304    ;
305
306  yylval.t = create_scalar_type (yytext, len);
307  update_lineno (yytext, yyleng);
308  return SCALAR;
309}
310
311"VEC"{WS}?"("{WS}?{ID}{WS}?(","{WS}?{ID}{WS}?)*")" {
312  char *macro, *arg;
313  unsigned macro_len, arg_len;
314  char *ptr = yytext;
315
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;
321
322  /* Find the arguments.  */
323  for (arg = ptr; *ptr != ')'; ptr++)
324    continue;
325  arg_len = ptr - arg;
326
327  ptr = mangle_macro_name (macro, macro_len, arg, arg_len);
328  yylval.s = ptr;
329  return ID;
330}
331
332{ID}/[^[:alnum:]_]		{
333  yylval.s = (const char *) xmemdup (yytext, yyleng, yyleng+1);
334  return ID;
335}
336
337\"([^"\\]|\\.)*\"		{
338  yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng-1);
339  return STRING;
340}
341"["[^\[\]]*"]"			{
342  yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng-1);
343  return ARRAY;
344}
345^"%"{ID}			{
346  yylval.s = (const char *) xmemdup (yytext+1, yyleng-1, yyleng);
347  return PERCENT_ID;
348}
349"'"("\\".|[^\\])"'"		{
350  yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng);
351  return CHAR;
352}
353
354[(){},*:<>]			{ return yytext[0]; }
355
356[;=]				{
357  if (lexer_toplevel_done)
358    {
359      BEGIN(INITIAL);
360      lexer_toplevel_done = 0;
361    }
362  return yytext[0];
363}
364
365^"%%"				{
366  BEGIN(INITIAL);
367  return PERCENTPERCENT;
368}
369
370"#define"[^\n]*\n		{lexer_line.line++;}
371
372.				{
373  error_at_line (&lexer_line, "unexpected character `%s'", yytext);
374}
375}
376
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 */
384
385<in_comment,in_struct_comment>{
386\n		{ lexer_line.line++; }
387[^*\n]{16}	|
388[^*\n]		/* do nothing */
389"*"/[^/]	/* do nothing */
390}
391<in_comment>"*/"	{ BEGIN(INITIAL); }
392<in_struct_comment>"*/"	{ BEGIN(in_struct); }
393
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");
403}
404}
405
406
407["/]    		|
408<in_struct_comment,in_comment>"*"	{
409  error_at_line (&lexer_line,
410		 "unterminated comment or string; unexpected EOF");
411}
412
413^"#define"{WS}"GTY(" /* do nothing */
414{WS}"GTY"{WS}?"("	{
415  error_at_line (&lexer_line, "stray GTY marker");
416}
417
418%%
419
420/* Deal with the expansion caused by the DEF_VEC_x macros.  */
421
422/* Mangle a macro and argument list as done by cpp concatenation in
423   the compiler proper.  */
424static char *
425mangle_macro_name (const char *macro, unsigned macro_len,
426		   const char *arg, unsigned arg_len)
427{
428  char *ptr = (char *) xmemdup (macro, macro_len, macro_len + arg_len + 2);
429
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;
440
441  return ptr;
442}
443
444typedef struct macro_def
445{
446  const char *name;
447  const char *expansion;
448  const char *additional;
449} macro_def_t;
450
451typedef struct macro
452{
453  const macro_def_t *def;
454  struct macro *next;
455  const char *args[10];
456} macro_t;
457
458static const macro_def_t macro_defs[] =
459{
460#define IN_GENGTYPE 1
461#include "vec.h"
462  {NULL, NULL, NULL}
463};
464
465/* Chain of macro expansions to do at end of scanning.  */
466static macro_t *macro_expns;
467static macro_t *macro_expns_end;
468
469/* Push macro NAME (NAME_LEN) with argument ARG (ARG_LEN) onto the
470   expansion queue.  We ensure NAME is known at this point.  */
471
472static const char *
473push_macro_expansion (const char *name, unsigned name_len,
474		      const char *arg, unsigned arg_len)
475{
476  unsigned ix;
477
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;
485
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;
528}
529
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.  */
533
534static unsigned
535macro_input (char *buffer, unsigned size)
536{
537  unsigned result;
538
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;
548
549      for (expn = macro_expns->def->expansion; *expn; expn++)
550        {
551	  if (*expn == '#')
552	    {
553	      int argno;
554
555	      argno = expn[1] - '0';
556	      expn += 1;
557
558	      /* Remove inserted space? */
559	      if (buffer[result-1] == ' ' && buffer[result-2] == '_')
560	        result--;
561
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		}
569
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;
588}
589
590void
591yyerror (const char *s)
592{
593  error_at_line (&lexer_line, "%s", s);
594}
595
596void
597parse_file (const char *fname)
598{
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);
610}
611