summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c762
1 files changed, 0 insertions, 762 deletions
diff --git a/src/main.c b/src/main.c
deleted file mode 100644
index 4b897e34..00000000
--- a/src/main.c
+++ /dev/null
@@ -1,762 +0,0 @@
-/* GNU m4 -- A simple macro processor
-
- Copyright (C) 1989-1994, 1999-2000, 2003-2010, 2013-2014, 2017 Free
- Software Foundation, Inc.
-
- This file is part of GNU M4.
-
- GNU M4 is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- GNU M4 is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#include <locale.h>
-
-#include "m4.h"
-
-#include "closein.h"
-#include "configmake.h"
-#include "getopt.h"
-#include "propername.h"
-#include "quotearg.h"
-#include "version-etc.h"
-#include "xstrtol.h"
-
-#define AUTHORS \
- proper_name_utf8 ("Rene' Seindal", "Ren\xc3\xa9 Seindal"), \
- proper_name ("Gary V. Vaughan"), \
- proper_name ("Eric Blake")
-
-typedef struct deferred
-{
- struct deferred *next;
- int code; /* deferred optchar */
- const char *value;
-} deferred;
-
-
-/* Error handling functions. */
-
-#ifdef USE_STACKOVF
-
-/* Tell user stack overflowed and abort. */
-static void
-stackovf_handler (void)
-{
- /* FIXME - calling gettext and error inside a signal handler is dangerous,
- since these functions invoke functions that are not signal-safe. We
- are sort of justified by the fact that we will exit and never return,
- but this should really be fixed. */
- error (EXIT_FAILURE, 0, _("stack overflow (infinite define recursion?)"));
-}
-
-#endif /* USE_STACKOVF */
-
-
-
-/* Print a usage message and exit with STATUS. */
-static void
-usage (int status)
-{
- if (status != EXIT_SUCCESS)
- xfprintf (stderr, _("Try `%s --help' for more information.\n"),
- m4_get_program_name ());
- else
- {
- xprintf (_("Usage: %s [OPTION]... [FILE]...\n"), m4_get_program_name ());
- fputs (_("\
-Process macros in FILEs.\n\
-If no FILE or if FILE is `-', standard input is read. If no FILE, and both\n\
-standard input and standard error are terminals, -i is implied.\n\
-"), stdout);
- puts ("");
- fputs (_("\
-Mandatory or optional arguments to long options are mandatory or optional\n\
-for short options too.\n\
-\n\
-Operation modes:\n\
- --help display this help and exit\n\
- --version output version information and exit\n\
-"), stdout);
- fputs (_("\
- -b, --batch buffer output, process interrupts\n\
- -c, --discard-comments do not copy comments to the output\n\
- -E, --fatal-warnings once: warnings become errors, twice: stop\n\
- execution at first error\n\
- -i, --interactive unbuffer output, ignore interrupts\n\
- -P, --prefix-builtins force a `m4_' prefix to all builtins\n\
- -Q, --quiet, --silent suppress some warnings for builtins\n\
- -r, --regexp-syntax[=SPEC] set default regexp syntax to SPEC [GNU_M4]\n\
- --safer disable potentially unsafe builtins\n\
- -W, --warnings enable all warnings\n\
-"), stdout);
- puts ("");
- fputs (_("\
-SPEC is any one of:\n\
- AWK, BASIC, BSD_M4, ED, EMACS, EXTENDED, GNU_AWK, GNU_EGREP, GNU_M4,\n\
- GREP, POSIX_AWK, POSIX_EGREP, MINIMAL, MINIMAL_BASIC, SED.\n\
-"), stdout);
- puts ("");
- fputs (_("\
-Preprocessor features:\n\
- -B, --prepend-include=DIR add DIR to include path before `.'\n\
- -D, --define=NAME[=VALUE] define NAME as having VALUE, or empty\n\
- --import-environment import all environment variables as macros\n\
- -I, --include=DIR add DIR to include path after `.'\n\
-"), stdout);
- fputs (_("\
- --popdef=NAME popdef NAME\n\
- -p, --pushdef=NAME[=VALUE] pushdef NAME as having VALUE, or empty\n\
- -s, --synclines short for --syncoutput=1\n\
- --syncoutput[=STATE] set generation of `#line NUM \"FILE\"' lines\n\
- to STATE (0=off, 1=on, default 0)\n\
- -U, --undefine=NAME undefine NAME\n\
-"), stdout);
- puts ("");
- fputs (_("\
-Limits control:\n\
- -g, --gnu override -G to re-enable GNU extensions\n\
- -G, --traditional, --posix suppress all GNU extensions\n\
- -L, --nesting-limit=NUMBER change artificial nesting limit [1024]\n\
-"), stdout);
- puts ("");
- fputs (_("\
-Frozen state files:\n\
- -F, --freeze-state=FILE produce a frozen state on FILE at end\n\
- -R, --reload-state=FILE reload a frozen state from FILE at start\n\
-"), stdout);
- puts ("");
- fputs (_("\
-Debugging:\n\
- -d, --debug[=[-|+]FLAGS], --debugmode[=[-|+]FLAGS]\n\
- set debug level (no FLAGS implies `+adeq')\n\
- --debugfile[=FILE] redirect debug and trace output to FILE\n\
- (default stderr, discard if empty string)\n\
- -l, --debuglen=NUM restrict macro tracing size\n\
- -t, --trace=NAME, --traceon=NAME\n\
- trace NAME when it is defined\n\
- --traceoff=NAME no longer trace NAME\n\
-"), stdout);
- puts ("");
- fputs (_("\
-FLAGS is any of:\n\
- a show actual arguments in trace\n\
- c show collection line in trace\n\
- d warn when dereferencing undefined macros (default on unless -E)\n\
- e show expansion in trace\n\
- f include current input file name in trace and debug\n\
- i show changes in input files in debug\n\
- l include current input line number in trace and debug\n\
-"), stdout);
- fputs (_("\
- m show module information in trace, debug, and dumpdef\n\
- o output dumpdef to stderr rather than debug file\n\
- p show results of path searches in debug\n\
- q quote values in dumpdef and trace, useful with a or e\n\
- s show full stack of pushdef values in dumpdef\n\
- t trace all macro calls, regardless of per-macro traceon state\n\
- x include unique macro call id in trace, useful with c\n\
- V shorthand for all of the above flags\n\
-"), stdout);
- puts ("");
- fputs (_("\
-If defined, the environment variable `M4PATH' is a colon-separated list\n\
-of directories included after any specified by `-I' or `-B'. The\n\
-environment variable `POSIXLY_CORRECT' implies -G -Q; otherwise GNU\n\
-extensions are enabled by default.\n\
-"), stdout);
- puts ("");
- fputs (_("\
-Exit status is 0 for success, 1 for failure, 63 for frozen file version\n\
-mismatch, or whatever value was passed to the m4exit macro.\n\
-"), stdout);
- emit_bug_reporting_address ();
- }
- exit (status);
-}
-
-/* For long options that have no equivalent short option, use a
- non-character as a pseudo short option, starting with CHAR_MAX + 1. */
-enum
-{
- ARGLENGTH_OPTION = CHAR_MAX + 1, /* not quite -l, because of message */
- DEBUGFILE_OPTION, /* no short opt */
- ERROR_OUTPUT_OPTION, /* not quite -o, because of message */
- HASHSIZE_OPTION, /* not quite -H, because of message */
- IMPORT_ENVIRONMENT_OPTION, /* no short opt */
- POPDEF_OPTION, /* no short opt */
- PREPEND_INCLUDE_OPTION, /* not quite -B, because of message */
- SAFER_OPTION, /* -S still has old no-op semantics */
- SYNCOUTPUT_OPTION, /* not quite -s, because of opt arg */
- TRACEOFF_OPTION, /* no short opt */
- WORD_REGEXP_OPTION, /* deprecated, used to be -W */
-
- HELP_OPTION, /* no short opt */
- VERSION_OPTION /* no short opt */
-};
-
-/* Decode options and launch execution. */
-static const struct option long_options[] =
-{
- {"batch", no_argument, NULL, 'b'},
- {"debug", optional_argument, NULL, 'd'},
- {"debuglen", required_argument, NULL, 'l'},
- {"debugmode", optional_argument, NULL, 'd'},
- {"define", required_argument, NULL, 'D'},
- {"discard-comments", no_argument, NULL, 'c'},
- {"fatal-warnings", no_argument, NULL, 'E'},
- {"freeze-state", required_argument, NULL, 'F'},
- {"gnu", no_argument, NULL, 'g'},
- {"include", required_argument, NULL, 'I'},
- {"interactive", no_argument, NULL, 'i'},
- {"nesting-limit", required_argument, NULL, 'L'},
- {"posix", no_argument, NULL, 'G'},
- {"prefix-builtins", no_argument, NULL, 'P'},
- {"pushdef", required_argument, NULL, 'p'},
- {"quiet", no_argument, NULL, 'Q'},
- {"regexp-syntax", optional_argument, NULL, 'r'},
- {"reload-state", required_argument, NULL, 'R'},
- {"silent", no_argument, NULL, 'Q'},
- {"synclines", no_argument, NULL, 's'},
- {"trace", required_argument, NULL, 't'},
- {"traceon", required_argument, NULL, 't'},
- {"traditional", no_argument, NULL, 'G'},
- {"undefine", required_argument, NULL, 'U'},
- {"warnings", no_argument, NULL, 'W'},
-
- {"arglength", required_argument, NULL, ARGLENGTH_OPTION},
- {"debugfile", optional_argument, NULL, DEBUGFILE_OPTION},
- {"hashsize", required_argument, NULL, HASHSIZE_OPTION},
- {"error-output", required_argument, NULL, ERROR_OUTPUT_OPTION},
- {"import-environment", no_argument, NULL, IMPORT_ENVIRONMENT_OPTION},
- {"popdef", required_argument, NULL, POPDEF_OPTION},
- {"prepend-include", required_argument, NULL, PREPEND_INCLUDE_OPTION},
- {"safer", no_argument, NULL, SAFER_OPTION},
- {"syncoutput", optional_argument, NULL, SYNCOUTPUT_OPTION},
- {"traceoff", required_argument, NULL, TRACEOFF_OPTION},
- {"word-regexp", required_argument, NULL, WORD_REGEXP_OPTION},
-
- {"help", no_argument, NULL, HELP_OPTION},
- {"version", no_argument, NULL, VERSION_OPTION},
-
- { NULL, 0, NULL, 0 },
-};
-
-/* POSIX requires only -D, -U, and -s; and says that the first two
- must be recognized when interspersed with file names. Traditional
- behavior also handles -s between files. Starting OPTSTRING with
- '-' forces getopt_long to hand back file names as arguments to opt
- '\1', rather than reordering the command line. */
-#define OPTSTRING "-B:D:EF:GH:I:L:PQR:S:T:U:Wbcd::egil:o:p:r::st:"
-
-/* For determining whether to be interactive. */
-enum interactive_choice
-{
- INTERACTIVE_UNKNOWN, /* Still processing arguments, no -b or -i yet */
- INTERACTIVE_YES, /* -i specified last */
- INTERACTIVE_NO /* -b specified last */
-};
-
-/* Convert OPT to size_t, reporting an error using long option index
- OI or short option character OPTCHAR if it does not fit. */
-static size_t
-size_opt (char const *opt, int oi, int optchar)
-{
- unsigned long int size;
- strtol_error status = xstrtoul (opt, NULL, 10, &size, "kKmMgGtTPEZY0");
- if (SIZE_MAX < size && status == LONGINT_OK)
- status = LONGINT_OVERFLOW;
- if (status != LONGINT_OK)
- xstrtol_fatal (status, oi, optchar, long_options, opt);
- return size;
-}
-
-/* Process a command line file NAME. */
-static bool
-process_file (m4 *context, const char *name)
-{
- bool new_input = true;
-
- if (STREQ (name, "-"))
- /* TRANSLATORS: This is a short name for `standard input', used
- when a command line file was given as `-'. */
- m4_push_file (context, stdin, _("stdin"), false);
- else
- new_input = m4_load_filename (context, NULL, name, NULL, false);
-
- if (new_input)
- m4_macro_expand_input (context);
-
- return new_input;
-}
-
-
-/* Main entry point. Parse arguments, load modules, then parse input. */
-int
-main (int argc, char *const *argv, char *const *envp)
-{
- deferred *head = NULL; /* head of deferred argument list */
- deferred *tail = NULL;
- deferred *defn;
- size_t size; /* for parsing numeric option arguments */
-
- bool import_environment = false; /* true to import environment */
- bool seen_file = false;
- const char *debugfile = NULL;
- const char *frozen_file_to_read = NULL;
- const char *frozen_file_to_write = NULL;
- enum interactive_choice interactive = INTERACTIVE_UNKNOWN;
-
- m4 *context;
-
- int exit_status;
-
- /* Initialize gnulib error module. */
- m4_set_program_name (argv[0]);
- atexit (close_stdin);
-
- setlocale (LC_ALL, "");
-#ifdef ENABLE_NLS
- textdomain (PACKAGE);
-#endif
-
- context = m4_create ();
-
-#ifdef USE_STACKOVF
- setup_stackovf_trap (argv, envp, stackovf_handler);
-#endif
-
- if (getenv ("POSIXLY_CORRECT"))
- {
- m4_set_posixly_correct_opt (context, true);
- m4_set_suppress_warnings_opt (context, true);
- }
- set_quoting_style (NULL, escape_quoting_style);
- set_char_quoting (NULL, ':', 1);
-
- /* First, we decode the arguments, to size up tables and stuff.
- Avoid lasting side effects; for example 'm4 --debugfile=oops
- --help' must not create the file `oops'. */
- while (1)
- {
- int oi = -1;
- int optchar = getopt_long (argc, (char **) argv, OPTSTRING,
- long_options, &oi);
- if (optchar == -1)
- break;
-
- switch (optchar)
- {
- default:
- usage (EXIT_FAILURE);
-
- case 'H':
- case HASHSIZE_OPTION:
- /* -H was supported in 1.4.x, but is a no-op now. FIXME -
- remove support for -H after 2.0. */
- error (0, 0, _("warning: `%s' is deprecated"),
- optchar == 'H' ? "-H" : "--hashsize");
- break;
-
- case 'S':
- case 'T':
- /* Compatibility junk: options that other implementations
- support, but which we ignore as no-ops and don't list in
- --help. */
- error (0, 0, _("warning: `-%c' is deprecated"),
- optchar);
- break;
-
- case WORD_REGEXP_OPTION:
- /* Supported in 1.4.x as -W, but no longer present. */
- error (0, 0, _("warning: `%s' is deprecated"), "--word-regexp");
- break;
-
- case 's':
- optchar = SYNCOUTPUT_OPTION;
- optarg = "1";
- /* fall through */
- case 'D':
- case 'U':
- case 'p':
- case 'r':
- case 't':
- case POPDEF_OPTION:
- case SYNCOUTPUT_OPTION:
- case TRACEOFF_OPTION:
- defer:
- /* Arguments that cannot be handled until later are accumulated. */
-
- defn = (deferred *) xmalloc (sizeof *defn);
- defn->code = optchar;
- defn->value = optarg;
- defn->next = NULL;
-
- if (head == NULL)
- head = defn;
- else
- tail->next = defn;
- tail = defn;
- break;
-
- case '\1':
- seen_file = true;
- goto defer;
-
- case 'B':
- /* In 1.4.x, -B<num> was a no-op option for compatibility with
- Solaris m4. Warn if optarg is all numeric. FIXME -
- silence this warning after 2.0. */
- if (isdigit (to_uchar (*optarg)))
- {
- char *end;
- errno = 0;
- strtol (optarg, &end, 10);
- if (*end == '\0' && errno == 0)
- error (0, 0, _("warning: recommend using `-B ./%s' instead"),
- optarg);
- }
- /* fall through */
- case PREPEND_INCLUDE_OPTION:
- m4_add_include_directory (context, optarg, true);
- break;
-
- case 'E':
- m4_debug_decode (context, "-d", SIZE_MAX);
- if (m4_get_fatal_warnings_opt (context))
- m4_set_warnings_exit_opt (context, true);
- else
- m4_set_fatal_warnings_opt (context, true);
- break;
-
- case 'F':
- frozen_file_to_write = optarg;
- break;
-
- case 'G':
- m4_set_posixly_correct_opt (context, true);
- break;
-
- case 'I':
- m4_add_include_directory (context, optarg, false);
- break;
-
- case 'L':
- size = size_opt (optarg, oi, optchar);
- if (!size)
- size = SIZE_MAX;
- m4_set_nesting_limit_opt (context, size);
- break;
-
- case 'P':
- m4_set_prefix_builtins_opt (context, true);
- break;
-
- case 'Q':
- m4_set_suppress_warnings_opt (context, true);
- break;
-
- case 'R':
- frozen_file_to_read = optarg;
- break;
-
- case 'W':
- /* FIXME - should W take an optional argument, to allow -Wall,
- -Wnone, -Werror, -Wcategory, -Wno-category? If so, then have
- -W == -Wall. */
- m4_set_suppress_warnings_opt (context, false);
- break;
-
- case 'b':
- interactive = INTERACTIVE_NO;
- break;
-
- case 'c':
- m4_set_discard_comments_opt (context, true);
- break;
-
- case 'd':
- /* Staggered handling of 'd', since -dm is useful prior to
- first file and prior to reloading, but other -d must also
- have effect between files. */
- if (seen_file || frozen_file_to_read)
- goto defer;
- if (m4_debug_decode (context, optarg, SIZE_MAX) < 0)
- error (0, 0, _("bad debug flags: %s"),
- quotearg_style (locale_quoting_style, optarg));
- break;
-
- case 'e':
- error (0, 0, _("warning: `%s' is deprecated, use `%s' instead"),
- "-e", "-i");
- /* fall through */
- case 'i':
- interactive = INTERACTIVE_YES;
- break;
-
- case 'g':
- m4_set_posixly_correct_opt (context, false);
- break;
-
- case ARGLENGTH_OPTION:
- error (0, 0, _("warning: `%s' is deprecated, use `%s' instead"),
- "--arglength", "--debuglen");
- /* fall through */
- case 'l':
- size = size_opt (optarg, oi, optchar);
- if (!size)
- size = SIZE_MAX;
- m4_set_max_debug_arg_length_opt (context, size);
- break;
-
- case DEBUGFILE_OPTION:
- /* Staggered handling of '--debugfile', since it is useful
- prior to first file and prior to reloading, but other
- uses must also have effect between files. */
- if (seen_file || frozen_file_to_read)
- goto defer;
- debugfile = optarg;
- break;
-
- case 'o':
- case ERROR_OUTPUT_OPTION:
- /* FIXME: -o is inconsistent with other tools' use of
- -o/--output for creating an output file instead of using
- stdout, and --error-output is misnamed since it does not
- affect error messages to stderr. Change the meaning of -o
- after 2.1. */
- error (0, 0, _("warning: `%s' is deprecated, use `%s' instead"),
- optchar == 'o' ? "-o" : "--error-output", "--debugfile");
- /* Don't call m4_debug_set_output here, as it has side effects. */
- debugfile = optarg;
- break;
-
- case IMPORT_ENVIRONMENT_OPTION:
- import_environment = true;
- break;
-
- case SAFER_OPTION:
- m4_set_safer_opt (context, true);
- break;
-
- case VERSION_OPTION:
- version_etc (stdout, PACKAGE, PACKAGE_NAME, VERSION, AUTHORS, NULL);
- exit (EXIT_SUCCESS);
- break;
-
- case HELP_OPTION:
- usage (EXIT_SUCCESS);
- break;
- }
- }
-
- /* Do the basic initializations. */
- if (debugfile && !m4_debug_set_output (context, NULL, debugfile))
- m4_error (context, 0, errno, NULL, _("cannot set debug file %s"),
- quotearg_style (locale_quoting_style, debugfile));
- m4_input_init (context);
- m4_output_init (context);
-
- if (frozen_file_to_read)
- reload_frozen_state (context, frozen_file_to_read);
- else
- {
- m4_module_load (context, "m4", NULL);
- if (m4_get_posixly_correct_opt (context))
- m4_module_load (context, "traditional", NULL);
- else
- m4_module_load (context, "gnu", NULL);
- }
-
- /* Import environment variables as macros. The definition are
- prepended to the macro definition list, so -U can override
- environment variables. */
-
- if (import_environment)
- {
- char *const *env;
-
- for (env = envp; *env != NULL; env++)
- {
- defn = (deferred *) xmalloc (sizeof *defn);
- defn->code = 'D';
- defn->value = *env;
- defn->next = head;
- head = defn;
- }
- }
-
- /* Handle deferred command line macro definitions. Must come after
- initialization of the symbol table. */
- defn = head;
- while (defn != NULL)
- {
- deferred *next;
- const char *arg = defn->value;
-
- switch (defn->code)
- {
- case 'D':
- case 'p':
- {
- m4_symbol_value *value = m4_symbol_value_create ();
-
- const char *str = strchr (arg, '=');
- size_t len = str ? str - arg : strlen (arg);
-
- m4_set_symbol_value_text (value, xstrdup (str ? str + 1 : ""),
- str ? strlen (str + 1) : 0, 0);
-
- if (defn->code == 'D')
- m4_symbol_define (M4SYMTAB, arg, len, value);
- else
- m4_symbol_pushdef (M4SYMTAB, arg, len, value);
- }
- break;
-
- case 'U':
- m4_symbol_delete (M4SYMTAB, arg, strlen (arg));
- break;
-
- case 'd':
- if (m4_debug_decode (context, arg, SIZE_MAX) < 0)
- error (0, 0, _("bad debug flags: %s"),
- quotearg_style (locale_quoting_style, arg));
- break;
-
- case 'r':
- m4_set_regexp_syntax_opt (context, m4_regexp_syntax_encode (arg));
- if (m4_get_regexp_syntax_opt (context) < 0)
- m4_error (context, EXIT_FAILURE, 0, NULL,
- _("bad syntax-spec: %s"),
- quotearg_style (locale_quoting_style, arg));
- break;
-
- case 't':
- m4_set_symbol_name_traced (M4SYMTAB, arg, strlen (arg), true);
- break;
-
- case '\1':
- if (process_file (context, arg))
- seen_file = true;
- break;
-
- case DEBUGFILE_OPTION:
- if (!m4_debug_set_output (context, NULL, arg))
- m4_error (context, 0, errno, NULL, _("cannot set debug file %s"),
- quotearg_style (locale_quoting_style,
- arg ? arg : _("stderr")));
- break;
-
- case POPDEF_OPTION:
- {
- size_t len = strlen (arg);
- if (m4_symbol_lookup (M4SYMTAB, arg, len))
- m4_symbol_popdef (M4SYMTAB, arg, len);
- }
- break;
-
- case SYNCOUTPUT_OPTION:
- {
- bool previous = m4_get_syncoutput_opt (context);
- m4_call_info info = {0};
- info.name = "--syncoutput";
- info.name_len = strlen (info.name);
- m4_set_syncoutput_opt (context,
- m4_parse_truth_arg (context, &info, arg,
- SIZE_MAX, previous));
- }
- break;
-
- case TRACEOFF_OPTION:
- m4_set_symbol_name_traced (M4SYMTAB, arg, strlen (arg), false);
- break;
-
- default:
- assert (!"INTERNAL ERROR: bad code in deferred arguments");
- abort ();
- }
-
- next = defn->next;
- free (defn);
- defn = next;
- }
-
-
- /* Interactive if specified, or if no input files and stdin and
- stderr are terminals, to match sh behavior. Interactive mode
- means unbuffered output, and interrupts ignored. */
-
- m4_set_interactive_opt (context, (interactive == INTERACTIVE_YES
- || (interactive == INTERACTIVE_UNKNOWN
- && optind == argc && !seen_file
- && isatty (STDIN_FILENO)
- && isatty (STDERR_FILENO))));
- if (m4_get_interactive_opt (context))
- {
- signal (SIGINT, SIG_IGN);
- setbuf (stdout, NULL);
- }
- else
- signal (SIGPIPE, SIG_DFL);
-
-
- /* Handle remaining input files. Each file is pushed on the input,
- and the input read. */
-
- if (optind == argc && !seen_file)
- process_file (context, "-");
- else
- for (; optind < argc; optind++)
- process_file (context, argv[optind]);
-
- /* Now handle wrapup text.
- FIXME - when -F is in effect, should wrapped text be frozen? */
- while (m4_pop_wrapup (context))
- m4_macro_expand_input (context);
-
- if (frozen_file_to_write)
- produce_frozen_state (context, frozen_file_to_write);
- else
- {
- m4_make_diversion (context, 0);
- m4_undivert_all (context);
- }
-
- /* The remaining cleanup functions systematically free all of the
- memory we still have pointers to. By definition, if there is
- anything left when we're done: it was caused by a memory leak.
- Strictly, we don't need to do this, but it makes leak detection
- a whole lot easier! */
-
- m4_output_exit ();
- m4_input_exit ();
-
- /* Change debug stream back to stderr, to force flushing the debug
- stream and detect any errors it might have encountered. The
- three standard streams are closed by close_stdin. */
- m4_debug_set_output (context, NULL, NULL);
-
- exit_status = m4_get_exit_status (context);
- m4_delete (context);
-
- m4_hash_exit ();
- quotearg_free ();
-
-#ifdef USE_STACKOVF
- stackovf_exit ();
-#endif
-
- exit (exit_status);
-}