1 %{ /* deffilep.y - parser for .def files */ 2 3 /* Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 4 2007, 2009 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 3 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, 21 MA 02110-1301, USA. */ 22 23 #include "sysdep.h" 24 #include "libiberty.h" 25 #include "safe-ctype.h" 26 #include "bfd.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 typedef struct def_pool_str { 82 struct def_pool_str *next; 83 char data[1]; 84 } def_pool_str; 85 86 static def_pool_str *pool_strs = NULL; 87 88 static char *def_pool_alloc (size_t sz); 89 static char *def_pool_strdup (const char *str); 90 static void def_pool_free (void); 91 92 static void def_description (const char *); 93 static void def_exports (const char *, const char *, int, int, const char *); 94 static void def_heapsize (int, int); 95 static void def_import (const char *, const char *, const char *, const char *, 96 int, const char *); 97 static void def_image_name (const char *, int, int); 98 static void def_section (const char *, int); 99 static void def_section_alt (const char *, const char *); 100 static void def_stacksize (int, int); 101 static void def_version (int, int); 102 static void def_directive (char *); 103 static void def_aligncomm (char *str, int align); 104 static int def_parse (void); 105 static int def_error (const char *); 106 static int def_lex (void); 107 108 static int lex_forced_token = 0; 109 static const char *lex_parse_string = 0; 110 static const char *lex_parse_string_end = 0; 111 112 %} 113 114 %union { 115 char *id; 116 const char *id_const; 117 int number; 118 char *digits; 119 }; 120 121 %token NAME LIBRARY DESCRIPTION STACKSIZE_K HEAPSIZE CODE DATAU DATAL 122 %token SECTIONS EXPORTS IMPORTS VERSIONK BASE CONSTANTU CONSTANTL 123 %token PRIVATEU PRIVATEL ALIGNCOMM 124 %token READ WRITE EXECUTE SHARED NONAMEU NONAMEL DIRECTIVE EQUAL 125 %token <id> ID 126 %token <digits> DIGITS 127 %type <number> NUMBER 128 %type <digits> opt_digits 129 %type <number> opt_base opt_ordinal 130 %type <number> attr attr_list opt_number exp_opt_list exp_opt 131 %type <id> opt_name opt_name2 opt_equal_name anylang_id opt_id 132 %type <id> opt_equalequal_name 133 %type <id_const> keyword_as_name 134 135 %% 136 137 start: start command 138 | command 139 ; 140 141 command: 142 NAME opt_name opt_base { def_image_name ($2, $3, 0); } 143 | LIBRARY opt_name opt_base { def_image_name ($2, $3, 1); } 144 | DESCRIPTION ID { def_description ($2);} 145 | STACKSIZE_K NUMBER opt_number { def_stacksize ($2, $3);} 146 | HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);} 147 | CODE attr_list { def_section ("CODE", $2);} 148 | DATAU attr_list { def_section ("DATA", $2);} 149 | SECTIONS seclist 150 | EXPORTS explist 151 | IMPORTS implist 152 | VERSIONK NUMBER { def_version ($2, 0);} 153 | VERSIONK NUMBER '.' NUMBER { def_version ($2, $4);} 154 | DIRECTIVE ID { def_directive ($2);} 155 | ALIGNCOMM anylang_id ',' NUMBER { def_aligncomm ($2, $4);} 156 ; 157 158 159 explist: 160 /* EMPTY */ 161 | expline 162 | explist expline 163 ; 164 165 expline: 166 /* The opt_comma is necessary to support both the usual 167 DEF file syntax as well as .drectve syntax which 168 mandates <expsym>,<expoptlist>. */ 169 opt_name2 opt_equal_name opt_ordinal opt_comma exp_opt_list opt_comma opt_equalequal_name 170 { def_exports ($1, $2, $3, $5, $7); } 171 ; 172 exp_opt_list: 173 /* The opt_comma is necessary to support both the usual 174 DEF file syntax as well as .drectve syntax which 175 allows for comma separated opt list. */ 176 exp_opt opt_comma exp_opt_list { $$ = $1 | $3; } 177 | { $$ = 0; } 178 ; 179 exp_opt: 180 NONAMEU { $$ = 1; } 181 | NONAMEL { $$ = 1; } 182 | CONSTANTU { $$ = 2; } 183 | CONSTANTL { $$ = 2; } 184 | DATAU { $$ = 4; } 185 | DATAL { $$ = 4; } 186 | PRIVATEU { $$ = 8; } 187 | PRIVATEL { $$ = 8; } 188 ; 189 implist: 190 implist impline 191 | impline 192 ; 193 194 impline: 195 ID '=' ID '.' ID '.' ID opt_equalequal_name 196 { def_import ($1, $3, $5, $7, -1, $8); } 197 | ID '=' ID '.' ID '.' NUMBER opt_equalequal_name 198 { def_import ($1, $3, $5, 0, $7, $8); } 199 | ID '=' ID '.' ID opt_equalequal_name 200 { def_import ($1, $3, 0, $5, -1, $6); } 201 | ID '=' ID '.' NUMBER opt_equalequal_name 202 { def_import ($1, $3, 0, 0, $5, $6); } 203 | ID '.' ID '.' ID opt_equalequal_name 204 { def_import( 0, $1, $3, $5, -1, $6); } 205 | ID '.' ID opt_equalequal_name 206 { def_import ( 0, $1, 0, $3, -1, $4); } 207 ; 208 209 seclist: 210 seclist secline 211 | secline 212 ; 213 214 secline: 215 ID attr_list { def_section ($1, $2);} 216 | ID ID { def_section_alt ($1, $2);} 217 ; 218 219 attr_list: 220 attr_list opt_comma attr { $$ = $1 | $3; } 221 | attr { $$ = $1; } 222 ; 223 224 opt_comma: 225 ',' 226 | 227 ; 228 opt_number: ',' NUMBER { $$=$2;} 229 | { $$=-1;} 230 ; 231 232 attr: 233 READ { $$ = 1;} 234 | WRITE { $$ = 2;} 235 | EXECUTE { $$=4;} 236 | SHARED { $$=8;} 237 ; 238 239 240 keyword_as_name: BASE { $$ = "BASE"; } 241 | CODE { $$ = "CODE"; } 242 | CONSTANTU { $$ = "CONSTANT"; } 243 | CONSTANTL { $$ = "constant"; } 244 | DATAU { $$ = "DATA"; } 245 | DATAL { $$ = "data"; } 246 | DESCRIPTION { $$ = "DESCRIPTION"; } 247 | DIRECTIVE { $$ = "DIRECTIVE"; } 248 | EXECUTE { $$ = "EXECUTE"; } 249 | EXPORTS { $$ = "EXPORTS"; } 250 | HEAPSIZE { $$ = "HEAPSIZE"; } 251 | IMPORTS { $$ = "IMPORTS"; } 252 /* Disable LIBRARY keyword as valid symbol-name. This is necessary 253 for libtool, which places this command after EXPORTS command. 254 This behavior is illegal by specification, but sadly required by 255 by compatibility reasons. 256 See PR binutils/13710 257 | LIBRARY { $$ = "LIBRARY"; } */ 258 | NAME { $$ = "NAME"; } 259 | NONAMEU { $$ = "NONAME"; } 260 | NONAMEL { $$ = "noname"; } 261 | PRIVATEU { $$ = "PRIVATE"; } 262 | PRIVATEL { $$ = "private"; } 263 | READ { $$ = "READ"; } 264 | SHARED { $$ = "SHARED"; } 265 | STACKSIZE_K { $$ = "STACKSIZE"; } 266 | VERSIONK { $$ = "VERSION"; } 267 | WRITE { $$ = "WRITE"; } 268 ; 269 270 opt_name2: ID { $$ = $1; } 271 | '.' keyword_as_name 272 { 273 char *name = xmalloc (strlen ($2) + 2); 274 sprintf (name, ".%s", $2); 275 $$ = name; 276 } 277 | '.' opt_name2 278 { 279 char *name = def_pool_alloc (strlen ($2) + 2); 280 sprintf (name, ".%s", $2); 281 $$ = name; 282 } 283 | keyword_as_name '.' opt_name2 284 { 285 char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1); 286 sprintf (name, "%s.%s", $1, $3); 287 $$ = name; 288 } 289 | ID '.' opt_name2 290 { 291 char *name = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + 1); 292 sprintf (name, "%s.%s", $1, $3); 293 $$ = name; 294 } 295 ; 296 297 opt_name: opt_name2 { $$ = $1; } 298 | { $$ = ""; } 299 ; 300 301 opt_equalequal_name: EQUAL ID { $$ = $2; } 302 | { $$ = 0; } 303 ; 304 305 opt_ordinal: 306 '@' NUMBER { $$ = $2;} 307 | { $$ = -1;} 308 ; 309 310 opt_equal_name: 311 '=' opt_name2 { $$ = $2; } 312 | { $$ = 0; } 313 ; 314 315 opt_base: BASE '=' NUMBER { $$ = $3;} 316 | { $$ = -1;} 317 ; 318 319 anylang_id: ID { $$ = $1; } 320 | '.' ID 321 { 322 char *id = def_pool_alloc (strlen ($2) + 2); 323 sprintf (id, ".%s", $2); 324 $$ = id; 325 } 326 | anylang_id '.' opt_digits opt_id 327 { 328 char *id = def_pool_alloc (strlen ($1) + 1 + strlen ($3) + strlen ($4) + 1); 329 sprintf (id, "%s.%s%s", $1, $3, $4); 330 $$ = id; 331 } 332 ; 333 334 opt_digits: DIGITS { $$ = $1; } 335 | { $$ = ""; } 336 ; 337 338 opt_id: ID { $$ = $1; } 339 | { $$ = ""; } 340 ; 341 342 NUMBER: DIGITS { $$ = strtoul ($1, 0, 0); } 343 344 %% 345 346 /***************************************************************************** 347 API 348 *****************************************************************************/ 349 350 static FILE *the_file; 351 static const char *def_filename; 352 static int linenumber; 353 static def_file *def; 354 static int saw_newline; 355 356 struct directive 357 { 358 struct directive *next; 359 char *name; 360 int len; 361 }; 362 363 static struct directive *directives = 0; 364 365 def_file * 366 def_file_empty (void) 367 { 368 def_file *rv = xmalloc (sizeof (def_file)); 369 memset (rv, 0, sizeof (def_file)); 370 rv->is_dll = -1; 371 rv->base_address = (bfd_vma) -1; 372 rv->stack_reserve = rv->stack_commit = -1; 373 rv->heap_reserve = rv->heap_commit = -1; 374 rv->version_major = rv->version_minor = -1; 375 return rv; 376 } 377 378 def_file * 379 def_file_parse (const char *filename, def_file *add_to) 380 { 381 struct directive *d; 382 383 the_file = fopen (filename, "r"); 384 def_filename = filename; 385 linenumber = 1; 386 if (!the_file) 387 { 388 perror (filename); 389 return 0; 390 } 391 if (add_to) 392 { 393 def = add_to; 394 } 395 else 396 { 397 def = def_file_empty (); 398 } 399 400 saw_newline = 1; 401 if (def_parse ()) 402 { 403 def_file_free (def); 404 fclose (the_file); 405 def_pool_free (); 406 return 0; 407 } 408 409 fclose (the_file); 410 411 while ((d = directives) != NULL) 412 { 413 #if TRACE 414 printf ("Adding directive %08x `%s'\n", d->name, d->name); 415 #endif 416 def_file_add_directive (def, d->name, d->len); 417 directives = d->next; 418 free (d->name); 419 free (d); 420 } 421 def_pool_free (); 422 423 return def; 424 } 425 426 void 427 def_file_free (def_file *fdef) 428 { 429 int i; 430 431 if (!fdef) 432 return; 433 if (fdef->name) 434 free (fdef->name); 435 if (fdef->description) 436 free (fdef->description); 437 438 if (fdef->section_defs) 439 { 440 for (i = 0; i < fdef->num_section_defs; i++) 441 { 442 if (fdef->section_defs[i].name) 443 free (fdef->section_defs[i].name); 444 if (fdef->section_defs[i].class) 445 free (fdef->section_defs[i].class); 446 } 447 free (fdef->section_defs); 448 } 449 450 if (fdef->exports) 451 { 452 for (i = 0; i < fdef->num_exports; i++) 453 { 454 if (fdef->exports[i].internal_name 455 && fdef->exports[i].internal_name != fdef->exports[i].name) 456 free (fdef->exports[i].internal_name); 457 if (fdef->exports[i].name) 458 free (fdef->exports[i].name); 459 if (fdef->exports[i].its_name) 460 free (fdef->exports[i].its_name); 461 } 462 free (fdef->exports); 463 } 464 465 if (fdef->imports) 466 { 467 for (i = 0; i < fdef->num_imports; i++) 468 { 469 if (fdef->imports[i].internal_name 470 && fdef->imports[i].internal_name != fdef->imports[i].name) 471 free (fdef->imports[i].internal_name); 472 if (fdef->imports[i].name) 473 free (fdef->imports[i].name); 474 if (fdef->imports[i].its_name) 475 free (fdef->imports[i].its_name); 476 } 477 free (fdef->imports); 478 } 479 480 while (fdef->modules) 481 { 482 def_file_module *m = fdef->modules; 483 484 fdef->modules = fdef->modules->next; 485 free (m); 486 } 487 488 while (fdef->aligncomms) 489 { 490 def_file_aligncomm *c = fdef->aligncomms; 491 492 fdef->aligncomms = fdef->aligncomms->next; 493 free (c->symbol_name); 494 free (c); 495 } 496 497 free (fdef); 498 } 499 500 #ifdef DEF_FILE_PRINT 501 void 502 def_file_print (FILE *file, def_file *fdef) 503 { 504 int i; 505 506 fprintf (file, ">>>> def_file at 0x%08x\n", fdef); 507 if (fdef->name) 508 fprintf (file, " name: %s\n", fdef->name ? fdef->name : "(unspecified)"); 509 if (fdef->is_dll != -1) 510 fprintf (file, " is dll: %s\n", fdef->is_dll ? "yes" : "no"); 511 if (fdef->base_address != (bfd_vma) -1) 512 fprintf (file, " base address: 0x%08x\n", fdef->base_address); 513 if (fdef->description) 514 fprintf (file, " description: `%s'\n", fdef->description); 515 if (fdef->stack_reserve != -1) 516 fprintf (file, " stack reserve: 0x%08x\n", fdef->stack_reserve); 517 if (fdef->stack_commit != -1) 518 fprintf (file, " stack commit: 0x%08x\n", fdef->stack_commit); 519 if (fdef->heap_reserve != -1) 520 fprintf (file, " heap reserve: 0x%08x\n", fdef->heap_reserve); 521 if (fdef->heap_commit != -1) 522 fprintf (file, " heap commit: 0x%08x\n", fdef->heap_commit); 523 524 if (fdef->num_section_defs > 0) 525 { 526 fprintf (file, " section defs:\n"); 527 528 for (i = 0; i < fdef->num_section_defs; i++) 529 { 530 fprintf (file, " name: `%s', class: `%s', flags:", 531 fdef->section_defs[i].name, fdef->section_defs[i].class); 532 if (fdef->section_defs[i].flag_read) 533 fprintf (file, " R"); 534 if (fdef->section_defs[i].flag_write) 535 fprintf (file, " W"); 536 if (fdef->section_defs[i].flag_execute) 537 fprintf (file, " X"); 538 if (fdef->section_defs[i].flag_shared) 539 fprintf (file, " S"); 540 fprintf (file, "\n"); 541 } 542 } 543 544 if (fdef->num_exports > 0) 545 { 546 fprintf (file, " exports:\n"); 547 548 for (i = 0; i < fdef->num_exports; i++) 549 { 550 fprintf (file, " name: `%s', int: `%s', ordinal: %d, flags:", 551 fdef->exports[i].name, fdef->exports[i].internal_name, 552 fdef->exports[i].ordinal); 553 if (fdef->exports[i].flag_private) 554 fprintf (file, " P"); 555 if (fdef->exports[i].flag_constant) 556 fprintf (file, " C"); 557 if (fdef->exports[i].flag_noname) 558 fprintf (file, " N"); 559 if (fdef->exports[i].flag_data) 560 fprintf (file, " D"); 561 fprintf (file, "\n"); 562 } 563 } 564 565 if (fdef->num_imports > 0) 566 { 567 fprintf (file, " imports:\n"); 568 569 for (i = 0; i < fdef->num_imports; i++) 570 { 571 fprintf (file, " int: %s, from: `%s', name: `%s', ordinal: %d\n", 572 fdef->imports[i].internal_name, 573 fdef->imports[i].module, 574 fdef->imports[i].name, 575 fdef->imports[i].ordinal); 576 } 577 } 578 579 if (fdef->version_major != -1) 580 fprintf (file, " version: %d.%d\n", fdef->version_major, fdef->version_minor); 581 582 fprintf (file, "<<<< def_file at 0x%08x\n", fdef); 583 } 584 #endif 585 586 /* Helper routine to check for identity of string pointers, 587 which might be NULL. */ 588 589 static int 590 are_names_equal (const char *s1, const char *s2) 591 { 592 if (!s1 && !s2) 593 return 0; 594 if (!s1 || !s2) 595 return (!s1 ? -1 : 1); 596 return strcmp (s1, s2); 597 } 598 599 static int 600 cmp_export_elem (const def_file_export *e, const char *ex_name, 601 const char *in_name, const char *its_name, 602 int ord) 603 { 604 int r; 605 606 if ((r = are_names_equal (ex_name, e->name)) != 0) 607 return r; 608 if ((r = are_names_equal (in_name, e->internal_name)) != 0) 609 return r; 610 if ((r = are_names_equal (its_name, e->its_name)) != 0) 611 return r; 612 return (ord - e->ordinal); 613 } 614 615 /* Search the position of the identical element, or returns the position 616 of the next higher element. If last valid element is smaller, then MAX 617 is returned. */ 618 619 static int 620 find_export_in_list (def_file_export *b, int max, 621 const char *ex_name, const char *in_name, 622 const char *its_name, int ord, int *is_ident) 623 { 624 int e, l, r, p; 625 626 *is_ident = 0; 627 if (!max) 628 return 0; 629 if ((e = cmp_export_elem (b, ex_name, in_name, its_name, ord)) <= 0) 630 { 631 if (!e) 632 *is_ident = 1; 633 return 0; 634 } 635 if (max == 1) 636 return 1; 637 if ((e = cmp_export_elem (b + (max - 1), ex_name, in_name, its_name, ord)) > 0) 638 return max; 639 else if (!e || max == 2) 640 { 641 if (!e) 642 *is_ident = 1; 643 return max - 1; 644 } 645 l = 0; r = max - 1; 646 while (l < r) 647 { 648 p = (l + r) / 2; 649 e = cmp_export_elem (b + p, ex_name, in_name, its_name, ord); 650 if (!e) 651 { 652 *is_ident = 1; 653 return p; 654 } 655 else if (e < 0) 656 r = p - 1; 657 else if (e > 0) 658 l = p + 1; 659 } 660 if ((e = cmp_export_elem (b + l, ex_name, in_name, its_name, ord)) > 0) 661 ++l; 662 else if (!e) 663 *is_ident = 1; 664 return l; 665 } 666 667 def_file_export * 668 def_file_add_export (def_file *fdef, 669 const char *external_name, 670 const char *internal_name, 671 int ordinal, 672 const char *its_name, 673 int *is_dup) 674 { 675 def_file_export *e; 676 int pos; 677 int max_exports = ROUND_UP(fdef->num_exports, 32); 678 679 if (internal_name && !external_name) 680 external_name = internal_name; 681 if (external_name && !internal_name) 682 internal_name = external_name; 683 684 /* We need to avoid duplicates. */ 685 *is_dup = 0; 686 pos = find_export_in_list (fdef->exports, fdef->num_exports, 687 external_name, internal_name, 688 its_name, ordinal, is_dup); 689 690 if (*is_dup != 0) 691 return (fdef->exports + pos); 692 693 if (fdef->num_exports >= max_exports) 694 { 695 max_exports = ROUND_UP(fdef->num_exports + 1, 32); 696 if (fdef->exports) 697 fdef->exports = xrealloc (fdef->exports, 698 max_exports * sizeof (def_file_export)); 699 else 700 fdef->exports = xmalloc (max_exports * sizeof (def_file_export)); 701 } 702 703 e = fdef->exports + pos; 704 if (pos != fdef->num_exports) 705 memmove (&e[1], e, (sizeof (def_file_export) * (fdef->num_exports - pos))); 706 memset (e, 0, sizeof (def_file_export)); 707 e->name = xstrdup (external_name); 708 e->internal_name = xstrdup (internal_name); 709 e->its_name = (its_name ? xstrdup (its_name) : NULL); 710 e->ordinal = ordinal; 711 fdef->num_exports++; 712 return e; 713 } 714 715 def_file_module * 716 def_get_module (def_file *fdef, const char *name) 717 { 718 def_file_module *s; 719 720 for (s = fdef->modules; s; s = s->next) 721 if (strcmp (s->name, name) == 0) 722 return s; 723 724 return NULL; 725 } 726 727 static def_file_module * 728 def_stash_module (def_file *fdef, const char *name) 729 { 730 def_file_module *s; 731 732 if ((s = def_get_module (fdef, name)) != NULL) 733 return s; 734 s = xmalloc (sizeof (def_file_module) + strlen (name)); 735 s->next = fdef->modules; 736 fdef->modules = s; 737 s->user_data = 0; 738 strcpy (s->name, name); 739 return s; 740 } 741 742 static int 743 cmp_import_elem (const def_file_import *e, const char *ex_name, 744 const char *in_name, const char *module, 745 int ord) 746 { 747 int r; 748 749 if ((r = are_names_equal (module, (e->module ? e->module->name : NULL)))) 750 return r; 751 if ((r = are_names_equal (ex_name, e->name)) != 0) 752 return r; 753 if ((r = are_names_equal (in_name, e->internal_name)) != 0) 754 return r; 755 if (ord != e->ordinal) 756 return (ord < e->ordinal ? -1 : 1); 757 return 0; 758 } 759 760 /* Search the position of the identical element, or returns the position 761 of the next higher element. If last valid element is smaller, then MAX 762 is returned. */ 763 764 static int 765 find_import_in_list (def_file_import *b, int max, 766 const char *ex_name, const char *in_name, 767 const char *module, int ord, int *is_ident) 768 { 769 int e, l, r, p; 770 771 *is_ident = 0; 772 if (!max) 773 return 0; 774 if ((e = cmp_import_elem (b, ex_name, in_name, module, ord)) <= 0) 775 { 776 if (!e) 777 *is_ident = 1; 778 return 0; 779 } 780 if (max == 1) 781 return 1; 782 if ((e = cmp_import_elem (b + (max - 1), ex_name, in_name, module, ord)) > 0) 783 return max; 784 else if (!e || max == 2) 785 { 786 if (!e) 787 *is_ident = 1; 788 return max - 1; 789 } 790 l = 0; r = max - 1; 791 while (l < r) 792 { 793 p = (l + r) / 2; 794 e = cmp_import_elem (b + p, ex_name, in_name, module, ord); 795 if (!e) 796 { 797 *is_ident = 1; 798 return p; 799 } 800 else if (e < 0) 801 r = p - 1; 802 else if (e > 0) 803 l = p + 1; 804 } 805 if ((e = cmp_import_elem (b + l, ex_name, in_name, module, ord)) > 0) 806 ++l; 807 else if (!e) 808 *is_ident = 1; 809 return l; 810 } 811 812 def_file_import * 813 def_file_add_import (def_file *fdef, 814 const char *name, 815 const char *module, 816 int ordinal, 817 const char *internal_name, 818 const char *its_name, 819 int *is_dup) 820 { 821 def_file_import *i; 822 int pos; 823 int max_imports = ROUND_UP (fdef->num_imports, 16); 824 825 /* We need to avoid here duplicates. */ 826 *is_dup = 0; 827 pos = find_import_in_list (fdef->imports, fdef->num_imports, 828 name, 829 (!internal_name ? name : internal_name), 830 module, ordinal, is_dup); 831 if (*is_dup != 0) 832 return fdef->imports + pos; 833 834 if (fdef->num_imports >= max_imports) 835 { 836 max_imports = ROUND_UP (fdef->num_imports+1, 16); 837 838 if (fdef->imports) 839 fdef->imports = xrealloc (fdef->imports, 840 max_imports * sizeof (def_file_import)); 841 else 842 fdef->imports = xmalloc (max_imports * sizeof (def_file_import)); 843 } 844 i = fdef->imports + pos; 845 if (pos != fdef->num_imports) 846 memmove (&i[1], i, (sizeof (def_file_import) * (fdef->num_imports - pos))); 847 memset (i, 0, sizeof (def_file_import)); 848 if (name) 849 i->name = xstrdup (name); 850 if (module) 851 i->module = def_stash_module (fdef, module); 852 i->ordinal = ordinal; 853 if (internal_name) 854 i->internal_name = xstrdup (internal_name); 855 else 856 i->internal_name = i->name; 857 i->its_name = (its_name ? xstrdup (its_name) : NULL); 858 fdef->num_imports++; 859 860 return i; 861 } 862 863 struct 864 { 865 char *param; 866 int token; 867 } 868 diropts[] = 869 { 870 { "-heap", HEAPSIZE }, 871 { "-stack", STACKSIZE_K }, 872 { "-attr", SECTIONS }, 873 { "-export", EXPORTS }, 874 { "-aligncomm", ALIGNCOMM }, 875 { 0, 0 } 876 }; 877 878 void 879 def_file_add_directive (def_file *my_def, const char *param, int len) 880 { 881 def_file *save_def = def; 882 const char *pend = param + len; 883 char * tend = (char *) param; 884 int i; 885 886 def = my_def; 887 888 while (param < pend) 889 { 890 while (param < pend 891 && (ISSPACE (*param) || *param == '\n' || *param == 0)) 892 param++; 893 894 if (param == pend) 895 break; 896 897 /* Scan forward until we encounter any of: 898 - the end of the buffer 899 - the start of a new option 900 - a newline seperating options 901 - a NUL seperating options. */ 902 for (tend = (char *) (param + 1); 903 (tend < pend 904 && !(ISSPACE (tend[-1]) && *tend == '-') 905 && *tend != '\n' && *tend != 0); 906 tend++) 907 ; 908 909 for (i = 0; diropts[i].param; i++) 910 { 911 len = strlen (diropts[i].param); 912 913 if (tend - param >= len 914 && strncmp (param, diropts[i].param, len) == 0 915 && (param[len] == ':' || param[len] == ' ')) 916 { 917 lex_parse_string_end = tend; 918 lex_parse_string = param + len + 1; 919 lex_forced_token = diropts[i].token; 920 saw_newline = 0; 921 if (def_parse ()) 922 continue; 923 break; 924 } 925 } 926 927 if (!diropts[i].param) 928 { 929 char saved; 930 931 saved = * tend; 932 * tend = 0; 933 /* xgettext:c-format */ 934 einfo (_("Warning: .drectve `%s' unrecognized\n"), param); 935 * tend = saved; 936 } 937 938 lex_parse_string = 0; 939 param = tend; 940 } 941 942 def = save_def; 943 def_pool_free (); 944 } 945 946 /* Parser Callbacks. */ 947 948 static void 949 def_image_name (const char *name, int base, int is_dll) 950 { 951 /* If a LIBRARY or NAME statement is specified without a name, there is nothing 952 to do here. We retain the output filename specified on command line. */ 953 if (*name) 954 { 955 const char* image_name = lbasename (name); 956 957 if (image_name != name) 958 einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n", 959 def_filename, linenumber, is_dll ? "LIBRARY" : "NAME", 960 name); 961 if (def->name) 962 free (def->name); 963 /* Append the default suffix, if none specified. */ 964 if (strchr (image_name, '.') == 0) 965 { 966 const char * suffix = is_dll ? ".dll" : ".exe"; 967 968 def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1); 969 sprintf (def->name, "%s%s", image_name, suffix); 970 } 971 else 972 def->name = xstrdup (image_name); 973 } 974 975 /* Honor a BASE address statement, even if LIBRARY string is empty. */ 976 def->base_address = base; 977 def->is_dll = is_dll; 978 } 979 980 static void 981 def_description (const char *text) 982 { 983 int len = def->description ? strlen (def->description) : 0; 984 985 len += strlen (text) + 1; 986 if (def->description) 987 { 988 def->description = xrealloc (def->description, len); 989 strcat (def->description, text); 990 } 991 else 992 { 993 def->description = xmalloc (len); 994 strcpy (def->description, text); 995 } 996 } 997 998 static void 999 def_stacksize (int reserve, int commit) 1000 { 1001 def->stack_reserve = reserve; 1002 def->stack_commit = commit; 1003 } 1004 1005 static void 1006 def_heapsize (int reserve, int commit) 1007 { 1008 def->heap_reserve = reserve; 1009 def->heap_commit = commit; 1010 } 1011 1012 static void 1013 def_section (const char *name, int attr) 1014 { 1015 def_file_section *s; 1016 int max_sections = ROUND_UP (def->num_section_defs, 4); 1017 1018 if (def->num_section_defs >= max_sections) 1019 { 1020 max_sections = ROUND_UP (def->num_section_defs+1, 4); 1021 1022 if (def->section_defs) 1023 def->section_defs = xrealloc (def->section_defs, 1024 max_sections * sizeof (def_file_import)); 1025 else 1026 def->section_defs = xmalloc (max_sections * sizeof (def_file_import)); 1027 } 1028 s = def->section_defs + def->num_section_defs; 1029 memset (s, 0, sizeof (def_file_section)); 1030 s->name = xstrdup (name); 1031 if (attr & 1) 1032 s->flag_read = 1; 1033 if (attr & 2) 1034 s->flag_write = 1; 1035 if (attr & 4) 1036 s->flag_execute = 1; 1037 if (attr & 8) 1038 s->flag_shared = 1; 1039 1040 def->num_section_defs++; 1041 } 1042 1043 static void 1044 def_section_alt (const char *name, const char *attr) 1045 { 1046 int aval = 0; 1047 1048 for (; *attr; attr++) 1049 { 1050 switch (*attr) 1051 { 1052 case 'R': 1053 case 'r': 1054 aval |= 1; 1055 break; 1056 case 'W': 1057 case 'w': 1058 aval |= 2; 1059 break; 1060 case 'X': 1061 case 'x': 1062 aval |= 4; 1063 break; 1064 case 'S': 1065 case 's': 1066 aval |= 8; 1067 break; 1068 } 1069 } 1070 def_section (name, aval); 1071 } 1072 1073 static void 1074 def_exports (const char *external_name, 1075 const char *internal_name, 1076 int ordinal, 1077 int flags, 1078 const char *its_name) 1079 { 1080 def_file_export *dfe; 1081 int is_dup = 0; 1082 1083 if (!internal_name && external_name) 1084 internal_name = external_name; 1085 #if TRACE 1086 printf ("def_exports, ext=%s int=%s\n", external_name, internal_name); 1087 #endif 1088 1089 dfe = def_file_add_export (def, external_name, internal_name, ordinal, 1090 its_name, &is_dup); 1091 1092 /* We might check here for flag redefinition and warn. For now we 1093 ignore duplicates silently. */ 1094 if (is_dup) 1095 return; 1096 1097 if (flags & 1) 1098 dfe->flag_noname = 1; 1099 if (flags & 2) 1100 dfe->flag_constant = 1; 1101 if (flags & 4) 1102 dfe->flag_data = 1; 1103 if (flags & 8) 1104 dfe->flag_private = 1; 1105 } 1106 1107 static void 1108 def_import (const char *internal_name, 1109 const char *module, 1110 const char *dllext, 1111 const char *name, 1112 int ordinal, 1113 const char *its_name) 1114 { 1115 char *buf = 0; 1116 const char *ext = dllext ? dllext : "dll"; 1117 int is_dup = 0; 1118 1119 buf = xmalloc (strlen (module) + strlen (ext) + 2); 1120 sprintf (buf, "%s.%s", module, ext); 1121 module = buf; 1122 1123 def_file_add_import (def, name, module, ordinal, internal_name, its_name, 1124 &is_dup); 1125 free (buf); 1126 } 1127 1128 static void 1129 def_version (int major, int minor) 1130 { 1131 def->version_major = major; 1132 def->version_minor = minor; 1133 } 1134 1135 static void 1136 def_directive (char *str) 1137 { 1138 struct directive *d = xmalloc (sizeof (struct directive)); 1139 1140 d->next = directives; 1141 directives = d; 1142 d->name = xstrdup (str); 1143 d->len = strlen (str); 1144 } 1145 1146 static void 1147 def_aligncomm (char *str, int align) 1148 { 1149 def_file_aligncomm *c, *p; 1150 1151 p = NULL; 1152 c = def->aligncomms; 1153 while (c != NULL) 1154 { 1155 int e = strcmp (c->symbol_name, str); 1156 if (!e) 1157 { 1158 /* Not sure if we want to allow here duplicates with 1159 different alignments, but for now we keep them. */ 1160 e = (int) c->alignment - align; 1161 if (!e) 1162 return; 1163 } 1164 if (e > 0) 1165 break; 1166 c = (p = c)->next; 1167 } 1168 1169 c = xmalloc (sizeof (def_file_aligncomm)); 1170 c->symbol_name = xstrdup (str); 1171 c->alignment = (unsigned int) align; 1172 if (!p) 1173 { 1174 c->next = def->aligncomms; 1175 def->aligncomms = c; 1176 } 1177 else 1178 { 1179 c->next = p->next; 1180 p->next = c; 1181 } 1182 } 1183 1184 static int 1185 def_error (const char *err) 1186 { 1187 einfo ("%P: %s:%d: %s\n", 1188 def_filename ? def_filename : "<unknown-file>", linenumber, err); 1189 return 0; 1190 } 1191 1192 1193 /* Lexical Scanner. */ 1194 1195 #undef TRACE 1196 #define TRACE 0 1197 1198 /* Never freed, but always reused as needed, so no real leak. */ 1199 static char *buffer = 0; 1200 static int buflen = 0; 1201 static int bufptr = 0; 1202 1203 static void 1204 put_buf (char c) 1205 { 1206 if (bufptr == buflen) 1207 { 1208 buflen += 50; /* overly reasonable, eh? */ 1209 if (buffer) 1210 buffer = xrealloc (buffer, buflen + 1); 1211 else 1212 buffer = xmalloc (buflen + 1); 1213 } 1214 buffer[bufptr++] = c; 1215 buffer[bufptr] = 0; /* not optimal, but very convenient. */ 1216 } 1217 1218 static struct 1219 { 1220 char *name; 1221 int token; 1222 } 1223 tokens[] = 1224 { 1225 { "BASE", BASE }, 1226 { "CODE", CODE }, 1227 { "CONSTANT", CONSTANTU }, 1228 { "constant", CONSTANTL }, 1229 { "DATA", DATAU }, 1230 { "data", DATAL }, 1231 { "DESCRIPTION", DESCRIPTION }, 1232 { "DIRECTIVE", DIRECTIVE }, 1233 { "EXECUTE", EXECUTE }, 1234 { "EXPORTS", EXPORTS }, 1235 { "HEAPSIZE", HEAPSIZE }, 1236 { "IMPORTS", IMPORTS }, 1237 { "LIBRARY", LIBRARY }, 1238 { "NAME", NAME }, 1239 { "NONAME", NONAMEU }, 1240 { "noname", NONAMEL }, 1241 { "PRIVATE", PRIVATEU }, 1242 { "private", PRIVATEL }, 1243 { "READ", READ }, 1244 { "SECTIONS", SECTIONS }, 1245 { "SEGMENTS", SECTIONS }, 1246 { "SHARED", SHARED }, 1247 { "STACKSIZE", STACKSIZE_K }, 1248 { "VERSION", VERSIONK }, 1249 { "WRITE", WRITE }, 1250 { 0, 0 } 1251 }; 1252 1253 static int 1254 def_getc (void) 1255 { 1256 int rv; 1257 1258 if (lex_parse_string) 1259 { 1260 if (lex_parse_string >= lex_parse_string_end) 1261 rv = EOF; 1262 else 1263 rv = *lex_parse_string++; 1264 } 1265 else 1266 { 1267 rv = fgetc (the_file); 1268 } 1269 if (rv == '\n') 1270 saw_newline = 1; 1271 return rv; 1272 } 1273 1274 static int 1275 def_ungetc (int c) 1276 { 1277 if (lex_parse_string) 1278 { 1279 lex_parse_string--; 1280 return c; 1281 } 1282 else 1283 return ungetc (c, the_file); 1284 } 1285 1286 static int 1287 def_lex (void) 1288 { 1289 int c, i, q; 1290 1291 if (lex_forced_token) 1292 { 1293 i = lex_forced_token; 1294 lex_forced_token = 0; 1295 #if TRACE 1296 printf ("lex: forcing token %d\n", i); 1297 #endif 1298 return i; 1299 } 1300 1301 c = def_getc (); 1302 1303 /* Trim leading whitespace. */ 1304 while (c != EOF && (c == ' ' || c == '\t') && saw_newline) 1305 c = def_getc (); 1306 1307 if (c == EOF) 1308 { 1309 #if TRACE 1310 printf ("lex: EOF\n"); 1311 #endif 1312 return 0; 1313 } 1314 1315 if (saw_newline && c == ';') 1316 { 1317 do 1318 { 1319 c = def_getc (); 1320 } 1321 while (c != EOF && c != '\n'); 1322 if (c == '\n') 1323 return def_lex (); 1324 return 0; 1325 } 1326 1327 /* Must be something else. */ 1328 saw_newline = 0; 1329 1330 if (ISDIGIT (c)) 1331 { 1332 bufptr = 0; 1333 while (c != EOF && (ISXDIGIT (c) || (c == 'x'))) 1334 { 1335 put_buf (c); 1336 c = def_getc (); 1337 } 1338 if (c != EOF) 1339 def_ungetc (c); 1340 yylval.digits = def_pool_strdup (buffer); 1341 #if TRACE 1342 printf ("lex: `%s' returns DIGITS\n", buffer); 1343 #endif 1344 return DIGITS; 1345 } 1346 1347 if (ISALPHA (c) || strchr ("$:-_?@", c)) 1348 { 1349 bufptr = 0; 1350 q = c; 1351 put_buf (c); 1352 c = def_getc (); 1353 1354 if (q == '@') 1355 { 1356 if (ISBLANK (c) ) /* '@' followed by whitespace. */ 1357 return (q); 1358 else if (ISDIGIT (c)) /* '@' followed by digit. */ 1359 { 1360 def_ungetc (c); 1361 return (q); 1362 } 1363 #if TRACE 1364 printf ("lex: @ returns itself\n"); 1365 #endif 1366 } 1367 1368 while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c))) 1369 { 1370 put_buf (c); 1371 c = def_getc (); 1372 } 1373 if (c != EOF) 1374 def_ungetc (c); 1375 if (ISALPHA (q)) /* Check for tokens. */ 1376 { 1377 for (i = 0; tokens[i].name; i++) 1378 if (strcmp (tokens[i].name, buffer) == 0) 1379 { 1380 #if TRACE 1381 printf ("lex: `%s' is a string token\n", buffer); 1382 #endif 1383 return tokens[i].token; 1384 } 1385 } 1386 #if TRACE 1387 printf ("lex: `%s' returns ID\n", buffer); 1388 #endif 1389 yylval.id = def_pool_strdup (buffer); 1390 return ID; 1391 } 1392 1393 if (c == '\'' || c == '"') 1394 { 1395 q = c; 1396 c = def_getc (); 1397 bufptr = 0; 1398 1399 while (c != EOF && c != q) 1400 { 1401 put_buf (c); 1402 c = def_getc (); 1403 } 1404 yylval.id = def_pool_strdup (buffer); 1405 #if TRACE 1406 printf ("lex: `%s' returns ID\n", buffer); 1407 #endif 1408 return ID; 1409 } 1410 1411 if ( c == '=') 1412 { 1413 c = def_getc (); 1414 if (c == '=') 1415 { 1416 #if TRACE 1417 printf ("lex: `==' returns EQUAL\n"); 1418 #endif 1419 return EQUAL; 1420 } 1421 def_ungetc (c); 1422 #if TRACE 1423 printf ("lex: `=' returns itself\n"); 1424 #endif 1425 return '='; 1426 } 1427 if (c == '.' || c == ',') 1428 { 1429 #if TRACE 1430 printf ("lex: `%c' returns itself\n", c); 1431 #endif 1432 return c; 1433 } 1434 1435 if (c == '\n') 1436 { 1437 linenumber++; 1438 saw_newline = 1; 1439 } 1440 1441 /*printf ("lex: 0x%02x ignored\n", c); */ 1442 return def_lex (); 1443 } 1444 1445 static char * 1446 def_pool_alloc (size_t sz) 1447 { 1448 def_pool_str *e; 1449 1450 e = (def_pool_str *) xmalloc (sizeof (def_pool_str) + sz); 1451 e->next = pool_strs; 1452 pool_strs = e; 1453 return e->data; 1454 } 1455 1456 static char * 1457 def_pool_strdup (const char *str) 1458 { 1459 char *s; 1460 size_t len; 1461 if (!str) 1462 return NULL; 1463 len = strlen (str) + 1; 1464 s = def_pool_alloc (len); 1465 memcpy (s, str, len); 1466 return s; 1467 } 1468 1469 static void 1470 def_pool_free (void) 1471 { 1472 def_pool_str *p; 1473 while ((p = pool_strs) != NULL) 1474 { 1475 pool_strs = p->next; 1476 free (p); 1477 } 1478 } 1479