]> git.saurik.com Git - bison.git/blob - src/getargs.c
diagnostics: revamp the handling of -Werror
[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 arg the subarguments to decode.
233 * If null, then activate all the flags.
234 * \param no length of the potential "no-" prefix.
235 * Can be 0 or 3. If 3, negate the action of the subargument.
236 * \param err length of a potential "error=".
237 * Can be 0 or 6. If 6, treat the subargument as a CATEGORY.
238 *
239 * If VALUE != 0 then KEY sets flags and no-KEY clears them.
240 * If VALUE == 0 then KEY clears all flags from \c all and no-KEY sets all
241 * flags from \c all. Thus no-none = all and no-all = none.
242 */
243 static void
244 warning_argmatch (char const *arg, size_t no, size_t err)
245 {
246 int value = XARGMATCH ("--warning", arg + no + err,
247 warnings_args, warnings_types);
248
249 /* -Wnone == -Wno-all, and -Wno-none == -Wall. */
250 if (!value)
251 {
252 value = Wall;
253 no = !no;
254 }
255
256 if (no)
257 {
258 size_t b;
259 for (b = 0; b < warnings_size; ++b)
260 if (value & 1 << b)
261 {
262 if (err)
263 {
264 /* -Wno-error=foo: if foo enabled as an error,
265 make it a warning. */
266 if (warnings_flag[b] == severity_error)
267 warnings_flag[b] = severity_warning;
268 }
269 else
270 /* -Wno-foo. */
271 warnings_flag[b] = severity_disabled;
272 }
273 }
274 else
275 {
276 size_t b;
277 for (b = 0; b < warnings_size; ++b)
278 if (value & 1 << b)
279 /* -Wfoo and -Werror=foo. */
280 warnings_flag[b] = err ? severity_error : severity_warning;
281 }
282 }
283
284 /** Decode a comma-separated list of arguments from -W.
285 *
286 * \param args comma separated list of effective subarguments to decode.
287 * If 0, then activate all the flags.
288 */
289 static void
290 warnings_argmatch (char *args)
291 {
292 if (args)
293 for (args = strtok (args, ","); args; args = strtok (NULL, ","))
294 if (STREQ (args, "error"))
295 warnings_are_errors = true;
296 else if (STREQ (args, "no-error"))
297 {
298 warnings_are_errors = false;
299 warning_argmatch ("no-error=all", 3, 6);
300 }
301 else
302 {
303 size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0;
304 size_t err = STRPREFIX_LIT ("error=", args + no) ? 6 : 0;
305
306 warning_argmatch (args, no, err);
307 }
308 else
309 warning_argmatch ("all", 0, 0);
310 }
311
312 const char * const warnings_args[] =
313 {
314 "none",
315 "midrule-values",
316 "yacc",
317 "conflicts-sr",
318 "conflicts-rr",
319 "deprecated",
320 "precedence",
321 "other",
322 "all",
323 "error",
324 0
325 };
326
327 const int warnings_types[] =
328 {
329 Wnone,
330 Wmidrule_values,
331 Wyacc,
332 Wconflicts_sr,
333 Wconflicts_rr,
334 Wdeprecated,
335 Wprecedence,
336 Wother,
337 Wall,
338 Werror
339 };
340
341 ARGMATCH_VERIFY (warnings_args, warnings_types);
342
343 /*-----------------------.
344 | --feature's handling. |
345 `-----------------------*/
346
347 static const char * const feature_args[] =
348 {
349 "none",
350 "caret", "diagnostics-show-caret",
351 "all",
352 0
353 };
354
355 static const int feature_types[] =
356 {
357 feature_none,
358 feature_caret, feature_caret,
359 feature_all
360 };
361
362 ARGMATCH_VERIFY (feature_args, feature_types);
363
364 /*-------------------------------------------.
365 | Display the help message and exit STATUS. |
366 `-------------------------------------------*/
367
368 static void usage (int) ATTRIBUTE_NORETURN;
369
370 static void
371 usage (int status)
372 {
373 if (status != 0)
374 fprintf (stderr, _("Try `%s --help' for more information.\n"),
375 program_name);
376 else
377 {
378 /* For ../build-aux/cross-options.pl to work, use the format:
379 ^ -S, --long[=ARGS] (whitespace)
380 A --long option is required.
381 Otherwise, add exceptions to ../build-aux/cross-options.pl. */
382
383 printf (_("Usage: %s [OPTION]... FILE\n"), program_name);
384 fputs (_("\
385 Generate a deterministic LR or generalized LR (GLR) parser employing\n\
386 LALR(1), IELR(1), or canonical LR(1) parser tables. IELR(1) and\n\
387 canonical LR(1) support is experimental.\n\
388 \n\
389 "), stdout);
390
391 fputs (_("\
392 Mandatory arguments to long options are mandatory for short options too.\n\
393 "), stdout);
394 fputs (_("\
395 The same is true for optional arguments.\n\
396 "), stdout);
397
398 fputs (_("\
399 \n\
400 Operation modes:\n\
401 -h, --help display this help and exit\n\
402 -V, --version output version information and exit\n\
403 --print-localedir output directory containing locale-dependent data\n\
404 --print-datadir output directory containing skeletons and XSLT\n\
405 -y, --yacc emulate POSIX Yacc\n\
406 -W, --warnings[=CATEGORY] report the warnings falling in CATEGORY\n\
407 -f, --feature[=FEATURE] activate miscellaneous features\n\
408 \n\
409 "), stdout);
410
411 fputs (_("\
412 Parser:\n\
413 -L, --language=LANGUAGE specify the output programming language\n\
414 -S, --skeleton=FILE specify the skeleton to use\n\
415 -t, --debug instrument the parser for tracing\n\
416 same as `-Dparse.trace'\n\
417 --locations enable location support\n\
418 -D, --define=NAME[=VALUE] similar to '%define NAME \"VALUE\"'\n\
419 -F, --force-define=NAME[=VALUE] override '%define NAME \"VALUE\"'\n\
420 -p, --name-prefix=PREFIX prepend PREFIX to the external symbols\n\
421 deprecated by '-Dapi.prefix=PREFIX'\n\
422 -l, --no-lines don't generate '#line' directives\n\
423 -k, --token-table include a table of token names\n\
424 "), stdout);
425 putc ('\n', stdout);
426
427 /* Keep -d and --defines separate so that ../build-aux/cross-options.pl
428 * won't assume that -d also takes an argument. */
429 fputs (_("\
430 Output:\n\
431 --defines[=FILE] also produce a header file\n\
432 -d likewise but cannot specify FILE (for POSIX Yacc)\n\
433 -r, --report=THINGS also produce details on the automaton\n\
434 --report-file=FILE write report to FILE\n\
435 -v, --verbose same as `--report=state'\n\
436 -b, --file-prefix=PREFIX specify a PREFIX for output files\n\
437 -o, --output=FILE leave output to FILE\n\
438 -g, --graph[=FILE] also output a graph of the automaton\n\
439 -x, --xml[=FILE] also output an XML report of the automaton\n\
440 (the XML schema is experimental)\n\
441 "), stdout);
442 putc ('\n', stdout);
443
444 fputs (_("\
445 Warning categories include:\n\
446 `midrule-values' unset or unused midrule values\n\
447 `yacc' incompatibilities with POSIX Yacc\n\
448 `conflicts-sr' S/R conflicts (enabled by default)\n\
449 `conflicts-rr' R/R conflicts (enabled by default)\n\
450 `deprecated' obsolete constructs\n\
451 `precedence' useless precedence and associativity\n\
452 `other' all other warnings (enabled by default)\n\
453 `all' all the warnings\n\
454 `no-CATEGORY' turn off warnings in CATEGORY\n\
455 `none' turn off all the warnings\n\
456 `error[=CATEGORY]' treat warnings as errors\n\
457 "), stdout);
458 putc ('\n', stdout);
459
460 fputs (_("\
461 THINGS is a list of comma separated words that can include:\n\
462 `state' describe the states\n\
463 `itemset' complete the core item sets with their closure\n\
464 `lookahead' explicitly associate lookahead tokens to items\n\
465 `solved' describe shift/reduce conflicts solving\n\
466 `all' include all the above information\n\
467 `none' disable the report\n\
468 "), stdout);
469 putc ('\n', stdout);
470
471 fputs (_("\
472 FEATURE is a list of comma separated words that can include:\n\
473 `caret' show errors with carets\n\
474 `all' all of the above\n\
475 `none' disable all of the above\n\
476 "), stdout);
477
478 putc ('\n', stdout);
479 printf (_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
480 printf (_("%s home page: <%s>.\n"), PACKAGE_NAME, PACKAGE_URL);
481 fputs (_("General help using GNU software: "
482 "<http://www.gnu.org/gethelp/>.\n"),
483 stdout);
484 /* Don't output this redundant message for English locales.
485 Note we still output for 'C' so that it gets included in the
486 man page. */
487 const char *lc_messages = setlocale (LC_MESSAGES, NULL);
488 if (lc_messages && !STREQ (lc_messages, "en_"))
489 /* TRANSLATORS: Replace LANG_CODE in this URL with your language
490 code <http://translationproject.org/team/LANG_CODE.html> to
491 form one of the URLs at http://translationproject.org/team/.
492 Otherwise, replace the entire URL with your translation team's
493 email address. */
494 fputs (_("Report translation bugs to "
495 "<http://translationproject.org/team/>.\n"), stdout);
496 fputs (_("For complete documentation, run: info bison.\n"), stdout);
497 }
498
499 exit (status);
500 }
501
502
503 /*------------------------------.
504 | Display the version message. |
505 `------------------------------*/
506
507 static void
508 version (void)
509 {
510 /* Some efforts were made to ease the translators' task, please
511 continue. */
512 printf (_("bison (GNU Bison) %s"), VERSION);
513 putc ('\n', stdout);
514 fputs (_("Written by Robert Corbett and Richard Stallman.\n"), stdout);
515 putc ('\n', stdout);
516
517 fprintf (stdout,
518 _("Copyright (C) %d Free Software Foundation, Inc.\n"),
519 PACKAGE_COPYRIGHT_YEAR);
520
521 fputs (_("\
522 This is free software; see the source for copying conditions. There is NO\n\
523 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
524 "),
525 stdout);
526 }
527
528
529 /*-------------------------------------.
530 | --skeleton and --language handling. |
531 `--------------------------------------*/
532
533 void
534 skeleton_arg (char const *arg, int prio, location loc)
535 {
536 if (prio < skeleton_prio)
537 {
538 skeleton_prio = prio;
539 skeleton = arg;
540 }
541 else if (prio == skeleton_prio)
542 complain (&loc, complaint,
543 _("multiple skeleton declarations are invalid"));
544 }
545
546 void
547 language_argmatch (char const *arg, int prio, location loc)
548 {
549 char const *msg;
550
551 if (prio < language_prio)
552 {
553 int i;
554 for (i = 0; valid_languages[i].language[0]; i++)
555 if (c_strcasecmp (arg, valid_languages[i].language) == 0)
556 {
557 language_prio = prio;
558 language = &valid_languages[i];
559 return;
560 }
561 msg = _("%s: invalid language");
562 }
563 else if (language_prio == prio)
564 msg = _("multiple language declarations are invalid");
565 else
566 return;
567
568 complain (&loc, complaint, msg, quotearg_colon (arg));
569 }
570
571 /*----------------------.
572 | Process the options. |
573 `----------------------*/
574
575 /* Shorts options.
576 Should be computed from long_options. */
577 static char const short_options[] =
578 "D:"
579 "F:"
580 "L:"
581 "S:"
582 "T::"
583 "V"
584 "W::"
585 "b:"
586 "d"
587 "f::"
588 "e"
589 "g::"
590 "h"
591 "k"
592 "l"
593 "n"
594 "o:"
595 "p:"
596 "r:"
597 "t"
598 "v"
599 "x::"
600 "y"
601 ;
602
603 /* Values for long options that do not have single-letter equivalents. */
604 enum
605 {
606 LOCATIONS_OPTION = CHAR_MAX + 1,
607 PRINT_LOCALEDIR_OPTION,
608 PRINT_DATADIR_OPTION,
609 REPORT_FILE_OPTION
610 };
611
612 static struct option const long_options[] =
613 {
614 /* Operation modes. */
615 { "help", no_argument, 0, 'h' },
616 { "version", no_argument, 0, 'V' },
617 { "print-localedir", no_argument, 0, PRINT_LOCALEDIR_OPTION },
618 { "print-datadir", no_argument, 0, PRINT_DATADIR_OPTION },
619 { "warnings", optional_argument, 0, 'W' },
620
621 /* Parser. */
622 { "name-prefix", required_argument, 0, 'p' },
623 { "include", required_argument, 0, 'I' },
624
625 /* Output. */
626 { "file-prefix", required_argument, 0, 'b' },
627 { "output", required_argument, 0, 'o' },
628 { "output-file", required_argument, 0, 'o' },
629 { "graph", optional_argument, 0, 'g' },
630 { "xml", optional_argument, 0, 'x' },
631 { "report", required_argument, 0, 'r' },
632 { "report-file", required_argument, 0, REPORT_FILE_OPTION },
633 { "verbose", no_argument, 0, 'v' },
634
635 /* Hidden. */
636 { "trace", optional_argument, 0, 'T' },
637
638 /* Output. */
639 { "defines", optional_argument, 0, 'd' },
640 { "feature", optional_argument, 0, 'f' },
641
642 /* Operation modes. */
643 { "fixed-output-files", no_argument, 0, 'y' },
644 { "yacc", no_argument, 0, 'y' },
645
646 /* Parser. */
647 { "debug", no_argument, 0, 't' },
648 { "define", required_argument, 0, 'D' },
649 { "force-define", required_argument, 0, 'F' },
650 { "locations", no_argument, 0, LOCATIONS_OPTION },
651 { "no-lines", no_argument, 0, 'l' },
652 { "raw", no_argument, 0, 0 },
653 { "skeleton", required_argument, 0, 'S' },
654 { "language", required_argument, 0, 'L' },
655 { "token-table", no_argument, 0, 'k' },
656
657 {0, 0, 0, 0}
658 };
659
660 /* Under DOS, there is no difference on the case. This can be
661 troublesome when looking for `.tab' etc. */
662 #ifdef MSDOS
663 # define AS_FILE_NAME(File) (strlwr (File), (File))
664 #else
665 # define AS_FILE_NAME(File) (File)
666 #endif
667
668 /* Build a location for the current command line argument. */
669 static
670 location
671 command_line_location (void)
672 {
673 location res;
674 /* "<command line>" is used in GCC's messages about -D. */
675 boundary_set (&res.start, uniqstr_new ("<command line>"), optind - 1, -1);
676 res.end = res.start;
677 return res;
678 }
679
680
681 void
682 getargs (int argc, char *argv[])
683 {
684 int c;
685
686 while ((c = getopt_long (argc, argv, short_options, long_options, NULL))
687 != -1)
688 switch (c)
689 {
690 /* ASCII Sorting for short options (i.e., upper case then
691 lower case), and then long-only options. */
692
693 case 0:
694 /* Certain long options cause getopt_long to return 0. */
695 break;
696
697 case 'D': /* -DNAME[=VALUE]. */
698 case 'F': /* -FNAME[=VALUE]. */
699 {
700 char* name = optarg;
701 char* value = strchr (optarg, '=');
702 if (value)
703 *value++ = 0;
704 muscle_percent_define_insert (name, command_line_location (),
705 value ? value : "",
706 c == 'D' ? MUSCLE_PERCENT_DEFINE_D
707 : MUSCLE_PERCENT_DEFINE_F);
708 }
709 break;
710
711 case 'I':
712 include = AS_FILE_NAME (optarg);
713 break;
714
715 case 'L':
716 language_argmatch (optarg, command_line_prio,
717 command_line_location ());
718 break;
719
720 case 'S':
721 skeleton_arg (AS_FILE_NAME (optarg), command_line_prio,
722 command_line_location ());
723 break;
724
725 case 'T':
726 FLAGS_ARGMATCH (trace, optarg, trace_all);
727 break;
728
729 case 'V':
730 version ();
731 exit (EXIT_SUCCESS);
732
733 case 'f':
734 FLAGS_ARGMATCH (feature, optarg, feature_all);
735 break;
736
737 case 'W':
738 warnings_argmatch (optarg);
739 break;
740
741 case 'b':
742 spec_file_prefix = AS_FILE_NAME (optarg);
743 break;
744
745 case 'd':
746 /* Here, the -d and --defines options are differentiated. */
747 defines_flag = true;
748 if (optarg)
749 {
750 free (spec_defines_file);
751 spec_defines_file = xstrdup (AS_FILE_NAME (optarg));
752 }
753 break;
754
755 case 'g':
756 graph_flag = true;
757 if (optarg)
758 {
759 free (spec_graph_file);
760 spec_graph_file = xstrdup (AS_FILE_NAME (optarg));
761 }
762 break;
763
764 case 'h':
765 usage (EXIT_SUCCESS);
766
767 case 'k':
768 token_table_flag = true;
769 break;
770
771 case 'l':
772 no_lines_flag = true;
773 break;
774
775 case 'o':
776 spec_outfile = AS_FILE_NAME (optarg);
777 break;
778
779 case 'p':
780 spec_name_prefix = optarg;
781 break;
782
783 case 'r':
784 FLAGS_ARGMATCH (report, optarg, report_all);
785 break;
786
787 case 't':
788 muscle_percent_define_insert ("parse.trace",
789 command_line_location (), "",
790 MUSCLE_PERCENT_DEFINE_D);
791 break;
792
793 case 'v':
794 report_flag |= report_states;
795 break;
796
797 case 'x':
798 xml_flag = true;
799 if (optarg)
800 {
801 free (spec_xml_file);
802 spec_xml_file = xstrdup (AS_FILE_NAME (optarg));
803 }
804 break;
805
806 case 'y':
807 warnings_flag[warning_yacc] = severity_error;
808 yacc_flag = true;
809 break;
810
811 case LOCATIONS_OPTION:
812 muscle_percent_define_ensure ("locations",
813 command_line_location (), true);
814 break;
815
816 case PRINT_LOCALEDIR_OPTION:
817 printf ("%s\n", LOCALEDIR);
818 exit (EXIT_SUCCESS);
819
820 case PRINT_DATADIR_OPTION:
821 printf ("%s\n", pkgdatadir ());
822 exit (EXIT_SUCCESS);
823
824 case REPORT_FILE_OPTION:
825 free (spec_verbose_file);
826 spec_verbose_file = xstrdup (AS_FILE_NAME (optarg));
827 break;
828
829 default:
830 usage (EXIT_FAILURE);
831 }
832
833 if (argc - optind != 1)
834 {
835 if (argc - optind < 1)
836 error (0, 0, _("%s: missing operand"), quotearg_colon (argv[argc - 1]));
837 else
838 error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
839 usage (EXIT_FAILURE);
840 }
841
842 current_file = grammar_file = uniqstr_new (argv[optind]);
843 MUSCLE_INSERT_C_STRING ("file_name", grammar_file);
844 }
845
846 void
847 tr (char *s, char from, char to)
848 {
849 for (; *s; s++)
850 if (*s == from)
851 *s = to;
852 }