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