+ complain_at (loc, complaint, msg, quotearg_colon (arg));
+}
+
+/*----------------------.
+| Process the options. |
+`----------------------*/
+
+/* Shorts options.
+ Should be computed from long_options. */
+static char const short_options[] =
+ "D:"
+ "F:"
+ "L:"
+ "S:"
+ "T::"
+ "V"
+ "W::"
+ "b:"
+ "d"
+ "e"
+ "g::"
+ "h"
+ "k"
+ "l"
+ "n"
+ "o:"
+ "p:"
+ "r:"
+ "t"
+ "v"
+ "x::"
+ "y"
+ ;
+
+/* Values for long options that do not have single-letter equivalents. */
+enum
+{
+ LOCATIONS_OPTION = CHAR_MAX + 1,
+ PRINT_LOCALEDIR_OPTION,
+ PRINT_DATADIR_OPTION,
+ REPORT_FILE_OPTION
+};
+
+static struct option const long_options[] =
+{
+ /* Operation modes. */
+ { "help", no_argument, 0, 'h' },
+ { "version", no_argument, 0, 'V' },
+ { "print-localedir", no_argument, 0, PRINT_LOCALEDIR_OPTION },
+ { "print-datadir", no_argument, 0, PRINT_DATADIR_OPTION },
+ { "warnings", optional_argument, 0, 'W' },
+
+ /* Parser. */
+ { "name-prefix", required_argument, 0, 'p' },
+ { "include", required_argument, 0, 'I' },
+
+ /* Output. */
+ { "file-prefix", required_argument, 0, 'b' },
+ { "output", required_argument, 0, 'o' },
+ { "output-file", required_argument, 0, 'o' },
+ { "graph", optional_argument, 0, 'g' },
+ { "xml", optional_argument, 0, 'x' },
+ { "report", required_argument, 0, 'r' },
+ { "report-file", required_argument, 0, REPORT_FILE_OPTION },
+ { "verbose", no_argument, 0, 'v' },
+
+ /* Hidden. */
+ { "trace", optional_argument, 0, 'T' },
+
+ /* Output. */
+ { "defines", optional_argument, 0, 'd' },
+
+ /* Operation modes. */
+ { "fixed-output-files", no_argument, 0, 'y' },
+ { "yacc", no_argument, 0, 'y' },
+
+ /* Parser. */
+ { "debug", no_argument, 0, 't' },
+ { "define", required_argument, 0, 'D' },
+ { "force-define", required_argument, 0, 'F' },
+ { "locations", no_argument, 0, LOCATIONS_OPTION },
+ { "no-lines", no_argument, 0, 'l' },
+ { "raw", no_argument, 0, 0 },
+ { "skeleton", required_argument, 0, 'S' },
+ { "language", required_argument, 0, 'L' },
+ { "token-table", no_argument, 0, 'k' },
+
+ {0, 0, 0, 0}
+};
+
+/* Under DOS, there is no difference on the case. This can be
+ troublesome when looking for `.tab' etc. */
+#ifdef MSDOS
+# define AS_FILE_NAME(File) (strlwr (File), (File))
+#else
+# define AS_FILE_NAME(File) (File)
+#endif
+
+/* Build a location for the current command line argument. */
+static
+location
+command_line_location (void)
+{
+ location res;
+ /* "<command line>" is used in GCC's messages about -D. */
+ boundary_set (&res.start, uniqstr_new ("<command line>"), optind, -1);
+ res.end = res.start;
+ return res;
+}
+
+
+void
+getargs (int argc, char *argv[])
+{
+ int c;
+
+ while ((c = getopt_long (argc, argv, short_options, long_options, NULL))
+ != -1)
+ switch (c)
+ {
+ /* ASCII Sorting for short options (i.e., upper case then
+ lower case), and then long-only options. */
+
+ case 0:
+ /* Certain long options cause getopt_long to return 0. */
+ break;
+
+ case 'D': /* -DNAME[=VALUE]. */
+ case 'F': /* -FNAME[=VALUE]. */
+ {
+ char* name = optarg;
+ char* value = strchr (optarg, '=');
+ if (value)
+ *value++ = 0;
+ muscle_percent_define_insert (name, command_line_location (),
+ value ? value : "",
+ c == 'D' ? MUSCLE_PERCENT_DEFINE_D
+ : MUSCLE_PERCENT_DEFINE_F);
+ }
+ break;
+
+ case 'I':
+ include = AS_FILE_NAME (optarg);
+ break;
+
+ case 'L':
+ language_argmatch (optarg, command_line_prio,
+ command_line_location ());
+ break;
+
+ case 'S':
+ skeleton_arg (AS_FILE_NAME (optarg), command_line_prio,
+ command_line_location ());
+ break;
+
+ case 'T':
+ FLAGS_ARGMATCH (trace, optarg, trace_all);
+ break;
+
+ case 'V':
+ version ();
+ exit (EXIT_SUCCESS);
+
+ case 'W':
+ FLAGS_ARGMATCH (warnings, optarg, Wall);
+ break;
+
+ case 'b':
+ spec_file_prefix = AS_FILE_NAME (optarg);
+ break;
+
+ case 'd':
+ /* Here, the -d and --defines options are differentiated. */
+ defines_flag = true;
+ if (optarg)
+ {
+ free (spec_defines_file);
+ spec_defines_file = xstrdup (AS_FILE_NAME (optarg));
+ }
+ break;
+
+ case 'g':
+ graph_flag = true;
+ if (optarg)
+ {
+ free (spec_graph_file);
+ spec_graph_file = xstrdup (AS_FILE_NAME (optarg));
+ }
+ break;
+
+ case 'h':
+ usage (EXIT_SUCCESS);
+
+ case 'k':
+ token_table_flag = true;
+ break;
+
+ case 'l':
+ no_lines_flag = true;
+ break;
+
+ case 'o':
+ spec_outfile = AS_FILE_NAME (optarg);
+ break;
+
+ case 'p':
+ spec_name_prefix = optarg;
+ break;
+
+ case 'r':
+ FLAGS_ARGMATCH (report, optarg, report_all);
+ break;
+
+ case 't':
+ muscle_percent_define_insert ("parse.trace",
+ command_line_location (), "",
+ MUSCLE_PERCENT_DEFINE_D);
+ break;
+
+ case 'v':
+ report_flag |= report_states;
+ break;
+
+ case 'x':
+ xml_flag = true;
+ if (optarg)
+ {
+ free (spec_xml_file);
+ spec_xml_file = xstrdup (AS_FILE_NAME (optarg));
+ }
+ break;
+
+ case 'y':
+ yacc_flag = true;
+ break;
+
+ case LOCATIONS_OPTION:
+ muscle_percent_define_ensure ("locations",
+ command_line_location (), true);
+ break;
+
+ case PRINT_LOCALEDIR_OPTION:
+ printf ("%s\n", LOCALEDIR);
+ exit (EXIT_SUCCESS);
+
+ case PRINT_DATADIR_OPTION:
+ printf ("%s\n", pkgdatadir ());
+ exit (EXIT_SUCCESS);
+
+ case REPORT_FILE_OPTION:
+ free (spec_verbose_file);
+ spec_verbose_file = xstrdup (AS_FILE_NAME (optarg));
+ break;
+
+ default:
+ usage (EXIT_FAILURE);
+ }
+
+ if (argc - optind != 1)