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