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