]> git.saurik.com Git - bison.git/blob - src/getargs.c
options: simplify the handling of -W
[bison.git] / src / getargs.c
1 /* Parse command line arguments for Bison.
2
3 Copyright (C) 1984, 1986, 1989, 1992, 2000-2013 Free Software
4 Foundation, Inc.
5
6 This file is part of Bison, the GNU Compiler Compiler.
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, see <http://www.gnu.org/licenses/>. */
20
21 #include <config.h>
22 #include "system.h"
23 #include "output.h"
24
25 #include <argmatch.h>
26 #include <c-strcase.h>
27 #include <configmake.h>
28 #include <error.h>
29 #include <getopt.h>
30 #include <progname.h>
31
32 #include "complain.h"
33 #include "files.h"
34 #include "getargs.h"
35 #include "muscle-tab.h"
36 #include "quote.h"
37 #include "uniqstr.h"
38
39 bool defines_flag;
40 bool graph_flag;
41 bool xml_flag;
42 bool no_lines_flag;
43 bool token_table_flag;
44 bool yacc_flag; /* for -y */
45
46 bool nondeterministic_parser = false;
47 bool glr_parser = false;
48
49 int feature_flag = feature_caret;
50 int report_flag = report_none;
51 int trace_flag = trace_none;
52
53 static struct bison_language const valid_languages[] = {
54 { "c", "c-skel.m4", ".c", ".h", true },
55 { "c++", "c++-skel.m4", ".cc", ".hh", true },
56 { "java", "java-skel.m4", ".java", ".java", false },
57 { "", "", "", "", false }
58 };
59
60 int skeleton_prio = default_prio;
61 const char *skeleton = NULL;
62 int language_prio = default_prio;
63 struct bison_language const *language = &valid_languages[0];
64 const char *include = NULL;
65
66 /** Decode an option's key.
67 *
68 * \param option option being decoded.
69 * \param keys array of valid subarguments.
70 * \param values array of corresponding (int) values.
71 * \param all the all value.
72 * \param flags the flags to update
73 * \param arg the subarguments to decode.
74 * If null, then activate all the flags.
75 * \param no length of the potential "no-" prefix.
76 * Can be 0 or 3. If 3, negate the action of the subargument.
77 *
78 * If VALUE != 0 then KEY sets flags and no-KEY clears them.
79 * If VALUE == 0 then KEY clears all flags from \c all and no-KEY sets all
80 * flags from \c all. Thus no-none = all and no-all = none.
81 */
82 static void
83 flag_argmatch (const char *option,
84 const char * const keys[], const int values[],
85 int all, int *flags, char *arg, size_t no)
86 {
87 int value = 0;
88 value = XARGMATCH (option, arg + no, keys, values);
89
90 if (value)
91 {
92 if (no)
93 *flags &= ~value;
94 else
95 *flags |= value;
96 }
97 else
98 {
99 if (no)
100 *flags |= all;
101 else
102 *flags &= ~all;
103 }
104 }
105
106 /** Decode an option's set of keys.
107 *
108 * \param option option being decoded.
109 * \param keys array of valid subarguments.
110 * \param values array of corresponding (int) values.
111 * \param all the all value.
112 * \param flags the flags to update
113 * \param args comma separated list of effective subarguments to decode.
114 * If 0, then activate all the flags.
115 */
116 static void
117 flags_argmatch (const char *option,
118 const char * const keys[], const int values[],
119 int all, int *flags, char *args)
120 {
121 if (args)
122 for (args = strtok (args, ","); args; args = strtok (NULL, ","))
123 {
124 size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0;
125 flag_argmatch (option, keys,
126 values, all, flags, args, no);
127 }
128 else
129 *flags |= all;
130 }
131
132
133 /** Decode a set of sub arguments.
134 *
135 * \param FlagName the flag familly to update.
136 * \param Args the effective sub arguments to decode.
137 * \param All the "all" value.
138 *
139 * \arg FlagName_args the list of keys.
140 * \arg FlagName_types the list of values.
141 * \arg FlagName_flag the flag to update.
142 */
143 #define FLAGS_ARGMATCH(FlagName, Args, All) \
144 flags_argmatch ("--" #FlagName, FlagName ## _args, FlagName ## _types, \
145 All, &FlagName ## _flag, Args)
146
147
148 /*----------------------.
149 | --report's handling. |
150 `----------------------*/
151
152 static const char * const report_args[] =
153 {
154 /* In a series of synonyms, present the most meaningful first, so
155 that argmatch_valid be more readable. */
156 "none",
157 "state", "states",
158 "itemset", "itemsets",
159 "lookahead", "lookaheads", "look-ahead",
160 "solved",
161 "all",
162 0
163 };
164
165 static const int report_types[] =
166 {
167 report_none,
168 report_states, report_states,
169 report_states | report_itemsets, report_states | report_itemsets,
170 report_states | report_lookahead_tokens,
171 report_states | report_lookahead_tokens,
172 report_states | report_lookahead_tokens,
173 report_states | report_solved_conflicts,
174 report_all
175 };
176
177 ARGMATCH_VERIFY (report_args, report_types);
178
179
180 /*---------------------.
181 | --trace's handling. |
182 `---------------------*/
183
184 static const char * const trace_args[] =
185 {
186 "none - no traces",
187 "scan - grammar scanner traces",
188 "parse - grammar parser traces",
189 "automaton - construction of the automaton",
190 "bitsets - use of bitsets",
191 "grammar - reading, reducing the grammar",
192 "resource - memory consumption (where available)",
193 "sets - grammar sets: firsts, nullable etc.",
194 "muscles - m4 definitions passed to the skeleton",
195 "tools - m4 invocation",
196 "m4 - m4 traces",
197 "skeleton - skeleton postprocessing",
198 "time - time consumption",
199 "ielr - IELR conversion",
200 "all - all of the above",
201 0
202 };
203
204 static const int trace_types[] =
205 {
206 trace_none,
207 trace_scan,
208 trace_parse,
209 trace_automaton,
210 trace_bitsets,
211 trace_grammar,
212 trace_resource,
213 trace_sets,
214 trace_muscles,
215 trace_tools,
216 trace_m4,
217 trace_skeleton,
218 trace_time,
219 trace_ielr,
220 trace_all
221 };
222
223 ARGMATCH_VERIFY (trace_args, trace_types);
224
225
226 /*------------------------.
227 | --warnings's handling. |
228 `------------------------*/
229
230 /** Decode a single argument from -W.
231 *
232 * \param flags the flags to update
233 * \param arg the subarguments to decode.
234 * If null, then activate all the flags.
235 * \param no length of the potential "no-" prefix.
236 * Can be 0 or 3. If 3, negate the action of the subargument.
237 * \param err length of a potential "error=".
238 * Can be 0 or 5. If 5, treat the subargument as a CATEGORY.
239 *
240 * If VALUE != 0 then KEY sets flags and no-KEY clears them.
241 * If VALUE == 0 then KEY clears all flags from \c all and no-KEY sets all
242 * flags from \c all. Thus no-none = all and no-all = none.
243 */
244 static void
245 warning_argmatch (int *flags, char *arg, size_t no, size_t err)
246 {
247 int value = 0;
248 if (!err || arg[no + err++] != '\0')
249 value = XARGMATCH ("--warning", arg + no + err,
250 warnings_args, warnings_types);
251
252 if (value)
253 {
254 if (no)
255 *flags &= ~value;
256 else
257 {
258 if (err)
259 warnings_flag |= value;
260 *flags |= value;
261 }
262 }
263 else
264 {
265 /* With a simpler 'if (no)' version, -Werror means -Werror=all
266 (or rather, -Werror=no-none, but that syntax is invalid).
267 The difference is:
268 - Werror activates all errors, but not the warnings
269 - Werror=all activates errors, and all warnings */
270 if (no ? !err : err)
271 *flags |= Wall;
272 else
273 *flags &= ~Wall;
274 }
275 }
276
277 /** Decode a comma-separated list of arguments from -W.
278 *
279 * \param args comma separated list of effective subarguments to decode.
280 * If 0, then activate all the flags.
281 */
282 static void
283 warnings_argmatch (char *args)
284 {
285 if (args)
286 for (args = strtok (args, ","); args; args = strtok (NULL, ","))
287 {
288 size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0;
289 size_t err = STRPREFIX_LIT ("error", args + no) ? 5 : 0;
290
291 warning_argmatch (err ? &errors_flag : &warnings_flag,
292 args, no, err);
293 }
294 else
295 warnings_flag |= Wall;
296 }
297
298 const char * const warnings_args[] =
299 {
300 "none",
301 "midrule-values",
302 "yacc",
303 "conflicts-sr",
304 "conflicts-rr",
305 "deprecated",
306 "precedence",
307 "other",
308 "all",
309 "error",
310 0
311 };
312
313 const int warnings_types[] =
314 {
315 Wnone,
316 Wmidrule_values,
317 Wyacc,
318 Wconflicts_sr,
319 Wconflicts_rr,
320 Wdeprecated,
321 Wprecedence,
322 Wother,
323 Wall,
324 Werror
325 };
326
327 ARGMATCH_VERIFY (warnings_args, warnings_types);
328
329 /*-----------------------.
330 | --feature's handling. |
331 `-----------------------*/
332
333 static const char * const feature_args[] =
334 {
335 "none",
336 "caret", "diagnostics-show-caret",
337 "all",
338 0
339 };
340
341 static const int feature_types[] =
342 {
343 feature_none,
344 feature_caret, feature_caret,
345 feature_all
346 };
347
348 ARGMATCH_VERIFY (feature_args, feature_types);
349
350 /*-------------------------------------------.
351 | Display the help message and exit STATUS. |
352 `-------------------------------------------*/
353
354 static void usage (int) ATTRIBUTE_NORETURN;
355
356 static void
357 usage (int status)
358 {
359 if (status != 0)
360 fprintf (stderr, _("Try `%s --help' for more information.\n"),
361 program_name);
362 else
363 {
364 /* For ../build-aux/cross-options.pl to work, use the format:
365 ^ -S, --long[=ARGS] (whitespace)
366 A --long option is required.
367 Otherwise, add exceptions to ../build-aux/cross-options.pl. */
368
369 printf (_("Usage: %s [OPTION]... FILE\n"), program_name);
370 fputs (_("\
371 Generate a deterministic LR or generalized LR (GLR) parser employing\n\
372 LALR(1), IELR(1), or canonical LR(1) parser tables. IELR(1) and\n\
373 canonical LR(1) support is experimental.\n\
374 \n\
375 "), stdout);
376
377 fputs (_("\
378 Mandatory arguments to long options are mandatory for short options too.\n\
379 "), stdout);
380 fputs (_("\
381 The same is true for optional arguments.\n\
382 "), stdout);
383
384 fputs (_("\
385 \n\
386 Operation modes:\n\
387 -h, --help display this help and exit\n\
388 -V, --version output version information and exit\n\
389 --print-localedir output directory containing locale-dependent data\n\
390 --print-datadir output directory containing skeletons and XSLT\n\
391 -y, --yacc emulate POSIX Yacc\n\
392 -W, --warnings[=CATEGORY] report the warnings falling in CATEGORY\n\
393 -f, --feature[=FEATURE] activate miscellaneous features\n\
394 \n\
395 "), stdout);
396
397 fputs (_("\
398 Parser:\n\
399 -L, --language=LANGUAGE specify the output programming language\n\
400 -S, --skeleton=FILE specify the skeleton to use\n\
401 -t, --debug instrument the parser for tracing\n\
402 same as `-Dparse.trace'\n\
403 --locations enable location support\n\
404 -D, --define=NAME[=VALUE] similar to '%define NAME \"VALUE\"'\n\
405 -F, --force-define=NAME[=VALUE] override '%define NAME \"VALUE\"'\n\
406 -p, --name-prefix=PREFIX prepend PREFIX to the external symbols\n\
407 deprecated by '-Dapi.prefix=PREFIX'\n\
408 -l, --no-lines don't generate '#line' directives\n\
409 -k, --token-table include a table of token names\n\
410 "), stdout);
411 putc ('\n', stdout);
412
413 /* Keep -d and --defines separate so that ../build-aux/cross-options.pl
414 * won't assume that -d also takes an argument. */
415 fputs (_("\
416 Output:\n\
417 --defines[=FILE] also produce a header file\n\
418 -d likewise but cannot specify FILE (for POSIX Yacc)\n\
419 -r, --report=THINGS also produce details on the automaton\n\
420 --report-file=FILE write report to FILE\n\
421 -v, --verbose same as `--report=state'\n\
422 -b, --file-prefix=PREFIX specify a PREFIX for output files\n\
423 -o, --output=FILE leave output to FILE\n\
424 -g, --graph[=FILE] also output a graph of the automaton\n\
425 -x, --xml[=FILE] also output an XML report of the automaton\n\
426 (the XML schema is experimental)\n\
427 "), stdout);
428 putc ('\n', stdout);
429
430 fputs (_("\
431 Warning categories include:\n\
432 `midrule-values' unset or unused midrule values\n\
433 `yacc' incompatibilities with POSIX Yacc\n\
434 `conflicts-sr' S/R conflicts (enabled by default)\n\
435 `conflicts-rr' R/R conflicts (enabled by default)\n\
436 `deprecated' obsolete constructs\n\
437 `precedence' useless precedence and associativity\n\
438 `other' all other warnings (enabled by default)\n\
439 `all' all the warnings\n\
440 `no-CATEGORY' turn off warnings in CATEGORY\n\
441 `none' turn off all the warnings\n\
442 `error[=CATEGORY]' treat warnings as errors\n\
443 "), stdout);
444 putc ('\n', stdout);
445
446 fputs (_("\
447 THINGS is a list of comma separated words that can include:\n\
448 `state' describe the states\n\
449 `itemset' complete the core item sets with their closure\n\
450 `lookahead' explicitly associate lookahead tokens to items\n\
451 `solved' describe shift/reduce conflicts solving\n\
452 `all' include all the above information\n\
453 `none' disable the report\n\
454 "), stdout);
455 putc ('\n', stdout);
456
457 fputs (_("\
458 FEATURE is a list of comma separated words that can include:\n\
459 `caret' show errors with carets\n\
460 `all' all of the above\n\
461 `none' disable all of the above\n\
462 "), stdout);
463
464 putc ('\n', stdout);
465 printf (_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
466 printf (_("%s home page: <%s>.\n"), PACKAGE_NAME, PACKAGE_URL);
467 fputs (_("General help using GNU software: "
468 "<http://www.gnu.org/gethelp/>.\n"),
469 stdout);
470 /* Don't output this redundant message for English locales.
471 Note we still output for 'C' so that it gets included in the
472 man page. */
473 const char *lc_messages = setlocale (LC_MESSAGES, NULL);
474 if (lc_messages && !STREQ (lc_messages, "en_"))
475 /* TRANSLATORS: Replace LANG_CODE in this URL with your language
476 code <http://translationproject.org/team/LANG_CODE.html> to
477 form one of the URLs at http://translationproject.org/team/.
478 Otherwise, replace the entire URL with your translation team's
479 email address. */
480 fputs (_("Report translation bugs to "
481 "<http://translationproject.org/team/>.\n"), stdout);
482 fputs (_("For complete documentation, run: info bison.\n"), stdout);
483 }
484
485 exit (status);
486 }
487
488
489 /*------------------------------.
490 | Display the version message. |
491 `------------------------------*/
492
493 static void
494 version (void)
495 {
496 /* Some efforts were made to ease the translators' task, please
497 continue. */
498 printf (_("bison (GNU Bison) %s"), VERSION);
499 putc ('\n', stdout);
500 fputs (_("Written by Robert Corbett and Richard Stallman.\n"), stdout);
501 putc ('\n', stdout);
502
503 fprintf (stdout,
504 _("Copyright (C) %d Free Software Foundation, Inc.\n"),
505 PACKAGE_COPYRIGHT_YEAR);
506
507 fputs (_("\
508 This is free software; see the source for copying conditions. There is NO\n\
509 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
510 "),
511 stdout);
512 }
513
514
515 /*-------------------------------------.
516 | --skeleton and --language handling. |
517 `--------------------------------------*/
518
519 void
520 skeleton_arg (char const *arg, int prio, location loc)
521 {
522 if (prio < skeleton_prio)
523 {
524 skeleton_prio = prio;
525 skeleton = arg;
526 }
527 else if (prio == skeleton_prio)
528 complain (&loc, complaint,
529 _("multiple skeleton declarations are invalid"));
530 }
531
532 void
533 language_argmatch (char const *arg, int prio, location loc)
534 {
535 char const *msg;
536
537 if (prio < language_prio)
538 {
539 int i;
540 for (i = 0; valid_languages[i].language[0]; i++)
541 if (c_strcasecmp (arg, valid_languages[i].language) == 0)
542 {
543 language_prio = prio;
544 language = &valid_languages[i];
545 return;
546 }
547 msg = _("%s: invalid language");
548 }
549 else if (language_prio == prio)
550 msg = _("multiple language declarations are invalid");
551 else
552 return;
553
554 complain (&loc, complaint, msg, quotearg_colon (arg));
555 }
556
557 /*----------------------.
558 | Process the options. |
559 `----------------------*/
560
561 /* Shorts options.
562 Should be computed from long_options. */
563 static char const short_options[] =
564 "D:"
565 "F:"
566 "L:"
567 "S:"
568 "T::"
569 "V"
570 "W::"
571 "b:"
572 "d"
573 "f::"
574 "e"
575 "g::"
576 "h"
577 "k"
578 "l"
579 "n"
580 "o:"
581 "p:"
582 "r:"
583 "t"
584 "v"
585 "x::"
586 "y"
587 ;
588
589 /* Values for long options that do not have single-letter equivalents. */
590 enum
591 {
592 LOCATIONS_OPTION = CHAR_MAX + 1,
593 PRINT_LOCALEDIR_OPTION,
594 PRINT_DATADIR_OPTION,
595 REPORT_FILE_OPTION
596 };
597
598 static struct option const long_options[] =
599 {
600 /* Operation modes. */
601 { "help", no_argument, 0, 'h' },
602 { "version", no_argument, 0, 'V' },
603 { "print-localedir", no_argument, 0, PRINT_LOCALEDIR_OPTION },
604 { "print-datadir", no_argument, 0, PRINT_DATADIR_OPTION },
605 { "warnings", optional_argument, 0, 'W' },
606
607 /* Parser. */
608 { "name-prefix", required_argument, 0, 'p' },
609 { "include", required_argument, 0, 'I' },
610
611 /* Output. */
612 { "file-prefix", required_argument, 0, 'b' },
613 { "output", required_argument, 0, 'o' },
614 { "output-file", required_argument, 0, 'o' },
615 { "graph", optional_argument, 0, 'g' },
616 { "xml", optional_argument, 0, 'x' },
617 { "report", required_argument, 0, 'r' },
618 { "report-file", required_argument, 0, REPORT_FILE_OPTION },
619 { "verbose", no_argument, 0, 'v' },
620
621 /* Hidden. */
622 { "trace", optional_argument, 0, 'T' },
623
624 /* Output. */
625 { "defines", optional_argument, 0, 'd' },
626 { "feature", optional_argument, 0, 'f' },
627
628 /* Operation modes. */
629 { "fixed-output-files", no_argument, 0, 'y' },
630 { "yacc", no_argument, 0, 'y' },
631
632 /* Parser. */
633 { "debug", no_argument, 0, 't' },
634 { "define", required_argument, 0, 'D' },
635 { "force-define", required_argument, 0, 'F' },
636 { "locations", no_argument, 0, LOCATIONS_OPTION },
637 { "no-lines", no_argument, 0, 'l' },
638 { "raw", no_argument, 0, 0 },
639 { "skeleton", required_argument, 0, 'S' },
640 { "language", required_argument, 0, 'L' },
641 { "token-table", no_argument, 0, 'k' },
642
643 {0, 0, 0, 0}
644 };
645
646 /* Under DOS, there is no difference on the case. This can be
647 troublesome when looking for `.tab' etc. */
648 #ifdef MSDOS
649 # define AS_FILE_NAME(File) (strlwr (File), (File))
650 #else
651 # define AS_FILE_NAME(File) (File)
652 #endif
653
654 /* Build a location for the current command line argument. */
655 static
656 location
657 command_line_location (void)
658 {
659 location res;
660 /* "<command line>" is used in GCC's messages about -D. */
661 boundary_set (&res.start, uniqstr_new ("<command line>"), optind - 1, -1);
662 res.end = res.start;
663 return res;
664 }
665
666
667 void
668 getargs (int argc, char *argv[])
669 {
670 int c;
671
672 while ((c = getopt_long (argc, argv, short_options, long_options, NULL))
673 != -1)
674 switch (c)
675 {
676 /* ASCII Sorting for short options (i.e., upper case then
677 lower case), and then long-only options. */
678
679 case 0:
680 /* Certain long options cause getopt_long to return 0. */
681 break;
682
683 case 'D': /* -DNAME[=VALUE]. */
684 case 'F': /* -FNAME[=VALUE]. */
685 {
686 char* name = optarg;
687 char* value = strchr (optarg, '=');
688 if (value)
689 *value++ = 0;
690 muscle_percent_define_insert (name, command_line_location (),
691 value ? value : "",
692 c == 'D' ? MUSCLE_PERCENT_DEFINE_D
693 : MUSCLE_PERCENT_DEFINE_F);
694 }
695 break;
696
697 case 'I':
698 include = AS_FILE_NAME (optarg);
699 break;
700
701 case 'L':
702 language_argmatch (optarg, command_line_prio,
703 command_line_location ());
704 break;
705
706 case 'S':
707 skeleton_arg (AS_FILE_NAME (optarg), command_line_prio,
708 command_line_location ());
709 break;
710
711 case 'T':
712 FLAGS_ARGMATCH (trace, optarg, trace_all);
713 break;
714
715 case 'V':
716 version ();
717 exit (EXIT_SUCCESS);
718
719 case 'f':
720 FLAGS_ARGMATCH (feature, optarg, feature_all);
721 break;
722
723 case 'W':
724 warnings_argmatch (optarg);
725 break;
726
727 case 'b':
728 spec_file_prefix = AS_FILE_NAME (optarg);
729 break;
730
731 case 'd':
732 /* Here, the -d and --defines options are differentiated. */
733 defines_flag = true;
734 if (optarg)
735 {
736 free (spec_defines_file);
737 spec_defines_file = xstrdup (AS_FILE_NAME (optarg));
738 }
739 break;
740
741 case 'g':
742 graph_flag = true;
743 if (optarg)
744 {
745 free (spec_graph_file);
746 spec_graph_file = xstrdup (AS_FILE_NAME (optarg));
747 }
748 break;
749
750 case 'h':
751 usage (EXIT_SUCCESS);
752
753 case 'k':
754 token_table_flag = true;
755 break;
756
757 case 'l':
758 no_lines_flag = true;
759 break;
760
761 case 'o':
762 spec_outfile = AS_FILE_NAME (optarg);
763 break;
764
765 case 'p':
766 spec_name_prefix = optarg;
767 break;
768
769 case 'r':
770 FLAGS_ARGMATCH (report, optarg, report_all);
771 break;
772
773 case 't':
774 muscle_percent_define_insert ("parse.trace",
775 command_line_location (), "",
776 MUSCLE_PERCENT_DEFINE_D);
777 break;
778
779 case 'v':
780 report_flag |= report_states;
781 break;
782
783 case 'x':
784 xml_flag = true;
785 if (optarg)
786 {
787 free (spec_xml_file);
788 spec_xml_file = xstrdup (AS_FILE_NAME (optarg));
789 }
790 break;
791
792 case 'y':
793 warnings_flag |= Wyacc;
794 errors_flag |= Wyacc;
795 yacc_flag = true;
796 break;
797
798 case LOCATIONS_OPTION:
799 muscle_percent_define_ensure ("locations",
800 command_line_location (), true);
801 break;
802
803 case PRINT_LOCALEDIR_OPTION:
804 printf ("%s\n", LOCALEDIR);
805 exit (EXIT_SUCCESS);
806
807 case PRINT_DATADIR_OPTION:
808 printf ("%s\n", pkgdatadir ());
809 exit (EXIT_SUCCESS);
810
811 case REPORT_FILE_OPTION:
812 free (spec_verbose_file);
813 spec_verbose_file = xstrdup (AS_FILE_NAME (optarg));
814 break;
815
816 default:
817 usage (EXIT_FAILURE);
818 }
819
820 if (argc - optind != 1)
821 {
822 if (argc - optind < 1)
823 error (0, 0, _("%s: missing operand"), quotearg_colon (argv[argc - 1]));
824 else
825 error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
826 usage (EXIT_FAILURE);
827 }
828
829 current_file = grammar_file = uniqstr_new (argv[optind]);
830 MUSCLE_INSERT_C_STRING ("file_name", grammar_file);
831 }
832
833 void
834 tr (char *s, char from, char to)
835 {
836 for (; *s; s++)
837 if (*s == from)
838 *s = to;
839 }