• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
trace_argmatch(char * args)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
report_argmatch(char * args)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
usage(int status)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@gnu.org>.\n"), stdout);
258     }
259 
260   exit (status);
261 }
262 
263 
264 /*------------------------------.
265 | Display the version message.  |
266 `------------------------------*/
267 
268 static void
version(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
getargs(int argc,char * argv[])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