1 : /*
2 : * OpenBIOS - free your system!
3 : * ( FCode tokenizer )
4 : *
5 : * toke.c - main tokenizer loop and parameter parsing.
6 : *
7 : * This program is part of a free implementation of the IEEE 1275-1994
8 : * Standard for Boot (Initialization Configuration) Firmware.
9 : *
10 : * Copyright (C) 2001-2006 by Stefan Reinauer <stepan@openbios.org>
11 : *
12 : * This program is free software; you can redistribute it and/or modify
13 : * it under the terms of the GNU General Public License as published by
14 : * the Free Software Foundation; version 2 of the License.
15 : *
16 : * This program is distributed in the hope that it will be useful,
17 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : * GNU General Public License for more details.
20 : *
21 : * You should have received a copy of the GNU General Public License
22 : * along with this program; if not, write to the Free Software
23 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
24 : *
25 : */
26 :
27 : /* **************************************************************************
28 : * Modifications made in 2005 by IBM Corporation
29 : * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
30 : * Modifications Author: David L. Paktor dlpaktor@us.ibm.com
31 : **************************************************************************** */
32 :
33 : #include <stdio.h>
34 : #include <stdlib.h>
35 : #include <string.h>
36 : #include <unistd.h>
37 :
38 : #ifdef __GLIBC__
39 : #define _GNU_SOURCE
40 : #include <getopt.h>
41 : #endif
42 :
43 : #include "types.h"
44 : #include "toke.h"
45 : #include "stream.h"
46 : #include "stack.h"
47 : #include "emit.h"
48 :
49 : #define TOKE_VERSION "1.0.0"
50 :
51 : #include "vocabfuncts.h"
52 : #include "scanner.h"
53 : #include "errhandler.h"
54 : #include "usersymbols.h"
55 : #include "clflags.h"
56 : #include "tracesyms.h"
57 :
58 : #define CORE_COPYR "(C) Copyright 2001-2006 Stefan Reinauer.\n" \
59 : "(C) Copyright 2006 coresystems GmbH <info@coresystems.de>"
60 : #define IBM_COPYR "(C) Copyright 2005 IBM Corporation. All Rights Reserved."
61 :
62 : /* Temporary hack during development... See DATE_STAMP line below... */
63 : #ifdef DEVEL
64 : #include "date_stamp.h"
65 : #endif /* DEVEL */
66 :
67 : /* **************************************************************************
68 : *
69 : * Global Variables Exported:
70 : * verbose If true, enable optional messages.
71 : * noerrors If true, create binary even if error(s) encountered.
72 : * fload_list If true, create an "FLoad-List" file
73 : * dependency_list If true, create a "Dependencies-List" file
74 : *
75 : **************************************************************************** */
76 :
77 : bool verbose = FALSE;
78 : bool noerrors = FALSE;
79 : bool fload_list = FALSE;
80 : bool dependency_list = FALSE;
81 :
82 : /* **************************************************************************
83 : *
84 : * Internal Static Variables
85 : * outputname Name of output file supplied on command-line
86 : * with the optional -o switch.
87 : * Internal System Variable
88 : * optind Index into argv vector of first param after options,
89 : * from which input file names will be taken.
90 : *
91 : **************************************************************************** */
92 :
93 : static char *outputname = NULL;
94 :
95 : /* **************************************************************************
96 : *
97 : * Print the copyright message.
98 : *
99 : **************************************************************************** */
100 : static void print_copyright(void)
101 161 : {
102 161 : printf( "Welcome to toke - OpenBIOS tokenizer v" TOKE_VERSION "\n"
103 : CORE_COPYR "\n" IBM_COPYR "\n"
104 : "This program is free software; you may redistribute it "
105 : "under the terms of\nthe GNU General Public License. This "
106 : "program has absolutely no warranty.\n\n");
107 : #ifdef DEVEL
108 : /* Temporary hack during development... */
109 : printf( "\tTokenizer Compiled " DATE_STAMP "\n" );
110 : #endif /* DEVEL */
111 :
112 161 : }
113 :
114 : /* **************************************************************************
115 : *
116 : * Function name: usage
117 : * Synopsis: Print convenient usage-help message
118 : *
119 : **************************************************************************** */
120 :
121 : static void usage(char *name)
122 2 : {
123 2 : printf("usage: %s [-v] [-i] [-l] [-P] [-o target] <[-d name[=value]]> "
124 : "<[-f [no]flagname]> <[-I dir-path]> "
125 : "<[-T symbol]> <forth-file>\n\n",name);
126 2 : printf(" -v|--verbose print Advisory messages\n");
127 2 : printf(" -i|--ignore-errors don't suppress output after errors\n");
128 2 : printf(" -l|--load-list create list of FLoaded file names\n");
129 2 : printf(" -P|--dependencies create dePendency-list file\n");
130 2 : printf(" -o|--output-name send output to filename given\n");
131 2 : printf(" -d|--define create user-defined symbol\n");
132 2 : printf(" -f|--flag set (or clear) Special-Feature flag\n");
133 2 : printf(" -I|--Include add a directory to the Include-List\n");
134 2 : printf(" -T|--Trace add a symbol to the Trace List\n");
135 2 : printf(" -h|--help print this help message\n\n");
136 2 : printf(" -f|--flag help Help for Special-Feature flags\n");
137 2 : }
138 :
139 : /* **************************************************************************
140 : *
141 : * Function name: get_args
142 : * Synopsis: Parse the Command-Line option switches
143 : *
144 : * Inputs:
145 : * Parameters: NONE
146 : * Global Variables:
147 : * argc Counter of command-line arguments
148 : * argv Vector pointing to command-line arguments
149 : * Command-Line Items: The entire command-line will be parsed
150 : *
151 : * Outputs:
152 : * Returned Value: NONE
153 : * Global Variables:
154 : * verbose set by "-v" switch
155 : * noerrors set by "-i" switch
156 : * fload_list set by "-l" switch
157 : * dependency_list set by "-P" switch
158 : * Internal Static Variables
159 : * outputname set by "-o" switch
160 : * Internal System Variable
161 : * optind Index into argv vector of the position
162 : * from which to take input file names.
163 : * Printout:
164 : * (Copyright was already printed by the main body as a
165 : * matter of course, rather than here depending on
166 : * the Verbose flag, because getopt() prints its
167 : * own error messages and we want to be sure to show
168 : * the Copyright notice before any error messages.)
169 : * Rules for Usage and Flags-list or Flags-help display:
170 : * Usage message on Help-Request or error.
171 : * Ask for usage help, get Usage plus list of Flag Names.
172 : * Ask for Flags-help alone, get Flags-help (names plus
173 : * explanations)
174 : * Ask for usage help and for Flags-help, get Usage plus
175 : * Flags-help, without redundant list of Flag Names.
176 : * Any help-request, exit Zero
177 : * Error in Option switches, or missing input-file name,
178 : * get error-description plus Usage
179 : * Error in Flag Names, get list of Flag Names.
180 : * Any error, exit One.
181 : * Behavior:
182 : * Exit (non-failure) after printing "Help" message
183 : *
184 : * Error Detection: Exit with failure status on:
185 : * Unknown Option switches or Flag Names
186 : * Missing input file name
187 : *
188 : * Process Explanation:
189 : * The following switches are recognized:
190 : * v
191 : * h
192 : * ?
193 : * i
194 : * I
195 : * l
196 : * P
197 : * o
198 : * d
199 : * f
200 : * T
201 : * The conditions they set remain in effect through
202 : * the entire program run.
203 : *
204 : * Revision History:
205 : * Updated Fri, 15 Jul 2005 by David L. Paktor
206 : * Don't bail on first invalid option.
207 : * Flags to control special features
208 : * Usage messages for "special-feature" flags
209 : * Updated Mon, 18 Jul 2005 by David L. Paktor
210 : * Fine-tune Usage and Flags-list or Flags-help display.
211 : * Updated Sun, 27 Nov 2005 by David L. Paktor
212 : * Add FLoad-List flag
213 : * Updated Wed, 29 Nov 2005 by David L. Paktor
214 : * Make getopt() case-insensitive
215 : * Updated Fri, 17 Mar 2006 by David L. O'Paktor
216 : * Make getopt() case-sensitive again,
217 : * add include-list support and dePendency-list switch
218 : *
219 : * Extraneous Remarks:
220 : * We were originally thinking about defining various classes
221 : * of "Warning" Messages and (somehow) controlling their
222 : * display, but now that we have "special-feature" flags
223 : * that control the generation of specific messages, that
224 : * step has become unnecessary...
225 : *
226 : **************************************************************************** */
227 :
228 : static void get_args( int argc, char **argv )
229 161 : {
230 161 : const char *optstring="vhilPo:d:f:I:T:?";
231 : int c;
232 161 : int argindx = 0;
233 161 : bool inval_opt = FALSE;
234 161 : bool help_mssg = FALSE;
235 161 : bool cl_flag_error = FALSE;
236 :
237 : while (1) {
238 : #ifdef __GLIBC__
239 700 : int option_index = 0;
240 : static struct option long_options[] = {
241 : { "verbose", 0, 0, 'v' },
242 : { "help", 0, 0, 'h' },
243 : { "ignore-errors", 0, 0, 'i' },
244 : { "load-list", 0, 0, 'l' },
245 : { "dependencies", 0, 0, 'P' },
246 : { "output-name", 1, 0, 'o' },
247 : { "define", 1, 0, 'd' },
248 : { "flag", 1, 0, 'f' },
249 : { "Include", 1, 0, 'I' },
250 : { "Trace", 1, 0, 'T' },
251 : { 0, 0, 0, 0 }
252 : };
253 :
254 700 : c = getopt_long (argc, argv, optstring,
255 : long_options, &option_index);
256 : #else
257 : c = getopt (argc, argv, optstring);
258 : #endif
259 700 : if (c == -1)
260 161 : break;
261 :
262 539 : argindx++;
263 539 : switch (c) {
264 : case 'v':
265 159 : verbose=TRUE;
266 159 : break;
267 : case 'o':
268 59 : outputname = optarg;
269 59 : break;
270 : case 'i':
271 79 : noerrors = TRUE;
272 79 : break;
273 : case 'l':
274 60 : fload_list = TRUE;
275 60 : break;
276 : case 'P':
277 2 : dependency_list = TRUE;
278 2 : break;
279 : case 'd':
280 : {
281 29 : char *user_symb = optarg;
282 29 : add_user_symbol(user_symb);
283 : }
284 29 : break;
285 : case 'f':
286 66 : cl_flag_error = set_cl_flag(optarg, FALSE) ;
287 66 : break;
288 : case 'I':
289 : {
290 75 : char *incl_list_elem = optarg;
291 75 : add_to_include_list(incl_list_elem);
292 : }
293 75 : break;
294 : case 'T':
295 9 : add_to_trace_list(optarg);
296 9 : break;
297 : case '?':
298 : /* Distinguish between a '?' from the user
299 : * and one getopt() returned
300 : */
301 0 : if ( argv[argindx][1] != '?' )
302 : {
303 0 : inval_opt = TRUE;
304 0 : break;
305 : }
306 : case 'h':
307 : case 'H':
308 1 : help_mssg = TRUE;
309 1 : break;
310 : default:
311 : /* This is never executed
312 : * because getopt() prints the
313 : * "unknown option -- X"
314 : * message and returns a '?'
315 : */
316 0 : printf ("%s: unknown options.\n",argv[0]);
317 0 : usage(argv[0]);
318 0 : exit( 1 );
319 : }
320 : }
321 :
322 161 : if ( help_mssg )
323 : {
324 1 : usage(argv[0]);
325 1 : if ( ! clflag_help )
326 : {
327 1 : list_cl_flag_names();
328 : }
329 : }
330 161 : if ( clflag_help ) cl_flags_help();
331 161 : if ( help_mssg || clflag_help )
332 : {
333 5 : exit( 0 );
334 : }
335 :
336 156 : if ( inval_opt ) printf ("unknown options.\n");
337 156 : if (optind >= argc) printf ("Input file name missing.\n");
338 156 : if ( inval_opt || (optind >= argc) )
339 : {
340 1 : usage(argv[0]);
341 : }
342 156 : if ( cl_flag_error ) list_cl_flag_names();
343 :
344 156 : if ( inval_opt || (optind >= argc) || cl_flag_error )
345 : {
346 2 : exit( 1);
347 : }
348 :
349 154 : if (verbose)
350 : {
351 153 : list_user_symbols();
352 153 : list_cl_flag_settings();
353 153 : display_include_list();
354 : }
355 154 : save_cl_flags();
356 154 : }
357 :
358 : /* **************************************************************************
359 : *
360 : * Main body of program. Return 0 for success, 1 for failure.
361 : *
362 : * Still to be done:
363 : * Devise a syntax to allow the command-line to specify multiple
364 : * input files together with an output file name for each.
365 : * Currently, the syntax allows only one output file name to be
366 : * specified; when multiple input file names are specified,
367 : * the specification of an output file name is disallowed,
368 : * and only the default output file names are permitted.
369 : * While this works around the immediate problem, a more
370 : * elegant solution could be devised...
371 : *
372 : **************************************************************************** */
373 :
374 : int main(int argc, char **argv)
375 161 : {
376 161 : int retval = 0;
377 :
378 161 : print_copyright();
379 161 : get_args( argc, argv );
380 :
381 154 : init_stack();
382 154 : init_dictionary();
383 :
384 154 : init_scanner();
385 :
386 154 : if ( outputname != NULL )
387 : {
388 54 : if ( argc > optind + 1 )
389 : {
390 : /* Multiple input file names w/ single output file name */
391 : /* Work-around */
392 0 : printf( "Cannot specify single output file name "
393 : "with multiple input file names.\n"
394 : "Please either remove output-file-name specification,\n"
395 : "or use multiple commands.\n");
396 0 : exit ( -2 );
397 : }
398 : }
399 :
400 170 : for ( ; optind < argc ; optind++ )
401 : {
402 : bool stream_ok ;
403 :
404 171 : printf("\nTokenizing %s ", argv[optind]);
405 171 : init_error_handler();
406 171 : stream_ok = init_stream( argv[optind]);
407 171 : if ( stream_ok )
408 : {
409 165 : init_output(argv[optind], outputname);
410 :
411 165 : init_scan_state();
412 :
413 165 : reset_vocabs();
414 165 : reset_cl_flags();
415 :
416 165 : tokenize();
417 164 : finish_headers();
418 :
419 164 : close_stream( NULL);
420 164 : if ( close_output() ) retval = 1;
421 : }
422 : }
423 :
424 153 : exit_scanner();
425 153 : return retval;
426 : }
427 :
|