1 %{ /* deffilep.y - parser for .def files */ 2 3 /* Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005 4 Free Software Foundation, Inc. 5 6 This file is part of GNU Binutils. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 21 22 #include <stdio.h> 23 #include "libiberty.h" 24 #include "safe-ctype.h" 25 #include "bfd.h" 26 #include "sysdep.h" 27 #include "ld.h" 28 #include "ldmisc.h" 29 #include "deffile.h" 30 31 #define TRACE 0 32 33 #define ROUND_UP(a, b) (((a)+((b)-1))&~((b)-1)) 34 35 /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc), 36 as well as gratuitiously global symbol names, so we can have multiple 37 yacc generated parsers in ld. Note that these are only the variables 38 produced by yacc. If other parser generators (bison, byacc, etc) produce 39 additional global names that conflict at link time, then those parser 40 generators need to be fixed instead of adding those names to this list. */ 41 42 #define yymaxdepth def_maxdepth 43 #define yyparse def_parse 44 #define yylex def_lex 45 #define yyerror def_error 46 #define yylval def_lval 47 #define yychar def_char 48 #define yydebug def_debug 49 #define yypact def_pact 50 #define yyr1 def_r1 51 #define yyr2 def_r2 52 #define yydef def_def 53 #define yychk def_chk 54 #define yypgo def_pgo 55 #define yyact def_act 56 #define yyexca def_exca 57 #define yyerrflag def_errflag 58 #define yynerrs def_nerrs 59 #define yyps def_ps 60 #define yypv def_pv 61 #define yys def_s 62 #define yy_yys def_yys 63 #define yystate def_state 64 #define yytmp def_tmp 65 #define yyv def_v 66 #define yy_yyv def_yyv 67 #define yyval def_val 68 #define yylloc def_lloc 69 #define yyreds def_reds /* With YYDEBUG defined. */ 70 #define yytoks def_toks /* With YYDEBUG defined. */ 71 #define yylhs def_yylhs 72 #define yylen def_yylen 73 #define yydefred def_yydefred 74 #define yydgoto def_yydgoto 75 #define yysindex def_yysindex 76 #define yyrindex def_yyrindex 77 #define yygindex def_yygindex 78 #define yytable def_yytable 79 #define yycheck def_yycheck 80 81 static void def_description (const char *); 82 static void def_exports (const char *, const char *, int, int); 83 static void def_heapsize (int, int); 84 static void def_import (const char *, const char *, const char *, const char *, 85 int); 86 static void def_image_name (const char *, int, int); 87 static void def_section (const char *, int); 88 static void def_section_alt (const char *, const char *); 89 static void def_stacksize (int, int); 90 static void def_version (int, int); 91 static void def_directive (char *); 92 static int def_parse (void); 93 static int def_error (const char *); 94 static int def_lex (void); 95 96 static int lex_forced_token = 0; 97 static const char *lex_parse_string = 0; 98 static const char *lex_parse_string_end = 0; 99 100 %} 101 102 %union { 103 char *id; 104 int number; 105 }; 106 107 %token NAME LIBRARY DESCRIPTION STACKSIZE HEAPSIZE CODE DATAU DATAL 108 %token SECTIONS EXPORTS IMPORTS VERSIONK BASE CONSTANTU CONSTANTL 109 %token PRIVATEU PRIVATEL 110 %token READ WRITE EXECUTE SHARED NONAMEU NONAMEL DIRECTIVE 111 %token <id> ID 112 %token <number> NUMBER 113 %type <number> opt_base opt_ordinal 114 %type <number> attr attr_list opt_number exp_opt_list exp_opt 115 %type <id> opt_name opt_equal_name dot_name 116 117 %% 118 119 start: start command 120 | command 121 ; 122 123 command: 124 NAME opt_name opt_base { def_image_name ($2, $3, 0); } 125 | LIBRARY opt_name opt_base { def_image_name ($2, $3, 1); } 126 | DESCRIPTION ID { def_description ($2);} 127 | STACKSIZE NUMBER opt_number { def_stacksize ($2, $3);} 128 | HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);} 129 | CODE attr_list { def_section ("CODE", $2);} 130 | DATAU attr_list { def_section ("DATA", $2);} 131 | SECTIONS seclist 132 | EXPORTS explist 133 | IMPORTS implist 134 | VERSIONK NUMBER { def_version ($2, 0);} 135 | VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);} 136 | DIRECTIVE ID { def_directive ($2);} 137 ; 138 139 140 explist: 141 /* EMPTY */ 142 | expline 143 | explist expline 144 ; 145 146 expline: 147 /* The opt_comma is necessary to support both the usual 148 DEF file syntax as well as .drectve syntax which 149 mandates <expsym>,<expoptlist>. */ 150 dot_name opt_equal_name opt_ordinal opt_comma exp_opt_list 151 { def_exports ($1, $2, $3, $5); } 152 ; 153 exp_opt_list: 154 /* The opt_comma is necessary to support both the usual 155 DEF file syntax as well as .drectve syntax which 156 allows for comma separated opt list. */ 157 exp_opt opt_comma exp_opt_list { $$ = $1 | $3; } 158 | { $$ = 0; } 159 ; 160 exp_opt: 161 NONAMEU { $$ = 1; } 162 | NONAMEL { $$ = 1; } 163 | CONSTANTU { $$ = 2; } 164 | CONSTANTL { $$ = 2; } 165 | DATAU { $$ = 4; } 166 | DATAL { $$ = 4; } 167 | PRIVATEU { $$ = 8; } 168 | PRIVATEL { $$ = 8; } 169 ; 170 implist: 171 implist impline 172 | impline 173 ; 174 175 impline: 176 ID '=' ID '.' ID '.' ID { def_import ($1, $3, $5, $7, -1); } 177 | ID '=' ID '.' ID '.' NUMBER { def_import ($1, $3, $5, 0, $7); } 178 | ID '=' ID '.' ID { def_import ($1, $3, 0, $5, -1); } 179 | ID '=' ID '.' NUMBER { def_import ($1, $3, 0, 0, $5); } 180 | ID '.' ID '.' ID { def_import ( 0, $1, $3, $5, -1); } 181 | ID '.' ID { def_import ( 0, $1, 0, $3, -1); } 182 ; 183 184 seclist: 185 seclist secline 186 | secline 187 ; 188 189 secline: 190 ID attr_list { def_section ($1, $2);} 191 | ID ID { def_section_alt ($1, $2);} 192 ; 193 194 attr_list: 195 attr_list opt_comma attr { $$ = $1 | $3; } 196 | attr { $$ = $1; } 197 ; 198 199 opt_comma: 200 ',' 201 | 202 ; 203 opt_number: ',' NUMBER { $$=$2;} 204 | { $$=-1;} 205 ; 206 207 attr: 208 READ { $$ = 1;} 209 | WRITE { $$ = 2;} 210 | EXECUTE { $$=4;} 211 | SHARED { $$=8;} 212 ; 213 214 opt_name: ID { $$ = $1; } 215 | ID '.' ID 216 { 217 char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1); 218 sprintf (name, "%s.%s", $1, $3); 219 $$ = name; 220 } 221 | { $$ = ""; } 222 ; 223 224 opt_ordinal: 225 '@' NUMBER { $$ = $2;} 226 | { $$ = -1;} 227 ; 228 229 opt_equal_name: 230 '=' dot_name { $$ = $2; } 231 | { $$ = 0; } 232 ; 233 234 opt_base: BASE '=' NUMBER { $$ = $3;} 235 | { $$ = -1;} 236 ; 237 238 dot_name: ID { $$ = $1; } 239 | dot_name '.' ID 240 { 241 char *name = xmalloc (strlen ($1) + 1 + strlen ($3) + 1); 242 sprintf (name, "%s.%s", $1, $3); 243 $$ = name; 244 } 245 ; 246 247 248 %% 249 250 /***************************************************************************** 251 API 252 *****************************************************************************/ 253 254 static FILE *the_file; 255 static const char *def_filename; 256 static int linenumber; 257 static def_file *def; 258 static int saw_newline; 259 260 struct directive 261 { 262 struct directive *next; 263 char *name; 264 int len; 265 }; 266 267 static struct directive *directives = 0; 268 269 def_file * 270 def_file_empty (void) 271 { 272 def_file *rv = xmalloc (sizeof (def_file)); 273 memset (rv, 0, sizeof (def_file)); 274 rv->is_dll = -1; 275 rv->base_address = (bfd_vma) -1; 276 rv->stack_reserve = rv->stack_commit = -1; 277 rv->heap_reserve = rv->heap_commit = -1; 278 rv->version_major = rv->version_minor = -1; 279 return rv; 280 } 281 282 def_file * 283 def_file_parse (const char *filename, def_file *add_to) 284 { 285 struct directive *d; 286 287 the_file = fopen (filename, "r"); 288 def_filename = filename; 289 linenumber = 1; 290 if (!the_file) 291 { 292 perror (filename); 293 return 0; 294 } 295 if (add_to) 296 { 297 def = add_to; 298 } 299 else 300 { 301 def = def_file_empty (); 302 } 303 304 saw_newline = 1; 305 if (def_parse ()) 306 { 307 def_file_free (def); 308 fclose (the_file); 309 return 0; 310 } 311 312 fclose (the_file); 313 314 for (d = directives; d; d = d->next) 315 { 316 #if TRACE 317 printf ("Adding directive %08x `%s'\n", d->name, d->name); 318 #endif 319 def_file_add_directive (def, d->name, d->len); 320 } 321 322 return def; 323 } 324 325 void 326 def_file_free (def_file *def) 327 { 328 int i; 329 330 if (!def) 331 return; 332 if (def->name) 333 free (def->name); 334 if (def->description) 335 free (def->description); 336 337 if (def->section_defs) 338 { 339 for (i = 0; i < def->num_section_defs; i++) 340 { 341 if (def->section_defs[i].name) 342 free (def->section_defs[i].name); 343 if (def->section_defs[i].class) 344 free (def->section_defs[i].class); 345 } 346 free (def->section_defs); 347 } 348 349 if (def->exports) 350 { 351 for (i = 0; i < def->num_exports; i++) 352 { 353 if (def->exports[i].internal_name 354 && def->exports[i].internal_name != def->exports[i].name) 355 free (def->exports[i].internal_name); 356 if (def->exports[i].name) 357 free (def->exports[i].name); 358 } 359 free (def->exports); 360 } 361 362 if (def->imports) 363 { 364 for (i = 0; i < def->num_imports; i++) 365 { 366 if (def->imports[i].internal_name 367 && def->imports[i].internal_name != def->imports[i].name) 368 free (def->imports[i].internal_name); 369 if (def->imports[i].name) 370 free (def->imports[i].name); 371 } 372 free (def->imports); 373 } 374 375 while (def->modules) 376 { 377 def_file_module *m = def->modules; 378 def->modules = def->modules->next; 379 free (m); 380 } 381 382 free (def); 383 } 384 385 #ifdef DEF_FILE_PRINT 386 void 387 def_file_print (FILE *file, def_file *def) 388 { 389 int i; 390 391 fprintf (file, ">>>> def_file at 0x%08x\n", def); 392 if (def->name) 393 fprintf (file, " name: %s\n", def->name ? def->name : "(unspecified)"); 394 if (def->is_dll != -1) 395 fprintf (file, " is dll: %s\n", def->is_dll ? "yes" : "no"); 396 if (def->base_address != (bfd_vma) -1) 397 fprintf (file, " base address: 0x%08x\n", def->base_address); 398 if (def->description) 399 fprintf (file, " description: `%s'\n", def->description); 400 if (def->stack_reserve != -1) 401 fprintf (file, " stack reserve: 0x%08x\n", def->stack_reserve); 402 if (def->stack_commit != -1) 403 fprintf (file, " stack commit: 0x%08x\n", def->stack_commit); 404 if (def->heap_reserve != -1) 405 fprintf (file, " heap reserve: 0x%08x\n", def->heap_reserve); 406 if (def->heap_commit != -1) 407 fprintf (file, " heap commit: 0x%08x\n", def->heap_commit); 408 409 if (def->num_section_defs > 0) 410 { 411 fprintf (file, " section defs:\n"); 412 413 for (i = 0; i < def->num_section_defs; i++) 414 { 415 fprintf (file, " name: `%s', class: `%s', flags:", 416 def->section_defs[i].name, def->section_defs[i].class); 417 if (def->section_defs[i].flag_read) 418 fprintf (file, " R"); 419 if (def->section_defs[i].flag_write) 420 fprintf (file, " W"); 421 if (def->section_defs[i].flag_execute) 422 fprintf (file, " X"); 423 if (def->section_defs[i].flag_shared) 424 fprintf (file, " S"); 425 fprintf (file, "\n"); 426 } 427 } 428 429 if (def->num_exports > 0) 430 { 431 fprintf (file, " exports:\n"); 432 433 for (i = 0; i < def->num_exports; i++) 434 { 435 fprintf (file, " name: `%s', int: `%s', ordinal: %d, flags:", 436 def->exports[i].name, def->exports[i].internal_name, 437 def->exports[i].ordinal); 438 if (def->exports[i].flag_private) 439 fprintf (file, " P"); 440 if (def->exports[i].flag_constant) 441 fprintf (file, " C"); 442 if (def->exports[i].flag_noname) 443 fprintf (file, " N"); 444 if (def->exports[i].flag_data) 445 fprintf (file, " D"); 446 fprintf (file, "\n"); 447 } 448 } 449 450 if (def->num_imports > 0) 451 { 452 fprintf (file, " imports:\n"); 453 454 for (i = 0; i < def->num_imports; i++) 455 { 456 fprintf (file, " int: %s, from: `%s', name: `%s', ordinal: %d\n", 457 def->imports[i].internal_name, 458 def->imports[i].module, 459 def->imports[i].name, 460 def->imports[i].ordinal); 461 } 462 } 463 464 if (def->version_major != -1) 465 fprintf (file, " version: %d.%d\n", def->version_major, def->version_minor); 466 467 fprintf (file, "<<<< def_file at 0x%08x\n", def); 468 } 469 #endif 470 471 def_file_export * 472 def_file_add_export (def_file *def, 473 const char *external_name, 474 const char *internal_name, 475 int ordinal) 476 { 477 def_file_export *e; 478 int max_exports = ROUND_UP(def->num_exports, 32); 479 480 if (def->num_exports >= max_exports) 481 { 482 max_exports = ROUND_UP(def->num_exports + 1, 32); 483 if (def->exports) 484 def->exports = xrealloc (def->exports, 485 max_exports * sizeof (def_file_export)); 486 else 487 def->exports = xmalloc (max_exports * sizeof (def_file_export)); 488 } 489 e = def->exports + def->num_exports; 490 memset (e, 0, sizeof (def_file_export)); 491 if (internal_name && !external_name) 492 external_name = internal_name; 493 if (external_name && !internal_name) 494 internal_name = external_name; 495 e->name = xstrdup (external_name); 496 e->internal_name = xstrdup (internal_name); 497 e->ordinal = ordinal; 498 def->num_exports++; 499 return e; 500 } 501 502 def_file_module * 503 def_get_module (def_file *def, const char *name) 504 { 505 def_file_module *s; 506 507 for (s = def->modules; s; s = s->next) 508 if (strcmp (s->name, name) == 0) 509 return s; 510 511 return NULL; 512 } 513 514 static def_file_module * 515 def_stash_module (def_file *def, const char *name) 516 { 517 def_file_module *s; 518 519 if ((s = def_get_module (def, name)) != NULL) 520 return s; 521 s = xmalloc (sizeof (def_file_module) + strlen (name)); 522 s->next = def->modules; 523 def->modules = s; 524 s->user_data = 0; 525 strcpy (s->name, name); 526 return s; 527 } 528 529 def_file_import * 530 def_file_add_import (def_file *def, 531 const char *name, 532 const char *module, 533 int ordinal, 534 const char *internal_name) 535 { 536 def_file_import *i; 537 int max_imports = ROUND_UP (def->num_imports, 16); 538 539 if (def->num_imports >= max_imports) 540 { 541 max_imports = ROUND_UP (def->num_imports+1, 16); 542 543 if (def->imports) 544 def->imports = xrealloc (def->imports, 545 max_imports * sizeof (def_file_import)); 546 else 547 def->imports = xmalloc (max_imports * sizeof (def_file_import)); 548 } 549 i = def->imports + def->num_imports; 550 memset (i, 0, sizeof (def_file_import)); 551 if (name) 552 i->name = xstrdup (name); 553 if (module) 554 i->module = def_stash_module (def, module); 555 i->ordinal = ordinal; 556 if (internal_name) 557 i->internal_name = xstrdup (internal_name); 558 else 559 i->internal_name = i->name; 560 def->num_imports++; 561 562 return i; 563 } 564 565 struct 566 { 567 char *param; 568 int token; 569 } 570 diropts[] = 571 { 572 { "-heap", HEAPSIZE }, 573 { "-stack", STACKSIZE }, 574 { "-attr", SECTIONS }, 575 { "-export", EXPORTS }, 576 { 0, 0 } 577 }; 578 579 void 580 def_file_add_directive (def_file *my_def, const char *param, int len) 581 { 582 def_file *save_def = def; 583 const char *pend = param + len; 584 char * tend = (char *) param; 585 int i; 586 587 def = my_def; 588 589 while (param < pend) 590 { 591 while (param < pend 592 && (ISSPACE (*param) || *param == '\n' || *param == 0)) 593 param++; 594 595 if (param == pend) 596 break; 597 598 /* Scan forward until we encounter any of: 599 - the end of the buffer 600 - the start of a new option 601 - a newline seperating options 602 - a NUL seperating options. */ 603 for (tend = (char *) (param + 1); 604 (tend < pend 605 && !(ISSPACE (tend[-1]) && *tend == '-') 606 && *tend != '\n' && *tend != 0); 607 tend++) 608 ; 609 610 for (i = 0; diropts[i].param; i++) 611 { 612 int len = strlen (diropts[i].param); 613 614 if (tend - param >= len 615 && strncmp (param, diropts[i].param, len) == 0 616 && (param[len] == ':' || param[len] == ' ')) 617 { 618 lex_parse_string_end = tend; 619 lex_parse_string = param + len + 1; 620 lex_forced_token = diropts[i].token; 621 saw_newline = 0; 622 if (def_parse ()) 623 continue; 624 break; 625 } 626 } 627 628 if (!diropts[i].param) 629 { 630 char saved; 631 632 saved = * tend; 633 * tend = 0; 634 /* xgettext:c-format */ 635 einfo (_("Warning: .drectve `%s' unrecognized\n"), param); 636 * tend = saved; 637 } 638 639 lex_parse_string = 0; 640 param = tend; 641 } 642 643 def = save_def; 644 } 645 646 /* Parser Callbacks. */ 647 648 static void 649 def_image_name (const char *name, int base, int is_dll) 650 { 651 /* If a LIBRARY or NAME statement is specified without a name, there is nothing 652 to do here. We retain the output filename specified on command line. */ 653 if (*name) 654 { 655 const char* image_name = lbasename (name); 656 if (image_name != name) 657 einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n", 658 def_filename, linenumber, is_dll ? "LIBRARY" : "NAME", 659 name); 660 if (def->name) 661 free (def->name); 662 /* Append the default suffix, if none specified. */ 663 if (strchr (image_name, '.') == 0) 664 { 665 const char * suffix = is_dll ? ".dll" : ".exe"; 666 667 def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1); 668 sprintf (def->name, "%s%s", image_name, suffix); 669 } 670 else 671 def->name = xstrdup (image_name); 672 } 673 674 /* Honor a BASE address statement, even if LIBRARY string is empty. */ 675 def->base_address = base; 676 def->is_dll = is_dll; 677 } 678 679 static void 680 def_description (const char *text) 681 { 682 int len = def->description ? strlen (def->description) : 0; 683 684 len += strlen (text) + 1; 685 if (def->description) 686 { 687 def->description = xrealloc (def->description, len); 688 strcat (def->description, text); 689 } 690 else 691 { 692 def->description = xmalloc (len); 693 strcpy (def->description, text); 694 } 695 } 696 697 static void 698 def_stacksize (int reserve, int commit) 699 { 700 def->stack_reserve = reserve; 701 def->stack_commit = commit; 702 } 703 704 static void 705 def_heapsize (int reserve, int commit) 706 { 707 def->heap_reserve = reserve; 708 def->heap_commit = commit; 709 } 710 711 static void 712 def_section (const char *name, int attr) 713 { 714 def_file_section *s; 715 int max_sections = ROUND_UP (def->num_section_defs, 4); 716 717 if (def->num_section_defs >= max_sections) 718 { 719 max_sections = ROUND_UP (def->num_section_defs+1, 4); 720 721 if (def->section_defs) 722 def->section_defs = xrealloc (def->section_defs, 723 max_sections * sizeof (def_file_import)); 724 else 725 def->section_defs = xmalloc (max_sections * sizeof (def_file_import)); 726 } 727 s = def->section_defs + def->num_section_defs; 728 memset (s, 0, sizeof (def_file_section)); 729 s->name = xstrdup (name); 730 if (attr & 1) 731 s->flag_read = 1; 732 if (attr & 2) 733 s->flag_write = 1; 734 if (attr & 4) 735 s->flag_execute = 1; 736 if (attr & 8) 737 s->flag_shared = 1; 738 739 def->num_section_defs++; 740 } 741 742 static void 743 def_section_alt (const char *name, const char *attr) 744 { 745 int aval = 0; 746 747 for (; *attr; attr++) 748 { 749 switch (*attr) 750 { 751 case 'R': 752 case 'r': 753 aval |= 1; 754 break; 755 case 'W': 756 case 'w': 757 aval |= 2; 758 break; 759 case 'X': 760 case 'x': 761 aval |= 4; 762 break; 763 case 'S': 764 case 's': 765 aval |= 8; 766 break; 767 } 768 } 769 def_section (name, aval); 770 } 771 772 static void 773 def_exports (const char *external_name, 774 const char *internal_name, 775 int ordinal, 776 int flags) 777 { 778 def_file_export *dfe; 779 780 if (!internal_name && external_name) 781 internal_name = external_name; 782 #if TRACE 783 printf ("def_exports, ext=%s int=%s\n", external_name, internal_name); 784 #endif 785 786 dfe = def_file_add_export (def, external_name, internal_name, ordinal); 787 if (flags & 1) 788 dfe->flag_noname = 1; 789 if (flags & 2) 790 dfe->flag_constant = 1; 791 if (flags & 4) 792 dfe->flag_data = 1; 793 if (flags & 8) 794 dfe->flag_private = 1; 795 } 796 797 static void 798 def_import (const char *internal_name, 799 const char *module, 800 const char *dllext, 801 const char *name, 802 int ordinal) 803 { 804 char *buf = 0; 805 const char *ext = dllext ? dllext : "dll"; 806 807 buf = xmalloc (strlen (module) + strlen (ext) + 2); 808 sprintf (buf, "%s.%s", module, ext); 809 module = buf; 810 811 def_file_add_import (def, name, module, ordinal, internal_name); 812 if (buf) 813 free (buf); 814 } 815 816 static void 817 def_version (int major, int minor) 818 { 819 def->version_major = major; 820 def->version_minor = minor; 821 } 822 823 static void 824 def_directive (char *str) 825 { 826 struct directive *d = xmalloc (sizeof (struct directive)); 827 828 d->next = directives; 829 directives = d; 830 d->name = xstrdup (str); 831 d->len = strlen (str); 832 } 833 834 static int 835 def_error (const char *err) 836 { 837 einfo ("%P: %s:%d: %s\n", 838 def_filename ? def_filename : "<unknown-file>", linenumber, err); 839 return 0; 840 } 841 842 843 /* Lexical Scanner. */ 844 845 #undef TRACE 846 #define TRACE 0 847 848 /* Never freed, but always reused as needed, so no real leak. */ 849 static char *buffer = 0; 850 static int buflen = 0; 851 static int bufptr = 0; 852 853 static void 854 put_buf (char c) 855 { 856 if (bufptr == buflen) 857 { 858 buflen += 50; /* overly reasonable, eh? */ 859 if (buffer) 860 buffer = xrealloc (buffer, buflen + 1); 861 else 862 buffer = xmalloc (buflen + 1); 863 } 864 buffer[bufptr++] = c; 865 buffer[bufptr] = 0; /* not optimal, but very convenient. */ 866 } 867 868 static struct 869 { 870 char *name; 871 int token; 872 } 873 tokens[] = 874 { 875 { "BASE", BASE }, 876 { "CODE", CODE }, 877 { "CONSTANT", CONSTANTU }, 878 { "constant", CONSTANTL }, 879 { "DATA", DATAU }, 880 { "data", DATAL }, 881 { "DESCRIPTION", DESCRIPTION }, 882 { "DIRECTIVE", DIRECTIVE }, 883 { "EXECUTE", EXECUTE }, 884 { "EXPORTS", EXPORTS }, 885 { "HEAPSIZE", HEAPSIZE }, 886 { "IMPORTS", IMPORTS }, 887 { "LIBRARY", LIBRARY }, 888 { "NAME", NAME }, 889 { "NONAME", NONAMEU }, 890 { "noname", NONAMEL }, 891 { "PRIVATE", PRIVATEU }, 892 { "private", PRIVATEL }, 893 { "READ", READ }, 894 { "SECTIONS", SECTIONS }, 895 { "SEGMENTS", SECTIONS }, 896 { "SHARED", SHARED }, 897 { "STACKSIZE", STACKSIZE }, 898 { "VERSION", VERSIONK }, 899 { "WRITE", WRITE }, 900 { 0, 0 } 901 }; 902 903 static int 904 def_getc (void) 905 { 906 int rv; 907 908 if (lex_parse_string) 909 { 910 if (lex_parse_string >= lex_parse_string_end) 911 rv = EOF; 912 else 913 rv = *lex_parse_string++; 914 } 915 else 916 { 917 rv = fgetc (the_file); 918 } 919 if (rv == '\n') 920 saw_newline = 1; 921 return rv; 922 } 923 924 static int 925 def_ungetc (int c) 926 { 927 if (lex_parse_string) 928 { 929 lex_parse_string--; 930 return c; 931 } 932 else 933 return ungetc (c, the_file); 934 } 935 936 static int 937 def_lex (void) 938 { 939 int c, i, q; 940 941 if (lex_forced_token) 942 { 943 i = lex_forced_token; 944 lex_forced_token = 0; 945 #if TRACE 946 printf ("lex: forcing token %d\n", i); 947 #endif 948 return i; 949 } 950 951 c = def_getc (); 952 953 /* Trim leading whitespace. */ 954 while (c != EOF && (c == ' ' || c == '\t') && saw_newline) 955 c = def_getc (); 956 957 if (c == EOF) 958 { 959 #if TRACE 960 printf ("lex: EOF\n"); 961 #endif 962 return 0; 963 } 964 965 if (saw_newline && c == ';') 966 { 967 do 968 { 969 c = def_getc (); 970 } 971 while (c != EOF && c != '\n'); 972 if (c == '\n') 973 return def_lex (); 974 return 0; 975 } 976 977 /* Must be something else. */ 978 saw_newline = 0; 979 980 if (ISDIGIT (c)) 981 { 982 bufptr = 0; 983 while (c != EOF && (ISXDIGIT (c) || (c == 'x'))) 984 { 985 put_buf (c); 986 c = def_getc (); 987 } 988 if (c != EOF) 989 def_ungetc (c); 990 yylval.number = strtoul (buffer, 0, 0); 991 #if TRACE 992 printf ("lex: `%s' returns NUMBER %d\n", buffer, yylval.number); 993 #endif 994 return NUMBER; 995 } 996 997 if (ISALPHA (c) || strchr ("$:-_?@", c)) 998 { 999 bufptr = 0; 1000 q = c; 1001 put_buf (c); 1002 c = def_getc (); 1003 1004 if (q == '@') 1005 { 1006 if (ISBLANK (c) ) /* '@' followed by whitespace. */ 1007 return (q); 1008 else if (ISDIGIT (c)) /* '@' followed by digit. */ 1009 { 1010 def_ungetc (c); 1011 return (q); 1012 } 1013 #if TRACE 1014 printf ("lex: @ returns itself\n"); 1015 #endif 1016 } 1017 1018 while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@", c))) 1019 { 1020 put_buf (c); 1021 c = def_getc (); 1022 } 1023 if (c != EOF) 1024 def_ungetc (c); 1025 if (ISALPHA (q)) /* Check for tokens. */ 1026 { 1027 for (i = 0; tokens[i].name; i++) 1028 if (strcmp (tokens[i].name, buffer) == 0) 1029 { 1030 #if TRACE 1031 printf ("lex: `%s' is a string token\n", buffer); 1032 #endif 1033 return tokens[i].token; 1034 } 1035 } 1036 #if TRACE 1037 printf ("lex: `%s' returns ID\n", buffer); 1038 #endif 1039 yylval.id = xstrdup (buffer); 1040 return ID; 1041 } 1042 1043 if (c == '\'' || c == '"') 1044 { 1045 q = c; 1046 c = def_getc (); 1047 bufptr = 0; 1048 1049 while (c != EOF && c != q) 1050 { 1051 put_buf (c); 1052 c = def_getc (); 1053 } 1054 yylval.id = xstrdup (buffer); 1055 #if TRACE 1056 printf ("lex: `%s' returns ID\n", buffer); 1057 #endif 1058 return ID; 1059 } 1060 1061 if (c == '=' || c == '.' || c == ',') 1062 { 1063 #if TRACE 1064 printf ("lex: `%c' returns itself\n", c); 1065 #endif 1066 return c; 1067 } 1068 1069 if (c == '\n') 1070 { 1071 linenumber++; 1072 saw_newline = 1; 1073 } 1074 1075 /*printf ("lex: 0x%02x ignored\n", c); */ 1076 return def_lex (); 1077 } 1078