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 = ¯o_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