* Makefile.am (src_m4_SOURCES): Add version-etc-fsf.c.
[m4/ericb.git] / src / main.c
blob8ab6228d5cfba43a3d6e852c721362e3c61a4fe4
1 /* GNU m4 -- A simple macro processor
3 Copyright (C) 1989-1994, 1999, 2000, 2003, 2004, 2005
4 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA
22 #include "m4.h"
23 #include "m4private.h"
24 #include "getopt.h"
25 #include "version-etc.h"
26 #include "gnu/progname.h"
28 static void print_program_name_CB (void);
31 /* Name of frozen file to digest after initialization. */
32 const char *frozen_file_to_read = NULL;
34 /* Name of frozen file to produce near completion. */
35 const char *frozen_file_to_write = NULL;
37 /* If nonzero, display usage information and exit. */
38 static int show_help = 0;
40 /* If nonzero, print the version on standard output and exit. */
41 static int show_version = 0;
43 /* If nonzero, import the environment as macros. */
44 static int import_environment = 0;
46 typedef struct macro_definition
48 struct macro_definition *next;
49 int code; /* D, U or t */
50 const char *macro;
51 } macro_definition;
54 /* Error handling functions. */
56 /* Print program name, source file and line reference on standard
57 error, as a prefix for error messages. Flush standard output first. */
58 static void
59 print_program_name_CB (void)
61 int e = errno;
62 fflush (stdout);
63 fprintf (stderr, "%s: ", program_name);
64 if (m4_current_line != 0)
65 fprintf (stderr, "%s: %d: ", m4_current_file, m4_current_line);
66 errno = e;
70 #ifdef USE_STACKOVF
72 /* Tell user stack overflowed and abort. */
73 static void
74 stackovf_handler (void)
76 M4ERROR ((EXIT_FAILURE, 0,
77 _("Stack overflow. (Infinite define recursion?)")));
80 #endif /* USE_STACKOV */
84 /* Print a usage message and exit with STATUS. */
85 static void
86 usage (int status)
88 if (status != EXIT_SUCCESS)
89 fprintf (stderr, _("Try `%s --help' for more information.\n"),
90 program_name);
91 else
93 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
94 fputs (_("\
95 Mandatory or optional arguments to long options are mandatory or optional\n\
96 for short options too.\n\
97 \n\
98 Operation modes:\n\
99 --help display this help and exit\n\
100 --version output version information and exit\n\
101 -c, --discard-comments do not copy comments to the output\n\
102 -b, --batch buffer output, process interrupts\n\
103 -e, --interactive unbuffer output, ignore interrupts\n\
104 -E, --fatal-warnings stop execution after first warning\n\
105 -Q, --quiet, --silent suppress some warnings for builtins\n\
106 -P, --prefix-builtins force a `m4_' prefix to all builtins\n"),
107 stdout);
108 printf (_("\
110 Dynamic loading features:\n\
111 -M, --module-directory=DIRECTORY add DIRECTORY to the module search path\n\
112 -m, --load-module=MODULE load dynamic MODULE from %s\n"),
113 USER_MODULE_PATH_ENV);
114 fputs (_("\
116 Preprocessor features:\n\
117 -I, --include=DIRECTORY search this directory second for includes\n\
118 -D, --define=NAME[=VALUE] enter NAME has having VALUE, or empty\n\
119 -U, --undefine=NAME delete builtin NAME\n\
120 -s, --synclines generate `#line NO \"FILE\"' lines\n"),
121 stdout);
122 fputs (_("\
124 Limits control:\n\
125 -G, --traditional suppress all GNU extensions\n\
126 -L, --nesting-limit=NUMBER change artificial nesting limit\n"),
127 stdout);
128 fputs (_("\
130 Frozen state files:\n\
131 -F, --freeze-state=FILE produce a frozen state on FILE at end\n\
132 -R, --reload-state=FILE reload a frozen state from FILE at start\n"),
133 stdout);
134 fputs (_("\
136 Debugging:\n\
137 -d, --debug=[FLAGS] set debug level (no FLAGS implies `aeq')\n\
138 -t, --trace=NAME trace NAME when it will be defined\n\
139 -l, --arglength=NUM restrict macro tracing size\n\
140 -o, --error-output=FILE redirect debug and trace output\n"),
141 stdout);
142 fputs (_("\
144 FLAGS is any of:\n\
145 t trace for all macro calls, not only traceon'ed\n\
146 a show actual arguments\n\
147 e show expansion\n\
148 q quote values as necessary, with a or e flag\n\
149 c show before collect, after collect and after call\n\
150 x add a unique macro call id, useful with c flag\n\
151 f say current input file name\n\
152 l say current input line number\n\
153 p show results of path searches\n\
154 i show changes in input files\n\
155 V shorthand for all of the above flags\n"),
156 stdout);
157 fputs (_("\
159 If no FILE or if FILE is `-', standard input is read.\n"),
160 stdout);
162 fputs (_("\nReport bugs to <bug-m4@gnu.org>.\n"), stdout);
164 exit (status);
167 /* Decode options and launch execution. */
168 static const struct option long_options[] =
170 {"arglength", required_argument, NULL, 'l'},
171 {"batch", no_argument, NULL, 'b'},
172 {"debug", optional_argument, NULL, 'd'},
173 {"discard-comments", no_argument, NULL, 'c'},
174 {"diversions", required_argument, NULL, 'N'},
175 {"error-output", required_argument, NULL, 'o'},
176 {"fatal-warnings", no_argument, NULL, 'E'},
177 {"freeze-state", required_argument, NULL, 'F'},
178 {"hashsize", required_argument, NULL, 'H'},
179 {"include", required_argument, NULL, 'I'},
180 {"interactive", no_argument, NULL, 'e'},
181 {"load-module", required_argument, NULL, 'm'},
182 {"module-directory", required_argument, NULL, 'M'},
183 {"nesting-limit", required_argument, NULL, 'L'},
184 {"prefix-builtins", no_argument, NULL, 'P'},
185 {"quiet", no_argument, NULL, 'Q'},
186 {"reload-state", required_argument, NULL, 'R'},
187 {"silent", no_argument, NULL, 'Q'},
188 {"synclines", no_argument, NULL, 's'},
189 {"traditional", no_argument, NULL, 'G'},
190 {"word-regexp", required_argument, NULL, 'W'},
192 {"import-environment", no_argument, &import_environment, 1},
194 {"help", no_argument, &show_help, 1},
195 {"version", no_argument, &show_version, 1},
197 /* These are somewhat troublesome. */
198 { "define", required_argument, NULL, 'D' },
199 { "undefine", required_argument, NULL, 'U' },
200 { "trace", required_argument, NULL, 't' },
202 { 0, 0, 0, 0 },
205 #define OPTSTRING "B:D:EF:GH:I:L:M:N:PQR:S:T:U:bcd::el:m:o:st:"
208 main (int argc, char *const *argv, char *const *envp)
210 macro_definition *head; /* head of deferred argument list */
211 macro_definition *tail;
212 macro_definition *new;
213 int optchar; /* option character */
215 macro_definition *defines;
216 FILE *fp;
217 char *filename;
219 m4 *context;
221 int exit_status;
223 /* Initialise gnulib error module. */
224 set_program_name (argv[0]);
225 error_print_progname = print_program_name_CB;
227 setlocale (LC_ALL, "");
228 #ifdef ENABLE_NLS
229 textdomain(PACKAGE);
230 #endif
232 LTDL_SET_PRELOADED_SYMBOLS();
234 context = m4_create ();
236 m4__module_init (context);
238 #ifdef USE_STACKOVF
239 setup_stackovf_trap (argv, envp, stackovf_handler);
240 #endif
242 if (isatty (STDIN_FILENO))
243 m4_set_interactive_opt (context, true);
245 if (getenv ("POSIXLY_CORRECT"))
246 m4_set_posixly_correct_opt (context, true);
248 /* First, we decode the arguments, to size up tables and stuff. */
250 head = tail = NULL;
252 while (optchar = getopt_long (argc, argv, OPTSTRING, long_options, NULL),
253 optchar != EOF)
254 switch (optchar)
256 default:
257 usage (EXIT_FAILURE);
259 case 0:
260 break;
262 case 'B': /* compatibility junk */
263 case 'H':
264 case 'N':
265 case 'S':
266 case 'T':
267 break;
269 case 'D':
270 case 'U':
271 case 't':
272 case 'm':
273 /* Arguments that cannot be handled until later are accumulated. */
275 new = xmalloc (sizeof *new);
276 new->code = optchar;
277 new->macro = optarg;
278 new->next = NULL;
280 if (head == NULL)
281 head = new;
282 else
283 tail->next = new;
284 tail = new;
286 break;
288 case 'E':
289 m4_set_warning_status_opt (context, EXIT_FAILURE);
290 break;
292 case 'F':
293 frozen_file_to_write = optarg;
294 break;
296 case 'G':
297 m4_set_no_gnu_extensions_opt (context, true);
298 m4_set_posixly_correct_opt (context, true);
299 break;
301 case 'I':
302 m4_add_include_directory (context, optarg);
303 break;
305 case 'L':
306 m4_set_nesting_limit_opt (context, atoi (optarg));
307 break;
308 case 'M':
309 if (lt_dlinsertsearchdir (lt_dlgetsearchpath(), optarg) != 0)
311 const char *dlerr = lt_dlerror();
312 if (dlerr == NULL)
313 M4ERROR ((EXIT_FAILURE, 0,
314 _("failed to add search directory `%s'"),
315 optarg));
316 else
317 M4ERROR ((EXIT_FAILURE, 0,
318 _("failed to add search directory `%s': %s"),
319 optarg, dlerr));
321 break;
323 case 'P':
324 m4_set_prefix_builtins_opt (context, true);
325 break;
327 case 'Q':
328 m4_set_suppress_warnings_opt (context, true);
329 break;
331 case 'R':
332 frozen_file_to_read = optarg;
333 break;
335 case 'b':
336 m4_set_interactive_opt (context, false);
337 break;
339 case 'c':
340 m4_set_discard_comments_opt (context, true);
341 break;
343 case 'd':
344 m4_set_debug_level_opt (context, m4_debug_decode (context, optarg));
345 if (m4_get_debug_level_opt (context) < 0)
347 error (0, 0, _("Bad debug flags: `%s'"), optarg);
348 m4_set_debug_level_opt (context, 0);
350 break;
352 case 'e':
353 m4_set_interactive_opt (context, true);
354 break;
356 case 'l':
357 m4_set_max_debug_arg_length_opt (context, atoi (optarg));
358 if (m4_get_max_debug_arg_length_opt (context) <= 0)
359 m4_set_max_debug_arg_length_opt (context, 0);
360 break;
362 case 'o':
363 if (!m4_debug_set_output (context, optarg))
364 error (0, errno, "%s", optarg);
365 break;
367 case 's':
368 m4_set_sync_output_opt (context, true);
369 break;
372 if (show_version)
374 version_etc (stdout, NULL, "GNU " PACKAGE TIMESTAMP,
375 VERSION, "Rene' Seindal", "Gary V. Vaughan", NULL);
376 exit (EXIT_SUCCESS);
379 if (show_help)
380 usage (EXIT_SUCCESS);
382 /* Do the basic initialisations. */
384 m4_input_init ();
385 m4_output_init ();
386 m4_include_env_init (context);
388 if (frozen_file_to_read)
390 int ch;
392 /* Take care not to mix frozen state with startup state. */
393 for (ch = 256; --ch > 0;)
394 context->syntax->table[ch] = 0;
396 reload_frozen_state (context, frozen_file_to_read);
398 else
400 m4_module_load (context, "m4", 0);
401 if (m4_get_no_gnu_extensions_opt (context))
402 m4_module_load (context, "traditional", 0);
403 else
404 m4_module_load (context, "gnu", 0);
407 /* Import environment variables as macros. The definition are
408 preprended to the macro definition list, so -U can override
409 environment variables. */
411 if (import_environment)
413 char *const *env;
415 for (env = envp; *env != NULL; env++)
417 new = xmalloc (sizeof *new);
418 new->code = 'D';
419 new->macro = *env;
420 new->next = head;
421 head = new;
425 /* Handle deferred command line macro definitions. Must come after
426 initialisation of the symbol table. */
428 defines = head;
430 while (defines != NULL)
432 macro_definition *next;
433 char *macro_value;
435 switch (defines->code)
437 case 'D':
439 m4_symbol_value *value = m4_symbol_value_create ();
441 macro_value = strchr (defines->macro, '=');
442 if (macro_value == NULL)
443 macro_value = "";
444 else
445 *macro_value++ = '\0';
446 m4_set_symbol_value_text (value, xstrdup (macro_value));
448 m4_symbol_pushdef (M4SYMTAB, defines->macro, value);
450 break;
452 case 'U':
453 m4_symbol_delete (M4SYMTAB, defines->macro);
454 break;
456 case 't':
457 m4_set_symbol_name_traced (M4SYMTAB, defines->macro);
458 break;
460 case 'm':
461 m4_module_load (context, defines->macro, 0);
462 break;
464 default:
465 M4ERROR ((m4_get_warning_status_opt (context), 0,
466 "INTERNAL ERROR: Bad code in deferred arguments"));
467 abort ();
470 next = defines->next;
471 free (defines);
472 defines = next;
476 /* Interactive mode means unbuffered output, and interrupts ignored. */
478 if (m4_get_interactive_opt (context))
480 signal (SIGINT, SIG_IGN);
481 setbuf (stdout, (char *) NULL);
484 /* Handle the various input files. Each file is pushed on the input,
485 and the input read. Wrapup text is handled separately later. */
487 exit_status = EXIT_SUCCESS;
488 if (optind == argc)
490 m4_push_file (context, stdin, "stdin");
491 m4_macro_expand_input (context);
493 else
494 for (; optind < argc; optind++)
496 if (strcmp (argv[optind], "-") == 0)
497 m4_push_file (context, stdin, "stdin");
498 else
500 fp = m4_path_search (context, argv[optind], &filename);
501 if (fp == NULL)
503 error (0, errno, "%s", argv[optind]);
504 exit_status = EXIT_FAILURE;
505 continue;
507 else
509 m4_push_file (context, fp, filename);
510 free (filename);
513 m4_macro_expand_input (context);
516 /* Now handle wrapup text. */
518 while (m4_pop_wrapup ())
519 m4_macro_expand_input (context);
521 if (frozen_file_to_write)
522 produce_frozen_state (context, frozen_file_to_write);
523 else
525 m4_make_diversion (0);
526 m4_undivert_all ();
529 /* The remaining cleanup functions systematically free all of the
530 memory we still have pointers to. By definition, if there is
531 anything left when we're done: it was caused by a memory leak.
532 Strictly, we don't need to do this, but it makes leak detection
533 a whole lot easier! */
535 m4__module_exit (context);
536 m4_output_exit ();
537 m4_input_exit ();
539 m4_delete (context);
541 m4_hash_exit ();
543 #ifdef USE_STACKOVF
544 stackovf_exit ();
545 #endif
547 exit (exit_status);