tree-dump.c revision 117395
1/* Tree-dumping functionality for intermediate representation. 2 Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc. 3 Written by Mark Mitchell <mark@codesourcery.com> 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 2, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING. If not, write to the Free 19Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2002111-1307, USA. */ 21 22#include "config.h" 23#include "system.h" 24#include "tree.h" 25#include "splay-tree.h" 26#include "diagnostic.h" 27#include "toplev.h" 28#include "tree-dump.h" 29#include "langhooks.h" 30 31static unsigned int queue PARAMS ((dump_info_p, tree, int)); 32static void dump_index PARAMS ((dump_info_p, unsigned int)); 33static void dequeue_and_dump PARAMS ((dump_info_p)); 34static void dump_new_line PARAMS ((dump_info_p)); 35static void dump_maybe_newline PARAMS ((dump_info_p)); 36static void dump_string_field PARAMS ((dump_info_p, const char *, const char *)); 37 38/* Add T to the end of the queue of nodes to dump. Returns the index 39 assigned to T. */ 40 41static unsigned int 42queue (di, t, flags) 43 dump_info_p di; 44 tree t; 45 int flags; 46{ 47 dump_queue_p dq; 48 dump_node_info_p dni; 49 unsigned int index; 50 51 /* Assign the next available index to T. */ 52 index = ++di->index; 53 54 /* Obtain a new queue node. */ 55 if (di->free_list) 56 { 57 dq = di->free_list; 58 di->free_list = dq->next; 59 } 60 else 61 dq = (dump_queue_p) xmalloc (sizeof (struct dump_queue)); 62 63 /* Create a new entry in the splay-tree. */ 64 dni = (dump_node_info_p) xmalloc (sizeof (struct dump_node_info)); 65 dni->index = index; 66 dni->binfo_p = ((flags & DUMP_BINFO) != 0); 67 dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t, 68 (splay_tree_value) dni); 69 70 /* Add it to the end of the queue. */ 71 dq->next = 0; 72 if (!di->queue_end) 73 di->queue = dq; 74 else 75 di->queue_end->next = dq; 76 di->queue_end = dq; 77 78 /* Return the index. */ 79 return index; 80} 81 82static void 83dump_index (di, index) 84 dump_info_p di; 85 unsigned int index; 86{ 87 fprintf (di->stream, "@%-6u ", index); 88 di->column += 8; 89} 90 91/* If T has not already been output, queue it for subsequent output. 92 FIELD is a string to print before printing the index. Then, the 93 index of T is printed. */ 94 95void 96queue_and_dump_index (di, field, t, flags) 97 dump_info_p di; 98 const char *field; 99 tree t; 100 int flags; 101{ 102 unsigned int index; 103 splay_tree_node n; 104 105 /* If there's no node, just return. This makes for fewer checks in 106 our callers. */ 107 if (!t) 108 return; 109 110 /* See if we've already queued or dumped this node. */ 111 n = splay_tree_lookup (di->nodes, (splay_tree_key) t); 112 if (n) 113 index = ((dump_node_info_p) n->value)->index; 114 else 115 /* If we haven't, add it to the queue. */ 116 index = queue (di, t, flags); 117 118 /* Print the index of the node. */ 119 dump_maybe_newline (di); 120 fprintf (di->stream, "%-4s: ", field); 121 di->column += 6; 122 dump_index (di, index); 123} 124 125/* Dump the type of T. */ 126 127void 128queue_and_dump_type (di, t) 129 dump_info_p di; 130 tree t; 131{ 132 queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE); 133} 134 135/* Dump column control */ 136#define SOL_COLUMN 25 /* Start of line column. */ 137#define EOL_COLUMN 55 /* End of line column. */ 138#define COLUMN_ALIGNMENT 15 /* Alignment. */ 139 140/* Insert a new line in the dump output, and indent to an appropriate 141 place to start printing more fields. */ 142 143static void 144dump_new_line (di) 145 dump_info_p di; 146{ 147 fprintf (di->stream, "\n%*s", SOL_COLUMN, ""); 148 di->column = SOL_COLUMN; 149} 150 151/* If necessary, insert a new line. */ 152 153static void 154dump_maybe_newline (di) 155 dump_info_p di; 156{ 157 int extra; 158 159 /* See if we need a new line. */ 160 if (di->column > EOL_COLUMN) 161 dump_new_line (di); 162 /* See if we need any padding. */ 163 else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0) 164 { 165 fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, ""); 166 di->column += COLUMN_ALIGNMENT - extra; 167 } 168} 169 170/* Dump pointer PTR using FIELD to identify it. */ 171 172void 173dump_pointer (di, field, ptr) 174 dump_info_p di; 175 const char *field; 176 void *ptr; 177{ 178 dump_maybe_newline (di); 179 fprintf (di->stream, "%-4s: %-8lx ", field, (long) ptr); 180 di->column += 15; 181} 182 183/* Dump integer I using FIELD to identify it. */ 184 185void 186dump_int (di, field, i) 187 dump_info_p di; 188 const char *field; 189 int i; 190{ 191 dump_maybe_newline (di); 192 fprintf (di->stream, "%-4s: %-7d ", field, i); 193 di->column += 14; 194} 195 196/* Dump the string S. */ 197 198void 199dump_string (di, string) 200 dump_info_p di; 201 const char *string; 202{ 203 dump_maybe_newline (di); 204 fprintf (di->stream, "%-13s ", string); 205 if (strlen (string) > 13) 206 di->column += strlen (string) + 1; 207 else 208 di->column += 14; 209} 210 211/* Dump the string field S. */ 212 213static void 214dump_string_field (di, field, string) 215 dump_info_p di; 216 const char *field; 217 const char *string; 218{ 219 dump_maybe_newline (di); 220 fprintf (di->stream, "%-4s: %-7s ", field, string); 221 if (strlen (string) > 7) 222 di->column += 6 + strlen (string) + 1; 223 else 224 di->column += 14; 225} 226 227/* Dump the next node in the queue. */ 228 229static void 230dequeue_and_dump (di) 231 dump_info_p di; 232{ 233 dump_queue_p dq; 234 splay_tree_node stn; 235 dump_node_info_p dni; 236 tree t; 237 unsigned int index; 238 enum tree_code code; 239 char code_class; 240 const char* code_name; 241 242 /* Get the next node from the queue. */ 243 dq = di->queue; 244 stn = dq->node; 245 t = (tree) stn->key; 246 dni = (dump_node_info_p) stn->value; 247 index = dni->index; 248 249 /* Remove the node from the queue, and put it on the free list. */ 250 di->queue = dq->next; 251 if (!di->queue) 252 di->queue_end = 0; 253 dq->next = di->free_list; 254 di->free_list = dq; 255 256 /* Print the node index. */ 257 dump_index (di, index); 258 /* And the type of node this is. */ 259 if (dni->binfo_p) 260 code_name = "binfo"; 261 else 262 code_name = tree_code_name[(int) TREE_CODE (t)]; 263 fprintf (di->stream, "%-16s ", code_name); 264 di->column = 25; 265 266 /* Figure out what kind of node this is. */ 267 code = TREE_CODE (t); 268 code_class = TREE_CODE_CLASS (code); 269 270 /* Although BINFOs are TREE_VECs, we dump them specially so as to be 271 more informative. */ 272 if (dni->binfo_p) 273 { 274 if (TREE_VIA_PUBLIC (t)) 275 dump_string (di, "pub"); 276 else if (TREE_VIA_PROTECTED (t)) 277 dump_string (di, "prot"); 278 else if (TREE_VIA_PRIVATE (t)) 279 dump_string (di, "priv"); 280 if (TREE_VIA_VIRTUAL (t)) 281 dump_string (di, "virt"); 282 283 dump_child ("type", BINFO_TYPE (t)); 284 dump_child ("base", BINFO_BASETYPES (t)); 285 286 goto done; 287 } 288 289 /* We can knock off a bunch of expression nodes in exactly the same 290 way. */ 291 if (IS_EXPR_CODE_CLASS (code_class)) 292 { 293 /* If we're dumping children, dump them now. */ 294 queue_and_dump_type (di, t); 295 296 switch (code_class) 297 { 298 case '1': 299 dump_child ("op 0", TREE_OPERAND (t, 0)); 300 break; 301 302 case '2': 303 case '<': 304 dump_child ("op 0", TREE_OPERAND (t, 0)); 305 dump_child ("op 1", TREE_OPERAND (t, 1)); 306 break; 307 308 case 'e': 309 /* These nodes are handled explicitly below. */ 310 break; 311 312 default: 313 abort (); 314 } 315 } 316 else if (DECL_P (t)) 317 { 318 /* All declarations have names. */ 319 if (DECL_NAME (t)) 320 dump_child ("name", DECL_NAME (t)); 321 if (DECL_ASSEMBLER_NAME_SET_P (t) 322 && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t)) 323 dump_child ("mngl", DECL_ASSEMBLER_NAME (t)); 324 /* And types. */ 325 queue_and_dump_type (di, t); 326 dump_child ("scpe", DECL_CONTEXT (t)); 327 /* And a source position. */ 328 if (DECL_SOURCE_FILE (t)) 329 { 330 const char *filename = strrchr (DECL_SOURCE_FILE (t), '/'); 331 if (!filename) 332 filename = DECL_SOURCE_FILE (t); 333 else 334 /* Skip the slash. */ 335 ++filename; 336 337 dump_maybe_newline (di); 338 fprintf (di->stream, "srcp: %s:%-6d ", filename, 339 DECL_SOURCE_LINE (t)); 340 di->column += 6 + strlen (filename) + 8; 341 } 342 /* And any declaration can be compiler-generated. */ 343 if (DECL_ARTIFICIAL (t)) 344 dump_string (di, "artificial"); 345 if (TREE_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL)) 346 dump_child ("chan", TREE_CHAIN (t)); 347 } 348 else if (code_class == 't') 349 { 350 /* All types have qualifiers. */ 351 int quals = (*lang_hooks.tree_dump.type_quals) (t); 352 353 if (quals != TYPE_UNQUALIFIED) 354 { 355 fprintf (di->stream, "qual: %c%c%c ", 356 (quals & TYPE_QUAL_CONST) ? 'c' : ' ', 357 (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ', 358 (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' '); 359 di->column += 14; 360 } 361 362 /* All types have associated declarations. */ 363 dump_child ("name", TYPE_NAME (t)); 364 365 /* All types have a main variant. */ 366 if (TYPE_MAIN_VARIANT (t) != t) 367 dump_child ("unql", TYPE_MAIN_VARIANT (t)); 368 369 /* And sizes. */ 370 dump_child ("size", TYPE_SIZE (t)); 371 372 /* All types have alignments. */ 373 dump_int (di, "algn", TYPE_ALIGN (t)); 374 } 375 else if (code_class == 'c') 376 /* All constants can have types. */ 377 queue_and_dump_type (di, t); 378 379 /* Give the language-specific code a chance to print something. If 380 it's completely taken care of things, don't bother printing 381 anything more ourselves. */ 382 if ((*lang_hooks.tree_dump.dump_tree) (di, t)) 383 goto done; 384 385 /* Now handle the various kinds of nodes. */ 386 switch (code) 387 { 388 int i; 389 390 case IDENTIFIER_NODE: 391 dump_string_field (di, "strg", IDENTIFIER_POINTER (t)); 392 dump_int (di, "lngt", IDENTIFIER_LENGTH (t)); 393 break; 394 395 case TREE_LIST: 396 dump_child ("purp", TREE_PURPOSE (t)); 397 dump_child ("valu", TREE_VALUE (t)); 398 dump_child ("chan", TREE_CHAIN (t)); 399 break; 400 401 case TREE_VEC: 402 dump_int (di, "lngt", TREE_VEC_LENGTH (t)); 403 for (i = 0; i < TREE_VEC_LENGTH (t); ++i) 404 { 405 char buffer[32]; 406 sprintf (buffer, "%u", i); 407 dump_child (buffer, TREE_VEC_ELT (t, i)); 408 } 409 break; 410 411 case INTEGER_TYPE: 412 case ENUMERAL_TYPE: 413 dump_int (di, "prec", TYPE_PRECISION (t)); 414 if (TREE_UNSIGNED (t)) 415 dump_string (di, "unsigned"); 416 dump_child ("min", TYPE_MIN_VALUE (t)); 417 dump_child ("max", TYPE_MAX_VALUE (t)); 418 419 if (code == ENUMERAL_TYPE) 420 dump_child ("csts", TYPE_VALUES (t)); 421 break; 422 423 case REAL_TYPE: 424 dump_int (di, "prec", TYPE_PRECISION (t)); 425 break; 426 427 case POINTER_TYPE: 428 dump_child ("ptd", TREE_TYPE (t)); 429 break; 430 431 case REFERENCE_TYPE: 432 dump_child ("refd", TREE_TYPE (t)); 433 break; 434 435 case METHOD_TYPE: 436 dump_child ("clas", TYPE_METHOD_BASETYPE (t)); 437 /* Fall through. */ 438 439 case FUNCTION_TYPE: 440 dump_child ("retn", TREE_TYPE (t)); 441 dump_child ("prms", TYPE_ARG_TYPES (t)); 442 break; 443 444 case ARRAY_TYPE: 445 dump_child ("elts", TREE_TYPE (t)); 446 dump_child ("domn", TYPE_DOMAIN (t)); 447 break; 448 449 case RECORD_TYPE: 450 case UNION_TYPE: 451 if (TREE_CODE (t) == RECORD_TYPE) 452 dump_string (di, "struct"); 453 else 454 dump_string (di, "union"); 455 456 dump_child ("flds", TYPE_FIELDS (t)); 457 dump_child ("fncs", TYPE_METHODS (t)); 458 queue_and_dump_index (di, "binf", TYPE_BINFO (t), 459 DUMP_BINFO); 460 break; 461 462 case CONST_DECL: 463 dump_child ("cnst", DECL_INITIAL (t)); 464 break; 465 466 case VAR_DECL: 467 case PARM_DECL: 468 case FIELD_DECL: 469 case RESULT_DECL: 470 if (TREE_CODE (t) == PARM_DECL) 471 dump_child ("argt", DECL_ARG_TYPE (t)); 472 else 473 dump_child ("init", DECL_INITIAL (t)); 474 dump_child ("size", DECL_SIZE (t)); 475 dump_int (di, "algn", DECL_ALIGN (t)); 476 477 if (TREE_CODE (t) == FIELD_DECL) 478 { 479 if (DECL_FIELD_OFFSET (t)) 480 dump_child ("bpos", bit_position (t)); 481 } 482 else if (TREE_CODE (t) == VAR_DECL 483 || TREE_CODE (t) == PARM_DECL) 484 { 485 dump_int (di, "used", TREE_USED (t)); 486 if (DECL_REGISTER (t)) 487 dump_string (di, "register"); 488 } 489 break; 490 491 case FUNCTION_DECL: 492 dump_child ("args", DECL_ARGUMENTS (t)); 493 if (DECL_EXTERNAL (t)) 494 dump_string (di, "undefined"); 495 if (TREE_PUBLIC (t)) 496 dump_string (di, "extern"); 497 else 498 dump_string (di, "static"); 499 if (DECL_LANG_SPECIFIC (t) && !dump_flag (di, TDF_SLIM, t)) 500 dump_child ("body", DECL_SAVED_TREE (t)); 501 break; 502 503 case INTEGER_CST: 504 if (TREE_INT_CST_HIGH (t)) 505 dump_int (di, "high", TREE_INT_CST_HIGH (t)); 506 dump_int (di, "low", TREE_INT_CST_LOW (t)); 507 break; 508 509 case STRING_CST: 510 fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t)); 511 dump_int (di, "lngt", TREE_STRING_LENGTH (t)); 512 break; 513 514 case TRUTH_NOT_EXPR: 515 case ADDR_EXPR: 516 case INDIRECT_REF: 517 case CLEANUP_POINT_EXPR: 518 case SAVE_EXPR: 519 /* These nodes are unary, but do not have code class `1'. */ 520 dump_child ("op 0", TREE_OPERAND (t, 0)); 521 break; 522 523 case TRUTH_ANDIF_EXPR: 524 case TRUTH_ORIF_EXPR: 525 case INIT_EXPR: 526 case MODIFY_EXPR: 527 case COMPONENT_REF: 528 case COMPOUND_EXPR: 529 case ARRAY_REF: 530 case PREDECREMENT_EXPR: 531 case PREINCREMENT_EXPR: 532 case POSTDECREMENT_EXPR: 533 case POSTINCREMENT_EXPR: 534 /* These nodes are binary, but do not have code class `2'. */ 535 dump_child ("op 0", TREE_OPERAND (t, 0)); 536 dump_child ("op 1", TREE_OPERAND (t, 1)); 537 break; 538 539 case COND_EXPR: 540 dump_child ("op 0", TREE_OPERAND (t, 0)); 541 dump_child ("op 1", TREE_OPERAND (t, 1)); 542 dump_child ("op 2", TREE_OPERAND (t, 2)); 543 break; 544 545 case CALL_EXPR: 546 dump_child ("fn", TREE_OPERAND (t, 0)); 547 dump_child ("args", TREE_OPERAND (t, 1)); 548 break; 549 550 case CONSTRUCTOR: 551 dump_child ("elts", TREE_OPERAND (t, 1)); 552 break; 553 554 case BIND_EXPR: 555 dump_child ("vars", TREE_OPERAND (t, 0)); 556 dump_child ("body", TREE_OPERAND (t, 1)); 557 break; 558 559 case LOOP_EXPR: 560 dump_child ("body", TREE_OPERAND (t, 0)); 561 break; 562 563 case EXIT_EXPR: 564 dump_child ("cond", TREE_OPERAND (t, 0)); 565 break; 566 567 case TARGET_EXPR: 568 dump_child ("decl", TREE_OPERAND (t, 0)); 569 dump_child ("init", TREE_OPERAND (t, 1)); 570 dump_child ("clnp", TREE_OPERAND (t, 2)); 571 /* There really are two possible places the initializer can be. 572 After RTL expansion, the second operand is moved to the 573 position of the fourth operand, and the second operand 574 becomes NULL. */ 575 dump_child ("init", TREE_OPERAND (t, 3)); 576 break; 577 578 case EXPR_WITH_FILE_LOCATION: 579 dump_child ("expr", EXPR_WFL_NODE (t)); 580 break; 581 582 default: 583 /* There are no additional fields to print. */ 584 break; 585 } 586 587 done: 588 if (dump_flag (di, TDF_ADDRESS, NULL)) 589 dump_pointer (di, "addr", (void *)t); 590 591 /* Terminate the line. */ 592 fprintf (di->stream, "\n"); 593} 594 595/* Return nonzero if FLAG has been specified for the dump, and NODE 596 is not the root node of the dump. */ 597 598int dump_flag (di, flag, node) 599 dump_info_p di; 600 int flag; 601 tree node; 602{ 603 return (di->flags & flag) && (node != di->node); 604} 605 606/* Dump T, and all its children, on STREAM. */ 607 608void 609dump_node (t, flags, stream) 610 tree t; 611 int flags; 612 FILE *stream; 613{ 614 struct dump_info di; 615 dump_queue_p dq; 616 dump_queue_p next_dq; 617 618 /* Initialize the dump-information structure. */ 619 di.stream = stream; 620 di.index = 0; 621 di.column = 0; 622 di.queue = 0; 623 di.queue_end = 0; 624 di.free_list = 0; 625 di.flags = flags; 626 di.node = t; 627 di.nodes = splay_tree_new (splay_tree_compare_pointers, 0, 628 (splay_tree_delete_value_fn) &free); 629 630 /* Queue up the first node. */ 631 queue (&di, t, DUMP_NONE); 632 633 /* Until the queue is empty, keep dumping nodes. */ 634 while (di.queue) 635 dequeue_and_dump (&di); 636 637 /* Now, clean up. */ 638 for (dq = di.free_list; dq; dq = next_dq) 639 { 640 next_dq = dq->next; 641 free (dq); 642 } 643 splay_tree_delete (di.nodes); 644} 645 646/* Define a tree dump switch. */ 647struct dump_file_info 648{ 649 const char *const suffix; /* suffix to give output file. */ 650 const char *const swtch; /* command line switch */ 651 int flags; /* user flags */ 652 int state; /* state of play */ 653}; 654 655/* Table of tree dump switches. This must be consistent with the 656 TREE_DUMP_INDEX enumeration in tree.h */ 657static struct dump_file_info dump_files[TDI_end] = 658{ 659 {".tu", "dump-translation-unit", 0, 0}, 660 {".class", "dump-class-hierarchy", 0, 0}, 661 {".original", "dump-tree-original", 0, 0}, 662 {".optimized", "dump-tree-optimized", 0, 0}, 663 {".inlined", "dump-tree-inlined", 0, 0}, 664}; 665 666/* Define a name->number mapping for a dump flag value. */ 667struct dump_option_value_info 668{ 669 const char *const name; /* the name of the value */ 670 const int value; /* the value of the name */ 671}; 672 673/* Table of dump options. This must be consistent with the TDF_* flags 674 in tree.h */ 675static const struct dump_option_value_info dump_options[] = 676{ 677 {"address", TDF_ADDRESS}, 678 {"slim", TDF_SLIM}, 679 {"all", ~0}, 680 {NULL, 0} 681}; 682 683/* Begin a tree dump for PHASE. Stores any user supplied flag in 684 *FLAG_PTR and returns a stream to write to. If the dump is not 685 enabled, returns NULL. 686 Multiple calls will reopen and append to the dump file. */ 687 688FILE * 689dump_begin (phase, flag_ptr) 690 enum tree_dump_index phase; 691 int *flag_ptr; 692{ 693 FILE *stream; 694 char *name; 695 696 if (!dump_files[phase].state) 697 return NULL; 698 699 name = concat (dump_base_name, dump_files[phase].suffix, NULL); 700 stream = fopen (name, dump_files[phase].state < 0 ? "w" : "a"); 701 if (!stream) 702 error ("could not open dump file `%s'", name); 703 else 704 dump_files[phase].state = 1; 705 free (name); 706 if (flag_ptr) 707 *flag_ptr = dump_files[phase].flags; 708 709 return stream; 710} 711 712/* Returns nonzero if tree dump PHASE is enabled. */ 713 714int 715dump_enabled_p (phase) 716 enum tree_dump_index phase; 717{ 718 return dump_files[phase].state; 719} 720 721/* Returns the switch name of PHASE. */ 722 723const char * 724dump_flag_name (phase) 725 enum tree_dump_index phase; 726{ 727 return dump_files[phase].swtch; 728} 729 730/* Finish a tree dump for PHASE. STREAM is the stream created by 731 dump_begin. */ 732 733void 734dump_end (phase, stream) 735 enum tree_dump_index phase ATTRIBUTE_UNUSED; 736 FILE *stream; 737{ 738 fclose (stream); 739} 740 741/* Parse ARG as a dump switch. Return nonzero if it is, and store the 742 relevant details in the dump_files array. */ 743 744int 745dump_switch_p (arg) 746 const char *arg; 747{ 748 unsigned ix; 749 const char *option_value; 750 751 for (ix = 0; ix != TDI_end; ix++) 752 if ((option_value = skip_leading_substring (arg, dump_files[ix].swtch))) 753 { 754 const char *ptr = option_value; 755 int flags = 0; 756 757 while (*ptr) 758 { 759 const struct dump_option_value_info *option_ptr; 760 const char *end_ptr; 761 unsigned length; 762 763 while (*ptr == '-') 764 ptr++; 765 end_ptr = strchr (ptr, '-'); 766 if (!end_ptr) 767 end_ptr = ptr + strlen (ptr); 768 length = end_ptr - ptr; 769 770 for (option_ptr = dump_options; option_ptr->name; 771 option_ptr++) 772 if (strlen (option_ptr->name) == length 773 && !memcmp (option_ptr->name, ptr, length)) 774 { 775 flags |= option_ptr->value; 776 goto found; 777 } 778 warning ("ignoring unknown option `%.*s' in `-f%s'", 779 length, ptr, dump_files[ix].swtch); 780 found:; 781 ptr = end_ptr; 782 } 783 784 dump_files[ix].state = -1; 785 dump_files[ix].flags = flags; 786 787 return 1; 788 } 789 return 0; 790} 791