From 3e33a6b3b9b2529939136c34b1e88bd3ee87a172 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Wed, 21 May 2008 06:59:01 -0600 Subject: [PATCH] Stage 24a: Use full call context in error reporting. * m4/m4module.h (m4_error, m4_warn): Change parameter type. (m4_error_at_line, m4_warn_at_line): Delete. (m4_debug_set_output, m4_skip_line, m4_bad_argc, m4_numeric_arg) (m4_parse_truth_arg, m4_symbol_value_lookup): Adjust all clients. * m4/m4private.h (m4__next_token): Likewise. * m4/utility.c (m4_verror_at_line): Alter parameter, and use caller's location if caller is provided. (m4_error, m4_warn): Change parameter type. (m4_error_at_line, m4_warn_at_line): Delete. (m4_bad_argc, m4_numeric_arg, m4_parse_truth_arg) (m4_symbol_value_lookup): Adjust all callers. * m4/debug.c (set_debug_file, m4_debug_set_output): Likewise. * m4/input.c (m4_skip_line, m4__next_token): Likewise. * m4/macro.c (expand_argument, collect_arguments, m4_macro_call) (process_macro): Likewise. * modules/m4.h (m4_make_temp_func): Likewise. * modules/evalparse.c (m4_evaluate): Likewise. * modules/format.c (arg_int, arg_long, arg_double, format): Likewise. * modules/gnu.c (builtin, changeresyntax, changesyntax, debugfile) (debuglen, debugmode, esyscmd, indir, mkdtemp, patsubst, regexp) (renamesyms, syncoutput, regexp_compile, substitute) (regexp_substitute, m4_resyntax_encode_safe): Likewise. * modules/m4.c (define, undefine, pushdef, popdef, ifdef, ifelse) (m4_dump_symbols, defn, syscmd, incr, decr, divert, undivert, dnl) (include, maketemp, mkstemp, m4exit, traceon, traceoff, substr): Likewise. * modules/stdlib.c (setenv, getpwuid, srand): Likewise. * modules/time.c (ctime, gmtime, localtime, mktime, strftime): Likewise. * tests/options.at (--syncoutput): Add test for invalid command-line argument. Split xfailed portion... (--syncoutput and diversions): ...into new test. (unknown option): New test. * tests/freeze.at (reloading unknown builtin): Update expected output. Signed-off-by: Eric Blake --- ChangeLog | 43 +++++++++++++++++++++ m4/debug.c | 26 ++++++------- m4/input.c | 83 +++++++++++++++++++++++++---------------- m4/m4module.h | 26 ++++++------- m4/m4private.h | 3 +- m4/macro.c | 22 +++++------ m4/utility.c | 105 +++++++++++++++------------------------------------- modules/evalparse.c | 2 +- modules/format.c | 8 ++-- modules/gnu.c | 61 +++++++++++++++--------------- modules/m4.c | 89 +++++++++++++++++++++++--------------------- modules/m4.h | 2 +- modules/stdlib.c | 6 +-- modules/time.c | 10 ++--- src/main.c | 6 ++- tests/freeze.at | 2 +- tests/options.at | 24 ++++++++++++ 17 files changed, 278 insertions(+), 240 deletions(-) diff --git a/ChangeLog b/ChangeLog index 176c7113..0545f869 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,48 @@ 2008-06-02 Eric Blake + Stage 24a: Use full call context in error reporting. + Replace const char *macro_name with const m4_call_info *call, so + that the next patch can pass the length of macro_name with + embedded NUL. Simplifies handling of global state. + Memory impact: none. + Speed impact: none noticed. + * m4/m4module.h (m4_error, m4_warn): Change parameter type. + (m4_error_at_line, m4_warn_at_line): Delete. + (m4_debug_set_output, m4_skip_line, m4_bad_argc, m4_numeric_arg) + (m4_parse_truth_arg, m4_symbol_value_lookup): Adjust all clients. + * m4/m4private.h (m4__next_token): Likewise. + * m4/utility.c (m4_verror_at_line): Alter parameter, and use + caller's location if caller is provided. + (m4_error, m4_warn): Change parameter type. + (m4_error_at_line, m4_warn_at_line): Delete. + (m4_bad_argc, m4_numeric_arg, m4_parse_truth_arg) + (m4_symbol_value_lookup): Adjust all callers. + * m4/debug.c (set_debug_file, m4_debug_set_output): Likewise. + * m4/input.c (m4_skip_line, m4__next_token): Likewise. + * m4/macro.c (expand_argument, collect_arguments, m4_macro_call) + (process_macro): Likewise. + * modules/m4.h (m4_make_temp_func): Likewise. + * modules/evalparse.c (m4_evaluate): Likewise. + * modules/format.c (arg_int, arg_long, arg_double, format): + Likewise. + * modules/gnu.c (builtin, changeresyntax, changesyntax, debugfile) + (debuglen, debugmode, esyscmd, indir, mkdtemp, patsubst, regexp) + (renamesyms, syncoutput, regexp_compile, substitute) + (regexp_substitute, m4_resyntax_encode_safe): Likewise. + * modules/m4.c (define, undefine, pushdef, popdef, ifdef, ifelse) + (m4_dump_symbols, defn, syscmd, incr, decr, divert, undivert, dnl) + (include, maketemp, mkstemp, m4exit, traceon, traceoff, substr): + Likewise. + * modules/stdlib.c (setenv, getpwuid, srand): Likewise. + * modules/time.c (ctime, gmtime, localtime, mktime, strftime): + Likewise. + * tests/options.at (--syncoutput): Add test for invalid + command-line argument. Split xfailed portion... + (--syncoutput and diversions): ...into new test. + (unknown option): New test. + * tests/freeze.at (reloading unknown builtin): Update expected + output. + Adjust to recent gnulib change. * configure.ac (AB_INIT): Delete, now that gnulib does this. diff --git a/m4/debug.c b/m4/debug.c index e6c8ffb8..d7e7e834 100644 --- a/m4/debug.c +++ b/m4/debug.c @@ -1,6 +1,6 @@ /* GNU m4 -- A simple macro processor - Copyright (C) 1991, 1992, 1993, 1994, 2006, 2007 Free Software - Foundation, Inc. + Copyright (C) 1991, 1992, 1993, 1994, 2006, 2007, 2008 Free + Software Foundation, Inc. This file is part of GNU M4. @@ -26,7 +26,7 @@ #include "m4private.h" #include "close-stream.h" -static void set_debug_file (m4 *, const char *, FILE *); +static void set_debug_file (m4 *, const m4_call_info *, FILE *); @@ -131,9 +131,9 @@ m4_debug_decode (m4 *context, int previous, const char *opts) /* Change the debug output stream to FP. If the underlying file is the same as stdout, use stdout instead so that debug messages appear in the - correct relative position. Report errors on behalf of MACRO. */ + correct relative position. Report errors on behalf of CALLER. */ static void -set_debug_file (m4 *context, const char *macro, FILE *fp) +set_debug_file (m4 *context, const m4_call_info *caller, FILE *fp) { FILE *debug_file; struct stat stdout_stat, debug_stat; @@ -143,7 +143,7 @@ set_debug_file (m4 *context, const char *macro, FILE *fp) debug_file = m4_get_debug_file (context); if (debug_file != NULL && debug_file != stderr && debug_file != stdout && close_stream (debug_file) != 0) - m4_error (context, 0, errno, macro, _("error writing to debug stream")); + m4_error (context, 0, errno, caller, _("error writing to debug stream")); debug_file = fp; m4_set_debug_file (context, fp); @@ -162,7 +162,7 @@ set_debug_file (m4 *context, const char *macro, FILE *fp) && stdout_stat.st_ino != 0) { if (debug_file != stderr && close_stream (debug_file) != 0) - m4_error (context, 0, errno, macro, + m4_error (context, 0, errno, caller, _("error writing to debug stream")); m4_set_debug_file (context, stdout); } @@ -172,18 +172,18 @@ set_debug_file (m4 *context, const char *macro, FILE *fp) /* Change the debug output to file NAME. If NAME is NULL, debug output is reverted to stderr, and if empty debug output is discarded. Return true iff the output stream was changed. Report - errors on behalf of MACRO. */ + errors on behalf of CALLER. */ bool -m4_debug_set_output (m4 *context, const char *macro, const char *name) +m4_debug_set_output (m4 *context, const m4_call_info *caller, const char *name) { FILE *fp; assert (context); if (name == NULL) - set_debug_file (context, macro, stderr); + set_debug_file (context, caller, stderr); else if (*name == '\0') - set_debug_file (context, macro, NULL); + set_debug_file (context, caller, NULL); else { fp = fopen (name, "a"); @@ -191,9 +191,9 @@ m4_debug_set_output (m4 *context, const char *macro, const char *name) return false; if (set_cloexec_flag (fileno (fp), true) != 0) - m4_warn (context, errno, macro, + m4_warn (context, errno, caller, _("cannot protect debug file across forks")); - set_debug_file (context, macro, fp); + set_debug_file (context, caller, fp); } return true; } diff --git a/m4/input.c b/m4/input.c index a021e70a..d2a508e5 100644 --- a/m4/input.c +++ b/m4/input.c @@ -1334,30 +1334,18 @@ unget_input (int ch) } /* skip_line () simply discards all immediately following characters, - up to the first newline. It is only used from m4_dnl (). NAME is - the spelling of argv[0], for use in any warning message. */ + up to the first newline. It is only used from m4_dnl (). Report + errors on behalf of CALLER. */ void -m4_skip_line (m4 *context, const char *name) +m4_skip_line (m4 *context, const m4_call_info *caller) { int ch; - const char *file = m4_get_current_file (context); - int line = m4_get_current_line (context); while ((ch = next_char (context, false, false, false)) != CHAR_EOF && ch != '\n') ; if (ch == CHAR_EOF) - /* current_file changed; use the previous value we cached. */ - m4_warn_at_line (context, 0, file, line, name, - _("end of file treated as newline")); - /* On the rare occasion that dnl crosses include file boundaries - (either the input file did not end in a newline, or changesyntax - was used), calling next_char can update current_file and - current_line, and that update will be undone as we return to - expand_macro. This tells next_char () to restore the location. */ - if (file != m4_get_current_file (context) - || line != m4_get_current_line (context)) - input_change = true; + m4_warn (context, 0, caller, _("end of file treated as newline")); } @@ -1521,13 +1509,12 @@ m4_input_exit (void) m4__next_token () is called. */ m4__token_type m4__next_token (m4 *context, m4_symbol_value *token, int *line, - m4_obstack *obs, bool allow_argv, const char *caller) + m4_obstack *obs, bool allow_argv, const m4_call_info *caller) { int ch; int quote_level; m4__token_type type; - const char *file; - int dummy; + const char *file = NULL; size_t len; /* The obstack where token data is stored. Generally token_stack, for tokens where argument collection might not use the literal @@ -1536,8 +1523,6 @@ m4__next_token (m4 *context, m4_symbol_value *token, int *line, m4_obstack *obs_safe = &token_stack; assert (next == NULL); - if (!line) - line = &dummy; memset (token, '\0', sizeof *token); do { obstack_free (&token_stack, token_bottom); @@ -1545,6 +1530,11 @@ m4__next_token (m4 *context, m4_symbol_value *token, int *line, /* Must consume an input character. */ ch = next_char (context, false, allow_argv && m4__quote_age (M4SYNTAX), false); + if (line) + { + *line = m4_get_current_line (context); + file = m4_get_current_file (context); + } if (ch == CHAR_EOF) /* EOF */ { #ifdef DEBUG_INPUT @@ -1570,9 +1560,6 @@ m4__next_token (m4 *context, m4_symbol_value *token, int *line, return M4_TOKEN_ARGV; } - file = m4_get_current_file (context); - *line = m4_get_current_line (context); - if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_ESCAPE)) { /* ESCAPED WORD */ obstack_1grow (&token_stack, ch); @@ -1607,8 +1594,16 @@ m4__next_token (m4 *context, m4_symbol_value *token, int *line, ch = next_char (context, obs && m4__quote_age (M4SYNTAX), false, false); if (ch == CHAR_EOF) - m4_error_at_line (context, EXIT_FAILURE, 0, file, *line, caller, - _("end of file in string")); + { + if (!caller) + { + assert (line); + m4_set_current_file (context, file); + m4_set_current_line (context, *line); + } + m4_error (context, EXIT_FAILURE, 0, caller, + _("end of file in string")); + } if (ch == CHAR_BUILTIN) init_builtin_token (context, obs, obs ? token : NULL); else if (ch == CHAR_QUOTE) @@ -1640,8 +1635,16 @@ m4__next_token (m4 *context, m4_symbol_value *token, int *line, { ch = next_char (context, false, false, false); if (ch == CHAR_EOF) - m4_error_at_line (context, EXIT_FAILURE, 0, file, *line, caller, - _("end of file in string")); + { + if (!caller) + { + assert (line); + m4_set_current_file (context, file); + m4_set_current_line (context, *line); + } + m4_error (context, EXIT_FAILURE, 0, caller, + _("end of file in string")); + } if (ch == CHAR_BUILTIN) init_builtin_token (context, obs, obs ? token : NULL); else if (MATCH (context, ch, context->syntax->quote.str2, true)) @@ -1670,8 +1673,16 @@ m4__next_token (m4 *context, m4_symbol_value *token, int *line, { ch = next_char (context, false, false, false); if (ch == CHAR_EOF) - m4_error_at_line (context, EXIT_FAILURE, 0, file, *line, caller, - _("end of file in comment")); + { + if (!caller) + { + assert (line); + m4_set_current_file (context, file); + m4_set_current_line (context, *line); + } + m4_error (context, EXIT_FAILURE, 0, caller, + _("end of file in comment")); + } if (ch == CHAR_BUILTIN) { init_builtin_token (context, NULL, NULL); @@ -1699,8 +1710,16 @@ m4__next_token (m4 *context, m4_symbol_value *token, int *line, { ch = next_char (context, false, false, false); if (ch == CHAR_EOF) - m4_error_at_line (context, EXIT_FAILURE, 0, file, *line, caller, - _("end of file in comment")); + { + if (!caller) + { + assert (line); + m4_set_current_file (context, file); + m4_set_current_line (context, *line); + } + m4_error (context, EXIT_FAILURE, 0, caller, + _("end of file in comment")); + } if (ch == CHAR_BUILTIN) { init_builtin_token (context, NULL, NULL); diff --git a/m4/m4module.h b/m4/m4module.h index 96b76eae..fb404ea2 100644 --- a/m4/m4module.h +++ b/m4/m4module.h @@ -159,24 +159,19 @@ struct m4_string_pair `m4_macro_args *argv' are in scope. */ #define M4ARGLEN(i) m4_arg_len (context, argv, i) -extern bool m4_bad_argc (m4 *, int, const char *, size_t, size_t, +extern bool m4_bad_argc (m4 *, int, const m4_call_info *, size_t, + size_t, bool); +extern bool m4_numeric_arg (m4 *, const m4_call_info *, const char *, + int *); +extern bool m4_parse_truth_arg (m4 *, const m4_call_info *, const char *, bool); -extern bool m4_numeric_arg (m4 *, const char *, const char *, int *); -extern bool m4_parse_truth_arg (m4 *, const char *, const char *, bool); -extern m4_symbol *m4_symbol_value_lookup (m4 *, const char *, - m4_macro_args *, size_t, bool); +extern m4_symbol *m4_symbol_value_lookup (m4 *, m4_macro_args *, size_t, bool); /* Error handling. */ -extern void m4_error (m4 *, int, int, const char *, const char *, ...) +extern void m4_error (m4 *, int, int, const m4_call_info *, const char *, ...) M4_GNUC_PRINTF (5, 6); -extern void m4_error_at_line (m4 *, int, int, const char *, int, - const char *, const char *, ...) - M4_GNUC_PRINTF (7, 8); -extern void m4_warn (m4 *, int, const char *, const char *, ...) +extern void m4_warn (m4 *, int, const m4_call_info *, const char *, ...) M4_GNUC_PRINTF (4, 5); -extern void m4_warn_at_line (m4 *, int, const char *, int, const char *, - const char *, ...) - M4_GNUC_PRINTF (6, 7); extern const char * m4_get_program_name (void); extern void m4_set_program_name (const char *); @@ -409,7 +404,8 @@ enum { #define m4_is_debug_bit(C,B) ((m4_get_debug_level_opt (C) & (B)) != 0) extern int m4_debug_decode (m4 *, int, const char *); -extern bool m4_debug_set_output (m4 *, const char *, const char *); +extern bool m4_debug_set_output (m4 *, const m4_call_info *, + const char *); extern void m4_debug_message_prefix (m4 *); extern void m4_debug_message (m4 *, int, const char *, ...) M4_GNUC_PRINTF (3, 4); @@ -491,7 +487,7 @@ extern int m4_set_syntax (m4_syntax_table*, char, char, const char*); extern void m4_input_init (m4 *context); extern void m4_input_exit (void); -extern void m4_skip_line (m4 *context, const char *); +extern void m4_skip_line (m4 *context, const m4_call_info *); /* push back input */ diff --git a/m4/m4private.h b/m4/m4private.h index 526a0ef5..c092016c 100644 --- a/m4/m4private.h +++ b/m4/m4private.h @@ -564,7 +564,8 @@ extern bool m4__push_symbol (m4 *, m4_symbol_value *, size_t, extern m4_obstack *m4__push_wrapup_init (m4 *, m4__symbol_chain ***); extern void m4__push_wrapup_finish (void); extern m4__token_type m4__next_token (m4 *, m4_symbol_value *, int *, - m4_obstack *, bool, const char *); + m4_obstack *, bool, + const m4_call_info *); extern bool m4__next_token_is_open (m4 *); /* Fast macro versions of macro argv accessor functions, diff --git a/m4/macro.c b/m4/macro.c index 1e88299c..43c3ad8f 100644 --- a/m4/macro.c +++ b/m4/macro.c @@ -128,7 +128,7 @@ static void expand_macro (m4 *, const char *, size_t, m4_symbol *); static bool expand_token (m4 *, m4_obstack *, m4__token_type, m4_symbol_value *, int, bool); static bool expand_argument (m4 *, m4_obstack *, m4_symbol_value *, - const char *); + const m4_call_info *); static void process_macro (m4 *, m4_symbol_value *, m4_obstack *, int, m4_macro_args *); @@ -290,12 +290,11 @@ expand_token (m4 *context, m4_obstack *obs, m4__token_type type, Report errors on behalf of CALLER. */ static bool expand_argument (m4 *context, m4_obstack *obs, m4_symbol_value *argp, - const char *caller) + const m4_call_info *caller) { m4__token_type type; m4_symbol_value token; int paren_level = 0; - const char *file = m4_get_current_file (context); int line = m4_get_current_line (context); size_t len; unsigned int age = m4__quote_age (M4SYNTAX); @@ -362,8 +361,8 @@ expand_argument (m4 *context, m4_obstack *obs, m4_symbol_value *argp, break; case M4_TOKEN_EOF: - m4_error_at_line (context, EXIT_FAILURE, 0, file, line, caller, - _("end of file in argument list")); + m4_error (context, EXIT_FAILURE, 0, caller, + _("end of file in argument list")); break; case M4_TOKEN_WORD: @@ -584,12 +583,12 @@ collect_arguments (m4 *context, m4_call_info *info, m4_symbol *symbol, if (m4__next_token_is_open (context)) { /* Gobble parenthesis, then collect arguments. */ - m4__next_token (context, &token, NULL, NULL, false, info->name); + m4__next_token (context, &token, NULL, NULL, false, info); do { tokenp = (m4_symbol_value *) obstack_alloc (arguments, sizeof *tokenp); - more_args = expand_argument (context, arguments, tokenp, info->name); + more_args = expand_argument (context, arguments, tokenp, info); if ((m4_is_symbol_value_text (tokenp) && !m4_get_symbol_value_len (tokenp)) @@ -661,7 +660,7 @@ m4_macro_call (m4 *context, m4_symbol_value *value, m4_obstack *expansion, if (argv->info->trace) trace_start = trace_pre (context, argv); - if (!m4_bad_argc (context, argv->argc, argv->argv0, + if (!m4_bad_argc (context, argv->argc, argv->info, VALUE_MIN_ARGS (value), VALUE_MAX_ARGS (value), BIT_TEST (VALUE_FLAGS (value), VALUE_SIDE_EFFECT_ARGS_BIT))) @@ -672,7 +671,7 @@ m4_macro_call (m4 *context, m4_symbol_value *value, m4_obstack *expansion, m4_get_symbol_value_func (value) (context, expansion, argv->argc, argv); else if (m4_is_symbol_value_placeholder (value)) - m4_warn (context, 0, M4ARG (0), + m4_warn (context, 0, argv->info, _("builtin `%s' requested by frozen file not found"), m4_get_symbol_value_placeholder (value)); else @@ -785,9 +784,8 @@ process_macro (m4 *context, m4_symbol_value *value, m4_obstack *obs, } else { - m4_error (context, 0, 0, M4ARG (0), - _("unterminated parameter reference: %s"), - key); + m4_error (context, 0, 0, argv->info, + _("unterminated parameter reference: %s"), key); } len -= endp - text; diff --git a/m4/utility.c b/m4/utility.c index 2cd4d18c..b15e17f6 100644 --- a/m4/utility.c +++ b/m4/utility.c @@ -41,8 +41,8 @@ static const char *skip_space (m4 *, const char *); Return true if the macro is guaranteed to expand to the empty string, false otherwise. */ bool -m4_bad_argc (m4 *context, int argc, const char *caller, size_t min, size_t max, - bool side_effect) +m4_bad_argc (m4 *context, int argc, const m4_call_info *caller, size_t min, + size_t max, bool side_effect) { if (argc - 1 < min) { @@ -74,7 +74,8 @@ skip_space (m4 *context, const char *arg) /* FIXME: Convert this to use gnulib's xstrtoimax, xstrtoumax. Otherwise, we are arbitrarily limiting integer values. */ bool -m4_numeric_arg (m4 *context, const char *caller, const char *arg, int *valuep) +m4_numeric_arg (m4 *context, const m4_call_info *caller, const char *arg, + int *valuep) { char *endp; @@ -96,10 +97,10 @@ m4_numeric_arg (m4 *context, const char *caller, const char *arg, int *valuep) } /* Parse ARG as a truth value. If unrecognized, issue a warning on - behalf of ME and return PREVIOUS; otherwise return the parsed + behalf of CALLER and return PREVIOUS; otherwise return the parsed value. */ bool -m4_parse_truth_arg (m4 *context, const char *arg, const char *me, +m4_parse_truth_arg (m4 *context, const m4_call_info *caller, const char *arg, bool previous) { /* 0, no, off, blank... */ @@ -115,17 +116,17 @@ m4_parse_truth_arg (m4 *context, const char *arg, const char *me, || ((arg[0] == 'o' || arg[0] == 'O') && (arg[1] == 'n' || arg[1] == 'N'))) return true; - m4_warn (context, 0, me, _("unknown directive `%s'"), arg); + m4_warn (context, 0, caller, _("unknown directive `%s'"), arg); return previous; } /* Helper method to look up a symbol table entry given an argument. - Warn on behalf of CALLER if VALUE is not a text argument, or if + Warn on behalf of ARGV if VALUE is not a text argument, or if MUST_EXIST and no macro exists by the name in VALUE. Return the result of the lookup, or NULL. */ m4_symbol * -m4_symbol_value_lookup (m4 *context, const char *caller, - m4_macro_args *argv, size_t i, bool must_exist) +m4_symbol_value_lookup (m4 *context, m4_macro_args *argv, size_t i, + bool must_exist) { m4_symbol *result = NULL; if (m4_is_arg_text (argv, i)) @@ -133,26 +134,30 @@ m4_symbol_value_lookup (m4 *context, const char *caller, const char *name = M4ARG (i); result = m4_symbol_lookup (M4SYMTAB, name); if (must_exist && !result) - m4_warn (context, 0, caller, _("undefined macro `%s'"), name); + m4_warn (context, 0, argv->info, _("undefined macro `%s'"), name); } else - m4_warn (context, 0, caller, _("invalid macro name ignored")); + m4_warn (context, 0, argv->info, _("invalid macro name ignored")); return result; } /* Helper for all error reporting. Report message based on FORMAT and - ARGS, on behalf of MACRO, at the optional location FILE and LINE. - If ERRNUM, decode the errno value as part of the message. If - STATUS, exit immediately with that status. If WARN, prepend - 'Warning: '. */ + ARGS, on behalf of CALLER (if any), otherwise at the global + position in CONTEXT. If ERRNUM, decode the errno value as part of + the message. If STATUS, exit immediately with that status. If + WARN, prepend 'Warning: '. */ static void m4_verror_at_line (m4 *context, bool warn, int status, int errnum, - const char *file, int line, const char *macro, - const char *format, va_list args) + const m4_call_info *caller, const char *format, + va_list args) { char *full = NULL; char *safe_macro = NULL; + const char *macro = caller ? caller->name : NULL; + const char *file = caller ? caller->file : m4_get_current_file (context); + int line = caller ? caller->line : m4_get_current_line (context); + assert (file || !line); /* Sanitize MACRO, since we are turning around and using it in a format string. The allocation is overly conservative, but problematic macro names only occur via indir or changesyntax. */ @@ -192,43 +197,19 @@ m4_verror_at_line (m4 *context, bool warn, int status, int errnum, any other arguments, and the program name and location (if we are currently parsing an input file) are automatically prepended. If ERRNUM is non-zero, include strerror output in the message. If - MACRO, prepend the message with the macro where the message + CALLER, prepend the message with the macro where the message occurred. If STATUS is non-zero, or if errors are fatal, call exit immediately; otherwise, remember that an error occurred so that m4 cannot exit with success later on.*/ void -m4_error (m4 *context, int status, int errnum, const char *macro, +m4_error (m4 *context, int status, int errnum, const m4_call_info *caller, const char *format, ...) { va_list args; - int line = m4_get_current_line (context); - assert (m4_get_current_file (context) || !line); va_start (args, format); if (status == EXIT_SUCCESS && m4_get_warnings_exit_opt (context)) status = EXIT_FAILURE; - m4_verror_at_line (context, false, status, errnum, - m4_get_current_file (context), line, macro, format, args); - va_end (args); -} - -/* Issue an error. The message is printf-style, based on FORMAT and - any other arguments, and the program name and location (from FILE - and LINE) are automatically prepended. If ERRNUM is non-zero, - include strerror output in the message. If STATUS is non-zero, or - if errors are fatal, call exit immediately; otherwise, remember - that an error occurred so that m4 cannot exit with success later - on. If MACRO, prepend the message with the macro where the message - occurred. */ -void -m4_error_at_line (m4 *context, int status, int errnum, const char *file, - int line, const char *macro, const char *format, ...) -{ - va_list args; - va_start (args, format); - if (status == EXIT_SUCCESS && m4_get_warnings_exit_opt (context)) - status = EXIT_FAILURE; - m4_verror_at_line (context, false, status, errnum, file, line, macro, - format, args); + m4_verror_at_line (context, false, status, errnum, caller, format, args); va_end (args); } @@ -236,39 +217,13 @@ m4_error_at_line (m4 *context, int status, int errnum, const char *file, printf-style, based on FORMAT and any other arguments, and the program name, location (if we are currently parsing an input file), and "Warning:" are automatically prepended. If ERRNUM is non-zero, - include strerror output in the message. If MACRO, prepend the + include strerror output in the message. If CALLER, prepend the message with the macro where the message occurred. If warnings are fatal, call exit immediately, otherwise exit status is unchanged. */ void -m4_warn (m4 *context, int errnum, const char *macro, const char *format, ...) -{ - if (!m4_get_suppress_warnings_opt (context)) - { - va_list args; - int status = EXIT_SUCCESS; - int line = m4_get_current_line (context); - assert (m4_get_current_file (context) || !line); - va_start (args, format); - if (m4_get_warnings_exit_opt (context)) - status = EXIT_FAILURE; - m4_verror_at_line (context, true, status, errnum, - m4_get_current_file (context), line, macro, format, - args); - va_end (args); - } -} - -/* Issue a warning, if they are not being suppressed. The message is - printf-style, based on FORMAT and any other arguments, and the - program name, location (from FILE and LINE), and "Warning:" are - automatically prepended. If ERRNUM is non-zero, include strerror - output in the message. If MACRO, prepend the message with the - macro where the message occurred. If warnings are fatal, call exit - immediately, otherwise exit status is unchanged. */ -void -m4_warn_at_line (m4 *context, int errnum, const char *file, int line, - const char *macro, const char *format, ...) +m4_warn (m4 *context, int errnum, const m4_call_info *caller, + const char *format, ...) { if (!m4_get_suppress_warnings_opt (context)) { @@ -277,13 +232,11 @@ m4_warn_at_line (m4 *context, int errnum, const char *file, int line, va_start (args, format); if (m4_get_warnings_exit_opt (context)) status = EXIT_FAILURE; - m4_verror_at_line (context, true, status, errnum, file, line, macro, - format, args); + m4_verror_at_line (context, true, status, errnum, caller, format, args); va_end (args); } } - /* Wrap the gnulib progname module, to avoid exporting a global variable from a library. Retrieve the program name for use in error messages and the __program__ macro. */ diff --git a/modules/evalparse.c b/modules/evalparse.c index 890816d1..8ad7182b 100644 --- a/modules/evalparse.c +++ b/modules/evalparse.c @@ -887,7 +887,7 @@ simple_term (m4 *context, eval_token et, number *v1) void m4_evaluate (m4 *context, m4_obstack *obs, size_t argc, m4_macro_args *argv) { - const char * me = M4ARG (0); + const m4_call_info *me = m4_arg_info (argv); const char * str = M4ARG (1); int radix = 10; int min = 1; diff --git a/modules/format.c b/modules/format.c index 4ff72b97..f5695e45 100644 --- a/modules/format.c +++ b/modules/format.c @@ -28,7 +28,7 @@ /* Parse STR as an integer, reporting warnings on behalf of ME. */ static int -arg_int (struct m4 *context, const char *me, const char *str) +arg_int (struct m4 *context, const m4_call_info *me, const char *str) { char *endp; long value; @@ -53,7 +53,7 @@ arg_int (struct m4 *context, const char *me, const char *str) /* Parse STR as a long, reporting warnings on behalf of ME. */ static long -arg_long (struct m4 *context, const char *me, const char *str) +arg_long (struct m4 *context, const m4_call_info *me, const char *str) { char *endp; long value; @@ -78,7 +78,7 @@ arg_long (struct m4 *context, const char *me, const char *str) /* Parse STR as a double, reporting warnings on behalf of ME. */ static double -arg_double (struct m4 *context, const char *me, const char *str) +arg_double (struct m4 *context, const m4_call_info *me, const char *str) { char *endp; double value; @@ -121,7 +121,7 @@ arg_double (struct m4 *context, const char *me, const char *str) static void format (m4 *context, m4_obstack *obs, int argc, m4_macro_args *argv) { - const char *me = M4ARG (0); /* Macro name. */ + const m4_call_info *me = m4_arg_info (argv); const char *f; /* Format control string. */ const char *fmt; /* Position within f. */ char fstart[] = "%'+- 0#*.*hhd"; /* Current format spec. */ diff --git a/modules/gnu.c b/modules/gnu.c index c28a1004..78c69b50 100644 --- a/modules/gnu.c +++ b/modules/gnu.c @@ -130,7 +130,7 @@ static m4_pattern_buffer regex_cache[REGEX_CACHE_SIZE]; CALLER, and return NULL. */ static m4_pattern_buffer * -regexp_compile (m4 *context, const char *caller, const char *regexp, +regexp_compile (m4 *context, const m4_call_info *caller, const char *regexp, size_t len, int resyntax) { /* regex_cache is guaranteed to start life 0-initialized, which @@ -231,7 +231,7 @@ regexp_search (m4_pattern_buffer *buf, const char *string, const int size, on behalf of CALLER. BUF may be NULL for the empty regex. */ static void -substitute (m4 *context, m4_obstack *obs, const char *caller, +substitute (m4 *context, m4_obstack *obs, const m4_call_info *caller, const char *victim, const char *repl, m4_pattern_buffer *buf) { int ch; @@ -285,7 +285,7 @@ substitute (m4 *context, m4_obstack *obs, const char *caller, copying the input if no changes are made. */ static bool -regexp_substitute (m4 *context, m4_obstack *obs, const char *caller, +regexp_substitute (m4 *context, m4_obstack *obs, const m4_call_info *caller, const char *victim, size_t len, const char *regexp, m4_pattern_buffer *buf, const char *replace, bool optimize) @@ -402,7 +402,7 @@ M4BUILTIN_HANDLER (__program__) **/ M4BUILTIN_HANDLER (builtin) { - const char *me = M4ARG (0); + const m4_call_info *me = m4_arg_info (argv); const char *name; m4_symbol_value *value; @@ -440,27 +440,27 @@ M4BUILTIN_HANDLER (builtin) else { const m4_builtin *bp = m4_get_symbol_value_builtin (value); - if (!m4_bad_argc (context, argc - 1, name, + m4_macro_args *new_argv; + bool flatten = (bp->flags & M4_BUILTIN_FLATTEN_ARGS) != 0; + new_argv = m4_make_argv_ref (context, argv, name, M4ARGLEN (1), + flatten, false); + if (!m4_bad_argc (context, argc - 1, m4_arg_info (new_argv), bp->min_args, bp->max_args, (bp->flags & M4_BUILTIN_SIDE_EFFECT) != 0)) - { - m4_macro_args *new_argv; - bool flatten = (bp->flags & M4_BUILTIN_FLATTEN_ARGS) != 0; - new_argv = m4_make_argv_ref (context, argv, name, M4ARGLEN (1), - flatten, false); - bp->func (context, obs, argc - 1, new_argv); - } + bp->func (context, obs, argc - 1, new_argv); free (value); } } } -/* Change the current regexp syntax. Currently this affects the - builtins: `patsubst', `regexp' and `renamesyms'. */ +/* Change the current regexp syntax to SPEC, or report failure on + behalf of CALLER. Currently this affects the builtins: `patsubst', + `regexp' and `renamesyms'. */ static int -m4_resyntax_encode_safe (m4 *context, const char *caller, const char *spec) +m4_resyntax_encode_safe (m4 *context, const m4_call_info *caller, + const char *spec) { int resyntax = m4_regexp_syntax_encode (spec); @@ -476,7 +476,8 @@ m4_resyntax_encode_safe (m4 *context, const char *caller, const char *spec) **/ M4BUILTIN_HANDLER (changeresyntax) { - int resyntax = m4_resyntax_encode_safe (context, M4ARG (0), M4ARG (1)); + int resyntax = m4_resyntax_encode_safe (context, m4_arg_info (argv), + M4ARG (1)); if (resyntax >= 0) m4_set_regexp_syntax_opt (context, resyntax); @@ -493,7 +494,7 @@ M4BUILTIN_HANDLER (changeresyntax) **/ M4BUILTIN_HANDLER (changesyntax) { - const char *me = M4ARG (0); + const m4_call_info *me = m4_arg_info (argv); M4_MODULE_IMPORT (m4, m4_expand_ranges); if (m4_expand_ranges) @@ -536,7 +537,7 @@ M4BUILTIN_HANDLER (changesyntax) **/ M4BUILTIN_HANDLER (debugfile) { - const char *me = M4ARG (0); + const m4_call_info *me = m4_arg_info (argv); if (argc == 1) m4_debug_set_output (context, me, NULL); @@ -558,7 +559,7 @@ M4BUILTIN_HANDLER (debuglen) { int i; size_t s; - if (!m4_numeric_arg (context, M4ARG (0), M4ARG (1), &i)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &i)) return; /* FIXME - make m4_numeric_arg more powerful - we want to accept suffixes, and limit the result to size_t. */ @@ -584,8 +585,8 @@ M4BUILTIN_HANDLER (debugmode) { new_debug_level = m4_debug_decode (context, debug_level, M4ARG (1)); if (new_debug_level < 0) - m4_error (context, 0, 0, M4ARG (0), _("bad debug flags: `%s'"), - M4ARG (1)); + m4_error (context, 0, 0, m4_arg_info (argv), + _("bad debug flags: `%s'"), M4ARG (1)); else m4_set_debug_level_opt (context, new_debug_level); } @@ -601,7 +602,7 @@ M4BUILTIN_HANDLER (debugmode) M4BUILTIN_HANDLER (esyscmd) { - const char *me = M4ARG (0); + const m4_call_info *me = m4_arg_info (argv); M4_MODULE_IMPORT (m4, m4_set_sysval); M4_MODULE_IMPORT (m4, m4_sysval_flush); @@ -667,7 +668,7 @@ M4BUILTIN_HANDLER (format) **/ M4BUILTIN_HANDLER (indir) { - const char *me = M4ARG (0); + const m4_call_info *me = m4_arg_info (argv); if (!m4_is_arg_text (argv, 1)) m4_warn (context, 0, me, _("invalid macro name ignored")); else @@ -701,7 +702,8 @@ M4BUILTIN_HANDLER (mkdtemp) M4_MODULE_IMPORT (m4, m4_make_temp); if (m4_make_temp) - m4_make_temp (context, obs, M4ARG (0), M4ARG (1), M4ARGLEN (1), true); + m4_make_temp (context, obs, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), + true); else assert (!"Unable to import from m4 module"); } @@ -719,13 +721,12 @@ M4BUILTIN_HANDLER (mkdtemp) **/ M4BUILTIN_HANDLER (patsubst) { - const char *me; /* name of this macro */ + const m4_call_info *me = m4_arg_info (argv); const char *pattern; /* regular expression */ const char *replace; /* replacement */ m4_pattern_buffer *buf; /* compiled regular expression */ int resyntax; - me = M4ARG (0); pattern = M4ARG (2); replace = M4ARG (3); @@ -766,7 +767,7 @@ M4BUILTIN_HANDLER (patsubst) **/ M4BUILTIN_HANDLER (regexp) { - const char *me; /* name of this macro */ + const m4_call_info *me = m4_arg_info (argv); const char *victim; /* string to search */ const char *pattern; /* regular expression */ const char *replace; /* optional replacement string */ @@ -775,7 +776,6 @@ M4BUILTIN_HANDLER (regexp) size_t len; /* length of first argument */ int resyntax; - me = M4ARG (0); pattern = M4ARG (2); replace = M4ARG (3); resyntax = m4_get_regexp_syntax_opt (context); @@ -850,7 +850,7 @@ M4BUILTIN_HANDLER (renamesyms) if (m4_dump_symbols) { - const char *me; /* name of this macro */ + const m4_call_info *me = m4_arg_info (argv); const char *regexp; /* regular expression string */ const char *replace; /* replacement expression string */ @@ -860,7 +860,6 @@ M4BUILTIN_HANDLER (renamesyms) int resyntax; - me = M4ARG (0); regexp = M4ARG (1); replace = M4ARG (2); @@ -937,6 +936,6 @@ M4BUILTIN_HANDLER (m4symbols) M4BUILTIN_HANDLER (syncoutput) { bool value = m4_get_syncoutput_opt (context); - value = m4_parse_truth_arg (context, M4ARG (1), M4ARG (0), value); + value = m4_parse_truth_arg (context, m4_arg_info (argv), M4ARG (1), value); m4_set_syncoutput_opt (context, value); } diff --git a/modules/m4.c b/modules/m4.c index 5cb6d114..bc93ee0f 100644 --- a/modules/m4.c +++ b/modules/m4.c @@ -47,13 +47,13 @@ #define m4_expand_ranges m4_LTX_m4_expand_ranges #define m4_make_temp m4_LTX_m4_make_temp -extern void m4_set_sysval (int value); -extern void m4_sysval_flush (m4 *context, bool report); -extern void m4_dump_symbols (m4 *context, m4_dump_symbol_data *data, - size_t argc, m4_macro_args *argv, bool complain); -extern const char *m4_expand_ranges (const char *s, m4_obstack *obs); -extern void m4_make_temp (m4 *context, m4_obstack *obs, const char *macro, - const char *name, size_t len, bool dir); +extern void m4_set_sysval (int); +extern void m4_sysval_flush (m4 *, bool); +extern void m4_dump_symbols (m4 *, m4_dump_symbol_data *, size_t, + m4_macro_args *, bool); +extern const char *m4_expand_ranges (const char *, m4_obstack *); +extern void m4_make_temp (m4 *, m4_obstack *, const m4_call_info *, + const char *, size_t, bool); /* Maintain each of the builtins implemented in this modules along with their details in a single table for easy maintenance. @@ -153,47 +153,49 @@ M4INIT_HANDLER (m4) M4BUILTIN_HANDLER (define) { + const m4_call_info *me = m4_arg_info (argv); + if (m4_is_arg_text (argv, 1)) { m4_symbol_value *value = m4_symbol_value_create (); if (m4_symbol_value_copy (context, value, m4_arg_symbol (argv, 2))) - m4_warn (context, 0, M4ARG (0), _("cannot concatenate builtins")); + m4_warn (context, 0, me, _("cannot concatenate builtins")); m4_symbol_define (M4SYMTAB, M4ARG (1), value); } else - m4_warn (context, 0, M4ARG (0), _("invalid macro name ignored")); + m4_warn (context, 0, me, _("invalid macro name ignored")); } M4BUILTIN_HANDLER (undefine) { - const char *me = M4ARG (0); size_t i; for (i = 1; i < argc; i++) - if (m4_symbol_value_lookup (context, me, argv, i, true)) + if (m4_symbol_value_lookup (context, argv, i, true)) m4_symbol_delete (M4SYMTAB, M4ARG (i)); } M4BUILTIN_HANDLER (pushdef) { + const m4_call_info *me = m4_arg_info (argv); + if (m4_is_arg_text (argv, 1)) { m4_symbol_value *value = m4_symbol_value_create (); if (m4_symbol_value_copy (context, value, m4_arg_symbol (argv, 2))) - m4_warn (context, 0, M4ARG (0), _("cannot concatenate builtins")); + m4_warn (context, 0, me, _("cannot concatenate builtins")); m4_symbol_pushdef (M4SYMTAB, M4ARG (1), value); } else - m4_warn (context, 0, M4ARG (0), _("invalid macro name ignored")); + m4_warn (context, 0, me, _("invalid macro name ignored")); } M4BUILTIN_HANDLER (popdef) { - const char *me = M4ARG (0); size_t i; for (i = 1; i < argc; i++) - if (m4_symbol_value_lookup (context, me, argv, i, true)) + if (m4_symbol_value_lookup (context, argv, i, true)) m4_symbol_popdef (M4SYMTAB, M4ARG (i)); } @@ -205,13 +207,12 @@ M4BUILTIN_HANDLER (popdef) M4BUILTIN_HANDLER (ifdef) { m4_push_arg (context, obs, argv, - (m4_symbol_value_lookup (context, M4ARG (0), argv, 1, false) - ? 2 : 3)); + m4_symbol_value_lookup (context, argv, 1, false) ? 2 : 3); } M4BUILTIN_HANDLER (ifelse) { - const char *me = M4ARG (0); + const m4_call_info *me = m4_arg_info (argv); size_t i; /* The valid ranges of argc for ifelse is discontinuous, we cannot @@ -290,7 +291,6 @@ void m4_dump_symbols (m4 *context, m4_dump_symbol_data *data, size_t argc, m4_macro_args *argv, bool complain) { - const char *me = M4ARG (0); assert (obstack_object_size (data->obs) == 0); data->size = obstack_room (data->obs) / sizeof (const char *); @@ -303,7 +303,7 @@ m4_dump_symbols (m4 *context, m4_dump_symbol_data *data, size_t argc, for (i = 1; i < argc; i++) { - symbol = m4_symbol_value_lookup (context, me, argv, i, complain); + symbol = m4_symbol_value_lookup (context, argv, i, complain); if (symbol) dump_symbol_CB (NULL, M4ARG (i), symbol, data); } @@ -353,12 +353,12 @@ M4BUILTIN_HANDLER (dumpdef) macro-definition token on the input stack. */ M4BUILTIN_HANDLER (defn) { - const char *me = M4ARG (0); + const m4_call_info *me = m4_arg_info (argv); size_t i; for (i = 1; i < argc; i++) { - m4_symbol *symbol = m4_symbol_value_lookup (context, me, argv, i, true); + m4_symbol *symbol = m4_symbol_value_lookup (context, argv, i, true); if (!symbol) ; @@ -368,9 +368,9 @@ M4BUILTIN_HANDLER (defn) else if (m4_is_symbol_func (symbol)) m4_push_builtin (context, obs, m4_get_symbol_value (symbol)); else if (m4_is_symbol_placeholder (symbol)) - m4_warn (context, 0, M4ARG (i), - _("builtin `%s' requested by frozen file not found"), - m4_get_symbol_placeholder (symbol)); + m4_warn (context, 0, me, + _("%s: builtin `%s' requested by frozen file not found"), + M4ARG (i), m4_get_symbol_placeholder (symbol)); else { assert (!"Bad token data type in m4_defn"); @@ -480,7 +480,7 @@ M4BUILTIN_HANDLER (syscmd) { if (m4_get_safer_opt (context)) { - m4_error (context, 0, 0, M4ARG (0), _("disabled by --safer")); + m4_error (context, 0, 0, m4_arg_info (argv), _("disabled by --safer")); return; } @@ -510,7 +510,7 @@ M4BUILTIN_HANDLER (incr) { int value; - if (!m4_numeric_arg (context, M4ARG (0), M4ARG (1), &value)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &value)) return; m4_shipout_int (obs, value + 1); @@ -520,7 +520,7 @@ M4BUILTIN_HANDLER (decr) { int value; - if (!m4_numeric_arg (context, M4ARG (0), M4ARG (1), &value)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &value)) return; m4_shipout_int (obs, value - 1); @@ -536,7 +536,8 @@ M4BUILTIN_HANDLER (divert) { int i = 0; - if (argc >= 2 && !m4_numeric_arg (context, M4ARG (0), M4ARG (1), &i)) + if (argc >= 2 && !m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), + &i)) return; m4_make_diversion (context, i); m4_divert_text (context, NULL, M4ARG (2), M4ARGLEN (2), @@ -557,7 +558,7 @@ M4BUILTIN_HANDLER (divnum) M4BUILTIN_HANDLER (undivert) { size_t i = 0; - const char *me = M4ARG (0); + const m4_call_info *me = m4_arg_info (argv); if (argc == 1) m4_undivert_all (context); @@ -596,7 +597,7 @@ M4BUILTIN_HANDLER (undivert) lives in input.c. */ M4BUILTIN_HANDLER (dnl) { - m4_skip_line (context, M4ARG (0)); + m4_skip_line (context, m4_arg_info (argv)); } /* Shift all arguments one to the left, discarding the first argument. @@ -641,7 +642,7 @@ include (m4 *context, int argc, m4_macro_args *argv, bool silent) if (fp == NULL) { if (!silent) - m4_error (context, 0, errno, M4ARG (0), _("cannot open `%s'"), + m4_error (context, 0, errno, m4_arg_info (argv), _("cannot open `%s'"), M4ARG (1)); return; } @@ -667,10 +668,10 @@ M4BUILTIN_HANDLER (sinclude) /* Add trailing `X' to PATTERN of length LEN as necessary, then securely create the temporary file system object. If DIR, create a - directory instead of a file. Report errors on behalf of MACRO. If + directory instead of a file. Report errors on behalf of CALLER. If successful, output the quoted resulting name on OBS. */ void -m4_make_temp (m4 *context, m4_obstack *obs, const char *macro, +m4_make_temp (m4 *context, m4_obstack *obs, const m4_call_info *caller, const char *pattern, size_t len, bool dir) { int fd; @@ -680,7 +681,7 @@ m4_make_temp (m4 *context, m4_obstack *obs, const char *macro, if (m4_get_safer_opt (context)) { - m4_error (context, 0, 0, macro, _("disabled by --safer")); + m4_error (context, 0, 0, caller, _("disabled by --safer")); return; } @@ -704,7 +705,7 @@ m4_make_temp (m4 *context, m4_obstack *obs, const char *macro, /* This use of _() will need to change if xgettext ever changes its undocumented behavior of parsing both string options. */ - m4_error (context, 0, errno, macro, + m4_error (context, 0, errno, caller, _(dir ? "cannot create directory from template `%s'" : "cannot create file from template `%s'"), pattern); @@ -723,7 +724,8 @@ m4_make_temp (m4 *context, m4_obstack *obs, const char *macro, /* Use the first argument as at template for a temporary file name. */ M4BUILTIN_HANDLER (maketemp) { - m4_warn (context, 0, M4ARG (0), _("recommend using mkstemp instead")); + const m4_call_info *me = m4_arg_info (argv); + m4_warn (context, 0, me, _("recommend using mkstemp instead")); if (m4_get_posixly_correct_opt (context)) { /* POSIX states "any trailing 'X' characters [are] replaced with @@ -757,13 +759,14 @@ M4BUILTIN_HANDLER (maketemp) } } else - m4_make_temp (context, obs, M4ARG (0), M4ARG (1), M4ARGLEN (1), false); + m4_make_temp (context, obs, me, M4ARG (1), M4ARGLEN (1), false); } /* Use the first argument as a template for a temporary file name. */ M4BUILTIN_HANDLER (mkstemp) { - m4_make_temp (context, obs, M4ARG (0), M4ARG (1), M4ARGLEN (1), false); + m4_make_temp (context, obs, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), + false); } /* Print all arguments on standard error. */ @@ -792,7 +795,7 @@ M4BUILTIN_HANDLER (errprint) arguments are present. */ M4BUILTIN_HANDLER (m4exit) { - const char *me = M4ARG (0); + const m4_call_info *me = m4_arg_info (argv); int exit_code = EXIT_SUCCESS; /* Warn on bad arguments, but still exit. */ @@ -836,7 +839,7 @@ M4BUILTIN_HANDLER (m4wrap) M4BUILTIN_HANDLER (traceon) { - const char *me = M4ARG (0); + const m4_call_info *me = m4_arg_info (argv); size_t i; if (argc == 1) @@ -853,7 +856,7 @@ M4BUILTIN_HANDLER (traceon) /* Disable tracing of all specified macros, or all, if none is specified. */ M4BUILTIN_HANDLER (traceoff) { - const char *me = M4ARG (0); + const m4_call_info *me = m4_arg_info (argv); size_t i; if (argc == 1) @@ -902,7 +905,7 @@ M4BUILTIN_HANDLER (index) substring extends to the end of the first argument. */ M4BUILTIN_HANDLER (substr) { - const char *me = M4ARG (0); + const m4_call_info *me = m4_arg_info (argv); const char *str = M4ARG (1); int start = 0; int length; diff --git a/modules/m4.h b/modules/m4.h index e1c3f960..eeefb181 100644 --- a/modules/m4.h +++ b/modules/m4.h @@ -43,7 +43,7 @@ typedef void m4_dump_symbols_func (m4 *context, m4_dump_symbol_data *data, bool complain); typedef const char *m4_expand_ranges_func (const char *s, m4_obstack *obs); typedef void m4_make_temp_func (m4 *context, m4_obstack *obs, - const char *macro, const char *name, + const m4_call_info *macro, const char *name, size_t len, bool dir); END_C_DECLS diff --git a/modules/stdlib.c b/modules/stdlib.c index c24fa2b9..0fd492fb 100644 --- a/modules/stdlib.c +++ b/modules/stdlib.c @@ -108,7 +108,7 @@ M4BUILTIN_HANDLER (setenv) int overwrite = 1; if (argc >= 4) - if (!m4_numeric_arg (context, M4ARG (0), M4ARG (3), &overwrite)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (3), &overwrite)) return; #if HAVE_SETENV @@ -206,7 +206,7 @@ M4BUILTIN_HANDLER (getpwuid) struct passwd *pw; int uid; - if (!m4_numeric_arg (context, M4ARG (0), M4ARG (1), &uid)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &uid)) return; pw = getpwuid (uid); @@ -261,7 +261,7 @@ M4BUILTIN_HANDLER (srand) seed = time (0L) * getpid (); else { - if (!m4_numeric_arg (context, M4ARG (0), M4ARG (1), &seed)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &seed)) return; } diff --git a/modules/time.c b/modules/time.c index 4febc8c5..62f3da60 100644 --- a/modules/time.c +++ b/modules/time.c @@ -104,7 +104,7 @@ M4BUILTIN_HANDLER (ctime) if (argc == 2) { - m4_numeric_arg (context, M4ARG (0), M4ARG (1), &i); + m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &i); t = i; } else @@ -152,7 +152,7 @@ M4BUILTIN_HANDLER (gmtime) time_t t; int i; - if (!m4_numeric_arg (context, M4ARG (0), M4ARG (1), &i)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &i)) return; t = i; @@ -167,7 +167,7 @@ M4BUILTIN_HANDLER (localtime) time_t t; int i; - if (!m4_numeric_arg (context, M4ARG (0), M4ARG (1), &i)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), &i)) return; t = i; @@ -180,7 +180,7 @@ M4BUILTIN_HANDLER (localtime) **/ M4BUILTIN_HANDLER (mktime) { - const char *me = M4ARG (0); + const m4_call_info *me = m4_arg_info (argv); struct tm tm; time_t t; @@ -216,7 +216,7 @@ M4BUILTIN_HANDLER (strftime) char *buf; int l; - if (!m4_numeric_arg (context, M4ARG (0), M4ARG (2), &l)) + if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (2), &l)) return; t = l; diff --git a/src/main.c b/src/main.c index 104c2568..e59183eb 100644 --- a/src/main.c +++ b/src/main.c @@ -748,9 +748,11 @@ main (int argc, char *const *argv, char *const *envp) 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, arg, - "--syncoutput", + m4_parse_truth_arg (context, &info, arg, previous)); } break; diff --git a/tests/freeze.at b/tests/freeze.at index 44de59d5..a90e24ed 100644 --- a/tests/freeze.at +++ b/tests/freeze.at @@ -506,7 +506,7 @@ AT_CHECK_M4([-R frozen.m4f input.m4], 0, a ]], -[[m4:input.m4:4: Warning: a: builtin `b' requested by frozen file not found +[[m4:input.m4:4: Warning: defn: a: builtin `b' requested by frozen file not found m4:input.m4:6: Warning: a: builtin `b' requested by frozen file not found m4:input.m4:8: Warning: a: builtin `b' requested by frozen file not found m4:input.m4:10: Warning: builtin: undefined builtin `b' diff --git a/tests/options.at b/tests/options.at index 5484f14c..66c4eada 100644 --- a/tests/options.at +++ b/tests/options.at @@ -248,6 +248,20 @@ AT_CHECK_M4([in -Q], [0], [[__line__ AT_CLEANUP +## -------------- ## +## unknown option ## +## -------------- ## + +AT_SETUP([unknown option]) + +AT_CHECK_M4([--unknown], [1], [], [stderr]) +AT_CHECK([sed 's/Try.*help/Try `m4 --help/' stderr], [0], +[[m4: unrecognized option `--unknown' +Try `m4 --help' for more information. +]]) + +AT_CLEANUP + ## --------- ## ## debugfile ## @@ -788,6 +802,16 @@ hi hi ]]) +dnl test parse error +AT_CHECK_M4([--syncoutput=huh in], [0], +[[hi +]], [[m4: Warning: --syncoutput: unknown directive `huh' +]]) + +AT_CLEANUP + +AT_SETUP([--syncoutput and diversions]) + dnl synclines should always start at the beginning of a line. dnl this does not (yet) happen reliably when diversions do not dnl always end in newline -- 2.11.4.GIT