]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-dump.c
* config/h8300/h8300.c (compute_saved_regs): Use a macro
[thirdparty/gcc.git] / gcc / tree-dump.c
CommitLineData
74338ff6 1/* Tree-dumping functionality for intermediate representation.
ac0c7fb1 2 Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
74338ff6 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"
74338ff6 25#include "splay-tree.h"
26#include "diagnostic.h"
27#include "toplev.h"
3119c950 28#include "tree-dump.h"
74338ff6 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);
40570cc2 67 dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
74338ff6 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;
40570cc2 158
74338ff6 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
74338ff6 227/* Dump the next node in the queue. */
228
40570cc2 229static void
74338ff6 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");
40570cc2 282
74338ff6 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;
40570cc2 301
74338ff6 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;
40570cc2 307
74338ff6 308 case 'e':
309 /* These nodes are handled explicitly below. */
310 break;
40570cc2 311
74338ff6 312 default:
ac0c7fb1 313 abort ();
74338ff6 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));
40570cc2 321 if (DECL_ASSEMBLER_NAME_SET_P (t)
74338ff6 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);
40570cc2 338 fprintf (di->stream, "srcp: %s:%-6d ", filename,
74338ff6 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);
40570cc2 352
74338ff6 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));
40570cc2 368
74338ff6 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");
40570cc2 455
74338ff6 456 dump_child ("flds", TYPE_FIELDS (t));
457 dump_child ("fncs", TYPE_METHODS (t));
40570cc2 458 queue_and_dump_index (di, "binf", TYPE_BINFO (t),
74338ff6 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 {
74338ff6 479 if (DECL_FIELD_OFFSET (t))
480 dump_child ("bpos", bit_position (t));
481 }
40570cc2 482 else if (TREE_CODE (t) == VAR_DECL
74338ff6 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
74338ff6 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
74338ff6 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;
40570cc2 577
74338ff6 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);
40570cc2 590
74338ff6 591 /* Terminate the line. */
592 fprintf (di->stream, "\n");
593}
594
595/* Return non-zero 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;
40570cc2 627 di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
74338ff6 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{
33b57a7b 649 const char *const suffix; /* suffix to give output file. */
650 const char *const swtch; /* command line switch */
74338ff6 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;
40570cc2 695
74338ff6 696 if (!dump_files[phase].state)
697 return NULL;
40570cc2 698
74338ff6 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;
40570cc2 708
74338ff6 709 return stream;
710}
711
712/* Returns non-zero 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 non-zero 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;
40570cc2 750
74338ff6 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;
40570cc2 756
74338ff6 757 while (*ptr)
758 {
759 const struct dump_option_value_info *option_ptr;
760 const char *end_ptr;
761 unsigned length;
40570cc2 762
74338ff6 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;
40570cc2 769
74338ff6 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 }
40570cc2 783
74338ff6 784 dump_files[ix].state = -1;
785 dump_files[ix].flags = flags;
40570cc2 786
74338ff6 787 return 1;
788 }
789 return 0;
790}