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