Home | History | Annotate | Download | only in src
      1 /* Parse command line arguments for Bison.
      2 
      3    Copyright (C) 1984, 1986, 1989, 1992, 2000, 2001, 2002, 2003, 2004,
      4    2005, 2006 Free Software Foundation, Inc.
      5 
      6    This file is part of Bison, the GNU Compiler Compiler.
      7 
      8    Bison is free software; you can redistribute it and/or modify it
      9    under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 2, or (at your option)
     11    any later version.
     12 
     13    Bison is distributed in the hope that it will be useful, but
     14    WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16    General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with Bison; see the file COPYING.  If not, write to the Free
     20    Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     21    02110-1301, USA.  */
     22 
     23 #include <config.h>
     24 #include "system.h"
     25 
     26 #include <argmatch.h>
     27 #include <error.h>
     28 
     29 /* Hack to get <getopt.h> to declare getopt with a prototype.  */
     30 #if lint && ! defined __GNU_LIBRARY__
     31 # define __GNU_LIBRARY__
     32 # define HACK_FOR___GNU_LIBRARY___PROTOTYPE 1
     33 #endif
     34 
     35 #include <getopt.h>
     36 
     37 #ifdef HACK_FOR___GNU_LIBRARY___PROTOTYPE
     38 # undef __GNU_LIBRARY__
     39 # undef HACK_FOR___GNU_LIBRARY___PROTOTYPE
     40 #endif
     41 
     42 #include "complain.h"
     43 #include "files.h"
     44 #include "getargs.h"
     45 #include "uniqstr.h"
     46 
     47 bool debug_flag;
     48 bool defines_flag;
     49 bool graph_flag;
     50 bool locations_flag;
     51 bool no_lines_flag;
     52 bool no_parser_flag;
     53 bool token_table_flag;
     54 bool yacc_flag;	/* for -y */
     55 
     56 bool error_verbose = false;
     57 
     58 bool nondeterministic_parser = false;
     59 bool glr_parser = false;
     60 bool pure_parser = false;
     61 
     62 int report_flag = report_none;
     63 int trace_flag = trace_none;
     64 
     65 const char *skeleton = NULL;
     66 const char *include = NULL;
     67 
     68 extern char *program_name;
     69 
     70 
     71 /*---------------------.
     72 | --trace's handling.  |
     73 `---------------------*/
     74 
     75 static const char * const trace_args[] =
     76 {
     77   /* In a series of synonyms, present the most meaningful first, so
     78      that argmatch_valid be more readable.  */
     79   "none       - no report",
     80   "scan       - grammar scanner traces",
     81   "parse      - grammar parser traces",
     82   "automaton  - contruction of the automaton",
     83   "bitsets    - use of bitsets",
     84   "grammar    - reading, reducing of the grammar",
     85   "resource   - memory consumption (where available)",
     86   "sets       - grammar sets: firsts, nullable etc.",
     87   "tools      - m4 invocation",
     88   "m4         - m4 traces",
     89   "skeleton   - skeleton postprocessing",
     90   "time       - time consumption",
     91   "all        - all of the above",
     92   0
     93 };
     94 
     95 static const int trace_types[] =
     96 {
     97   trace_none,
     98   trace_scan,
     99   trace_parse,
    100   trace_automaton,
    101   trace_bitsets,
    102   trace_grammar,
    103   trace_resource,
    104   trace_sets,
    105   trace_tools,
    106   trace_m4,
    107   trace_skeleton,
    108   trace_time,
    109   trace_all
    110 };
    111 
    112 ARGMATCH_VERIFY (trace_args, trace_types);
    113 
    114 static void
    115 trace_argmatch (char *args)
    116 {
    117   if (args)
    118     {
    119       args = strtok (args, ",");
    120       do
    121 	{
    122 	  int trace = XARGMATCH ("--trace", args,
    123 				 trace_args, trace_types);
    124 	  if (trace == trace_none)
    125 	    trace_flag = trace_none;
    126 	  else
    127 	    trace_flag |= trace;
    128 	}
    129       while ((args = strtok (NULL, ",")));
    130     }
    131   else
    132     trace_flag = trace_all;
    133 }
    134 
    135 
    136 /*----------------------.
    137 | --report's handling.  |
    138 `----------------------*/
    139 
    140 static const char * const report_args[] =
    141 {
    142   /* In a series of synonyms, present the most meaningful first, so
    143      that argmatch_valid be more readable.  */
    144   "none",
    145   "state", "states",
    146   "itemset", "itemsets",
    147   "look-ahead", "lookahead", "lookaheads",
    148   "solved",
    149   "all",
    150   0
    151 };
    152 
    153 static const int report_types[] =
    154 {
    155   report_none,
    156   report_states, report_states,
    157   report_states | report_itemsets, report_states | report_itemsets,
    158   report_states | report_look_ahead_tokens,
    159   report_states | report_look_ahead_tokens,
    160   report_states | report_look_ahead_tokens,
    161   report_states | report_solved_conflicts,
    162   report_all
    163 };
    164 
    165 ARGMATCH_VERIFY (report_args, report_types);
    166 
    167 static void
    168 report_argmatch (char *args)
    169 {
    170   args = strtok (args, ",");
    171   do
    172     {
    173       int report = XARGMATCH ("--report", args,
    174 			      report_args, report_types);
    175       if (report == report_none)
    176 	report_flag = report_none;
    177       else
    178 	report_flag |= report;
    179     }
    180   while ((args = strtok (NULL, ",")));
    181 }
    182 
    183 
    184 /*-------------------------------------------.
    185 | Display the help message and exit STATUS.  |
    186 `-------------------------------------------*/
    187 
    188 static void usage (int) ATTRIBUTE_NORETURN;
    189 
    190 static void
    191 usage (int status)
    192 {
    193   if (status != 0)
    194     fprintf (stderr, _("Try `%s --help' for more information.\n"),
    195 	     program_name);
    196   else
    197     {
    198       /* Some efforts were made to ease the translators' task, please
    199 	 continue.  */
    200       fputs (_("\
    201 GNU bison generates parsers for LALR(1) grammars.\n"), stdout);
    202       putc ('\n', stdout);
    203 
    204       fprintf (stdout, _("\
    205 Usage: %s [OPTION]... FILE\n"), program_name);
    206       putc ('\n', stdout);
    207 
    208       fputs (_("\
    209 If a long option shows an argument as mandatory, then it is mandatory\n\
    210 for the equivalent short option also.  Similarly for optional arguments.\n"),
    211 	     stdout);
    212       putc ('\n', stdout);
    213 
    214       fputs (_("\
    215 Operation modes:\n\
    216   -h, --help                 display this help and exit\n\
    217   -V, --version              output version information and exit\n\
    218       --print-localedir      output directory containing locale-dependent data\n\
    219   -y, --yacc                 emulate POSIX yacc\n"), stdout);
    220       putc ('\n', stdout);
    221 
    222       fputs (_("\
    223 Parser:\n\
    224   -S, --skeleton=FILE        specify the skeleton to use\n\
    225   -t, --debug                instrument the parser for debugging\n\
    226       --locations            enable locations computation\n\
    227   -p, --name-prefix=PREFIX   prepend PREFIX to the external symbols\n\
    228   -l, --no-lines             don't generate `#line' directives\n\
    229   -n, --no-parser            generate the tables only\n\
    230   -k, --token-table          include a table of token names\n\
    231 "), stdout);
    232       putc ('\n', stdout);
    233 
    234       fputs (_("\
    235 Output:\n\
    236   -d, --defines              also produce a header file\n\
    237   -r, --report=THINGS        also produce details on the automaton\n\
    238   -v, --verbose              same as `--report=state'\n\
    239   -b, --file-prefix=PREFIX   specify a PREFIX for output files\n\
    240   -o, --output=FILE          leave output to FILE\n\
    241   -g, --graph                also produce a VCG description of the automaton\n\
    242 "), stdout);
    243       putc ('\n', stdout);
    244 
    245       fputs (_("\
    246 THINGS is a list of comma separated words that can include:\n\
    247   `state'        describe the states\n\
    248   `itemset'      complete the core item sets with their closure\n\
    249   `look-ahead'   explicitly associate look-ahead tokens to items\n\
    250   `solved'       describe shift/reduce conflicts solving\n\
    251   `all'          include all the above information\n\
    252   `none'         disable the report\n\
    253 "), stdout);
    254       putc ('\n', stdout);
    255 
    256       fputs (_("\
    257 Report bugs to <bug-bison (at) gnu.org>.\n"), stdout);
    258     }
    259 
    260   exit (status);
    261 }
    262 
    263 
    264 /*------------------------------.
    265 | Display the version message.  |
    266 `------------------------------*/
    267 
    268 static void
    269 version (void)
    270 {
    271   /* Some efforts were made to ease the translators' task, please
    272      continue.  */
    273   printf (_("bison (GNU Bison) %s"), VERSION);
    274   putc ('\n', stdout);
    275   fputs (_("Written by Robert Corbett and Richard Stallman.\n"), stdout);
    276   putc ('\n', stdout);
    277 
    278   fprintf (stdout,
    279 	   _("Copyright (C) %d Free Software Foundation, Inc.\n"), 2006);
    280 
    281   fputs (_("\
    282 This is free software; see the source for copying conditions.  There is NO\n\
    283 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
    284 "),
    285 	 stdout);
    286 }
    287 
    288 
    289 /*----------------------.
    290 | Process the options.  |
    291 `----------------------*/
    292 
    293 /* Shorts options.  */
    294 static char const short_options[] = "yvegdhr:ltknVo:b:p:S:T::";
    295 
    296 /* Values for long options that do not have single-letter equivalents.  */
    297 enum
    298 {
    299   LOCATIONS_OPTION = CHAR_MAX + 1,
    300   PRINT_LOCALEDIR_OPTION
    301 };
    302 
    303 static struct option const long_options[] =
    304 {
    305   /* Operation modes. */
    306   { "help",            no_argument,	0,   'h' },
    307   { "version",         no_argument,	0,   'V' },
    308   { "print-localedir", no_argument,	0,   PRINT_LOCALEDIR_OPTION },
    309 
    310   /* Parser. */
    311   { "name-prefix",   required_argument,	  0,   'p' },
    312   { "include",       required_argument,   0,   'I' },
    313 
    314   /* Output. */
    315   { "file-prefix", required_argument,	0,   'b' },
    316   { "output",	   required_argument,	0,   'o' },
    317   { "output-file", required_argument,	0,   'o' },
    318   { "graph",	   optional_argument,	0,   'g' },
    319   { "report",	   required_argument,   0,   'r' },
    320   { "verbose",	   no_argument,	        0,   'v' },
    321 
    322   /* Hidden. */
    323   { "trace",         optional_argument,   0,     'T' },
    324 
    325   /* Output.  */
    326   { "defines",     optional_argument,   0,   'd' },
    327 
    328   /* Operation modes.  */
    329   { "fixed-output-files", no_argument,  0,   'y' },
    330   { "yacc",	          no_argument,  0,   'y' },
    331 
    332   /* Parser.  */
    333   { "debug",	      no_argument,               0,   't' },
    334   { "locations",      no_argument,		 0, LOCATIONS_OPTION },
    335   { "no-lines",       no_argument,               0,   'l' },
    336   { "no-parser",      no_argument,               0,   'n' },
    337   { "raw",            no_argument,               0,     0 },
    338   { "skeleton",       required_argument,         0,   'S' },
    339   { "token-table",    no_argument,               0,   'k' },
    340 
    341   {0, 0, 0, 0}
    342 };
    343 
    344 /* Under DOS, there is no difference on the case.  This can be
    345    troublesome when looking for `.tab' etc.  */
    346 #ifdef MSDOS
    347 # define AS_FILE_NAME(File) (strlwr (File), (File))
    348 #else
    349 # define AS_FILE_NAME(File) (File)
    350 #endif
    351 
    352 void
    353 getargs (int argc, char *argv[])
    354 {
    355   int c;
    356 
    357   while ((c = getopt_long (argc, argv, short_options, long_options, NULL))
    358 	 != -1)
    359     switch (c)
    360       {
    361       case 0:
    362 	/* Certain long options cause getopt_long to return 0.  */
    363 	break;
    364 
    365       case 'y':
    366 	yacc_flag = true;
    367 	break;
    368 
    369       case 'h':
    370 	usage (EXIT_SUCCESS);
    371 
    372       case 'V':
    373 	version ();
    374 	exit (EXIT_SUCCESS);
    375 
    376       case PRINT_LOCALEDIR_OPTION:
    377 	printf ("%s\n", LOCALEDIR);
    378 	exit (EXIT_SUCCESS);
    379 
    380       case 'g':
    381 	/* Here, the -g and --graph=FILE options are differentiated.  */
    382 	graph_flag = true;
    383 	if (optarg)
    384 	  spec_graph_file = AS_FILE_NAME (optarg);
    385 	break;
    386 
    387       case 'v':
    388 	report_flag |= report_states;
    389 	break;
    390 
    391       case 'S':
    392 	skeleton = AS_FILE_NAME (optarg);
    393 	break;
    394 
    395       case 'I':
    396 	include = AS_FILE_NAME (optarg);
    397 	break;
    398 
    399       case 'd':
    400 	/* Here, the -d and --defines options are differentiated.  */
    401 	defines_flag = true;
    402 	if (optarg)
    403 	  spec_defines_file = AS_FILE_NAME (optarg);
    404 	break;
    405 
    406       case 'l':
    407 	no_lines_flag = true;
    408 	break;
    409 
    410       case LOCATIONS_OPTION:
    411 	locations_flag = true;
    412 	break;
    413 
    414       case 'k':
    415 	token_table_flag = true;
    416 	break;
    417 
    418       case 'n':
    419 	no_parser_flag = true;
    420 	break;
    421 
    422       case 't':
    423 	debug_flag = true;
    424 	break;
    425 
    426       case 'o':
    427 	spec_outfile = AS_FILE_NAME (optarg);
    428 	break;
    429 
    430       case 'b':
    431 	spec_file_prefix = AS_FILE_NAME (optarg);
    432 	break;
    433 
    434       case 'p':
    435 	spec_name_prefix = optarg;
    436 	break;
    437 
    438       case 'r':
    439 	report_argmatch (optarg);
    440 	break;
    441 
    442       case 'T':
    443 	trace_argmatch (optarg);
    444 	break;
    445 
    446       default:
    447 	usage (EXIT_FAILURE);
    448       }
    449 
    450   if (argc - optind != 1)
    451     {
    452       if (argc - optind < 1)
    453 	error (0, 0, _("missing operand after `%s'"), argv[argc - 1]);
    454       else
    455 	error (0, 0, _("extra operand `%s'"), argv[optind + 1]);
    456       usage (EXIT_FAILURE);
    457     }
    458 
    459   current_file = grammar_file = uniqstr_new (argv[optind]);
    460 }
    461