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