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