summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2007-12-18 16:13:16 -0700
committerEric Blake <ebb9@byu.net>2008-06-02 21:31:43 -0600
commitf3fbfb92cc3f44af244f888b8be6b465493dc590 (patch)
treed28b83f9c5bc243b0be62713c38ae233f6957ef0
parentb9a0d949a0485213215c59b6df9283d4886d5fff (diff)
downloadm4-f3fbfb92cc3f44af244f888b8be6b465493dc590.tar.gz
Stage 24: Allow embedded NUL in macro names.
* m4/gnulib-cache.m4: Import xmemdup0 module. * src/m4.h (define_builtin, push_string_init, push_wrapup_init) (lookup_symbol): Add parameters. (struct call_info): Add name_len member. (struct token_data) [ENABLE_CHANGEWORD]: Add original_len member. (struct symbol): Add len member. (TOKEN_DATA_ORIG_LEN, SYMBOL_NAME_LEN): New accessors. (m4_error_at_line, m4_warn_at_line): Delete. (m4_error, m4_warn, debug_set_output, skip_line, set_word_regexp) (bad_argc, evaluate): Adjust parameter type. * src/m4.c (m4_error_at_line, m4_warn_at_line): Delete. (m4_verror_at_line, m4_error, m4_warn): Adjust parameter type. (main): Adjust caller. * src/symtab.c (profile_strcmp) [DEBUG_SYMTAB]: Rename... (profile_memcmp): ...and accomodate NUL. (hash, lookup_symbol): Add parameter to track length. (symtab_debug, symtab_print_list): Adjust callers. * src/input.c (push_string_init, push_wrapup_init): Take location as parameter rather than using global state. (skip_line, set_word_regexp, next_token): Adjust parameter type. (peek_input, next_char_1, match_input, lex_debug): Adjust callers. * src/macro.c (struct macro_arguments): Delete argv0 and argv0_len members, now covered by info. (expand_input, expand_token, expand_argument, collect_arguments) (expand_macro, arg_text, arg_empty, arg_len, make_argv_ref) (push_arg, wrap_args): Adjust callers. * src/builtin.c (define_builtin): Add parameter. (bad_argc, numeric_arg, mkstemp_helper, substitute): Adjust parameter type. (define_user_macro, builtin_init, define_macro, m4_undefine) (m4_popdef, m4_ifdef, m4_ifelse, dumpdef_cmp, m4_dumpdef) (m4_builtin, m4_indir, m4_defn, m4_syscmd, m4_esyscmd, m4_eval) (m4_incr, m4_decr, m4_divert, m4_divnum, m4_undivert, m4_shift) (m4_changequote, m4_changecom, m4_changeword, include) (m4_maketemp, m4_mkstemp, m4_errprint, m4___file__, m4___line__) (m4___program__, m4_m4exit, m4_m4wrap, m4_traceon, m4_traceoff) (m4_debugmode, m4_debugfile, m4_len, m4_index, m4_substr) (m4_translit, m4_format, m4_regexp, m4_patsubst): Adjust all callers. * src/debug.c (debug_set_file, debug_set_output): Adjust parameter type. (trace_flush, trace_prepre, trace_pre): Adjust all callers. * src/eval.c (logical_or_term, logical_and_term, or_term) (xor_term, and_term, equality_term, cmp_term, shift_term) (add_term, mult_term, exp_term, unary_term, simple_term) (evaluate): Adjust parameter type. * src/format.c (arg_int, arg_long, arg_double): Likewise. (expand_format): Adjust caller. * doc/m4.texinfo (Using frozen files): Test this. * examples/null.m4: Likewise. * examples/null.err: Adjust expected output. * examples/null.out: Likewise. (cherry picked from commit 6167507cf07ddbc838e14e3d66803b360e63f6f2) Signed-off-by: Eric Blake <ebb9@byu.net>
-rw-r--r--ChangeLog61
-rw-r--r--doc/m4.texinfo16
-rw-r--r--examples/null.errbin51 -> 505 bytes
-rw-r--r--examples/null.m4bin5876 -> 5891 bytes
-rw-r--r--examples/null.outbin404 -> 404 bytes
-rw-r--r--m4/gnulib-cache.m44
-rw-r--r--src/builtin.c193
-rw-r--r--src/debug.c26
-rw-r--r--src/eval.c56
-rw-r--r--src/format.c8
-rw-r--r--src/freeze.c10
-rw-r--r--src/input.c103
-rw-r--r--src/m4.c130
-rw-r--r--src/m4.h34
-rw-r--r--src/macro.c68
-rw-r--r--src/symtab.c74
16 files changed, 430 insertions, 353 deletions
diff --git a/ChangeLog b/ChangeLog
index 7bb18a1f..b3ddf607 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,66 @@
2008-06-02 Eric Blake <ebb9@byu.net>
+ Stage 24: Allow embedded NUL in macro names.
+ Replace const char *macro_name with const m4_call_info *call. Use
+ length rather than NUL-termination when tracking macro names,
+ including in diagnostics. Quote instances of problematic
+ characters in macro names when presented to user.
+ Memory impact: none.
+ Speed impact: slight penalty, due to more bookkeeping.
+ * m4/gnulib-cache.m4: Import xmemdup0 module.
+ * src/m4.h (define_builtin, push_string_init, push_wrapup_init)
+ (lookup_symbol): Add parameters.
+ (struct call_info): Add name_len member.
+ (struct token_data) [ENABLE_CHANGEWORD]: Add original_len member.
+ (struct symbol): Add len member.
+ (TOKEN_DATA_ORIG_LEN, SYMBOL_NAME_LEN): New accessors.
+ (m4_error_at_line, m4_warn_at_line): Delete.
+ (m4_error, m4_warn, debug_set_output, skip_line, set_word_regexp)
+ (bad_argc, evaluate): Adjust parameter type.
+ * src/m4.c (m4_error_at_line, m4_warn_at_line): Delete.
+ (m4_verror_at_line, m4_error, m4_warn): Adjust parameter type.
+ (main): Adjust caller.
+ * src/symtab.c (profile_strcmp) [DEBUG_SYMTAB]: Rename...
+ (profile_memcmp): ...and accomodate NUL.
+ (hash, lookup_symbol): Add parameter to track length.
+ (symtab_debug, symtab_print_list): Adjust callers.
+ * src/input.c (push_string_init, push_wrapup_init): Take location
+ as parameter rather than using global state.
+ (skip_line, set_word_regexp, next_token): Adjust parameter type.
+ (peek_input, next_char_1, match_input, lex_debug): Adjust
+ callers.
+ * src/macro.c (struct macro_arguments): Delete argv0 and argv0_len
+ members, now covered by info.
+ (expand_input, expand_token, expand_argument, collect_arguments)
+ (expand_macro, arg_text, arg_empty, arg_len, make_argv_ref)
+ (push_arg, wrap_args): Adjust callers.
+ * src/builtin.c (define_builtin): Add parameter.
+ (bad_argc, numeric_arg, mkstemp_helper, substitute): Adjust
+ parameter type.
+ (define_user_macro, builtin_init, define_macro, m4_undefine)
+ (m4_popdef, m4_ifdef, m4_ifelse, dumpdef_cmp, m4_dumpdef)
+ (m4_builtin, m4_indir, m4_defn, m4_syscmd, m4_esyscmd, m4_eval)
+ (m4_incr, m4_decr, m4_divert, m4_divnum, m4_undivert, m4_shift)
+ (m4_changequote, m4_changecom, m4_changeword, include)
+ (m4_maketemp, m4_mkstemp, m4_errprint, m4___file__, m4___line__)
+ (m4___program__, m4_m4exit, m4_m4wrap, m4_traceon, m4_traceoff)
+ (m4_debugmode, m4_debugfile, m4_len, m4_index, m4_substr)
+ (m4_translit, m4_format, m4_regexp, m4_patsubst): Adjust all
+ callers.
+ * src/debug.c (debug_set_file, debug_set_output): Adjust parameter
+ type.
+ (trace_flush, trace_prepre, trace_pre): Adjust all callers.
+ * src/eval.c (logical_or_term, logical_and_term, or_term)
+ (xor_term, and_term, equality_term, cmp_term, shift_term)
+ (add_term, mult_term, exp_term, unary_term, simple_term)
+ (evaluate): Adjust parameter type.
+ * src/format.c (arg_int, arg_long, arg_double): Likewise.
+ (expand_format): Adjust caller.
+ * doc/m4.texinfo (Using frozen files): Test this.
+ * examples/null.m4: Likewise.
+ * examples/null.err: Adjust expected output.
+ * examples/null.out: Likewise.
+
Allow autobuild usage.
* m4/gnulib.cache: Import autobuild module.
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index 67393e2e..fe429b49 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -7003,6 +7003,22 @@ $ @kbd{m4 -F /none/such}
^D
@error{}m4: cannot open /none/such: No such file or directory
@end example
+
+@c Another test - can we properly freeze embedded NUL?
+
+@comment xout: null.out
+@example
+ifdef(`__unix__', ,
+ `errprint(` skipping: syscmd does not have unix semantics
+')m4exit(`77')')dnl
+changequote(`[', `]')dnl
+syscmd([printf 'define(-\0-,hi)dnl
+divert(1)undivert(null.out)' | ]__program__[ -F in.m4f \
+ && printf 'errprint(indir(-\0-))' | ]__program__[ -R in.m4f \
+ && rm in.m4f])errprint([ ]sysval[
+])dnl
+@error{}hi 0
+@end example
@end ignore
When an @code{m4} run is to be frozen, the automatic undiversion
diff --git a/examples/null.err b/examples/null.err
index d8258182..05a1ba3c 100644
--- a/examples/null.err
+++ b/examples/null.err
Binary files differ
diff --git a/examples/null.m4 b/examples/null.m4
index 10d15aed..c9283605 100644
--- a/examples/null.m4
+++ b/examples/null.m4
Binary files differ
diff --git a/examples/null.out b/examples/null.out
index cd3764f7..66f41b55 100644
--- a/examples/null.out
+++ b/examples/null.out
Binary files differ
diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4
index 26abbef5..b6ba2020 100644
--- a/m4/gnulib-cache.m4
+++ b/m4/gnulib-cache.m4
@@ -15,11 +15,11 @@
# Specification in the form of a command-line invocation:
-# gnulib-tool --import --dir=. --local-dir=local --lib=libm4 --source-base=lib --m4-base=m4 --doc-base=doc --aux-dir=build-aux --with-tests --no-libtool --macro-prefix=M4 announce-gen assert autobuild avltree-oset binary-io clean-temp cloexec close-stream closein config-h error fdl fflush flexmember fopen-safer fseeko gendocs getopt git-version-gen gnumakefile gnupload gpl-3.0 intprops memchr2 memmem mkstemp obstack quote regex stdbool stdint stdlib-safer strtod strtol unlocked-io vasnprintf-posix verror version-etc version-etc-fsf xalloc xprintf xvasprintf-posix
+# gnulib-tool --import --dir=. --local-dir=local --lib=libm4 --source-base=lib --m4-base=m4 --doc-base=doc --aux-dir=build-aux --with-tests --no-libtool --macro-prefix=M4 announce-gen assert autobuild avltree-oset binary-io clean-temp cloexec close-stream closein config-h error fdl fflush flexmember fopen-safer fseeko gendocs getopt git-version-gen gnumakefile gnupload gpl-3.0 intprops memchr2 memmem mkstemp obstack quote regex stdbool stdint stdlib-safer strtod strtol unlocked-io vasnprintf-posix verror version-etc version-etc-fsf xalloc xmemdup0 xprintf xvasprintf-posix
# Specification in the form of a few gnulib-tool.m4 macro invocations:
gl_LOCAL_DIR([local])
-gl_MODULES([announce-gen assert autobuild avltree-oset binary-io clean-temp cloexec close-stream closein config-h error fdl fflush flexmember fopen-safer fseeko gendocs getopt git-version-gen gnumakefile gnupload gpl-3.0 intprops memchr2 memmem mkstemp obstack quote regex stdbool stdint stdlib-safer strtod strtol unlocked-io vasnprintf-posix verror version-etc version-etc-fsf xalloc xprintf xvasprintf-posix])
+gl_MODULES([announce-gen assert autobuild avltree-oset binary-io clean-temp cloexec close-stream closein config-h error fdl fflush flexmember fopen-safer fseeko gendocs getopt git-version-gen gnumakefile gnupload gpl-3.0 intprops memchr2 memmem mkstemp obstack quote regex stdbool stdint stdlib-safer strtod strtol unlocked-io vasnprintf-posix verror version-etc version-etc-fsf xalloc xmemdup0 xprintf xvasprintf-posix])
gl_AVOID([])
gl_SOURCE_BASE([lib])
gl_M4_BASE([m4])
diff --git a/src/builtin.c b/src/builtin.c
index 830d4a28..e3ddf322 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -230,18 +230,19 @@ func_print (struct obstack *obs, const builtin *func, bool flatten,
}
}
-/*-------------------------------------------------------------------------.
-| Install a builtin macro with name NAME, bound to the C function given in |
-| BP. MODE is SYMBOL_INSERT or SYMBOL_PUSHDEF. TRACED defines whether |
-| NAME is to be traced. |
-`-------------------------------------------------------------------------*/
+/*----------------------------------------------------------------.
+| Install a builtin macro with name NAME and length LEN, bound to |
+| the C function given in BP. MODE is SYMBOL_INSERT or |
+| SYMBOL_PUSHDEF. |
+`----------------------------------------------------------------*/
void
-define_builtin (const char *name, const builtin *bp, symbol_lookup mode)
+define_builtin (const char *name, size_t len, const builtin *bp,
+ symbol_lookup mode)
{
symbol *sym;
- sym = lookup_symbol (name, mode);
+ sym = lookup_symbol (name, len, mode);
SYMBOL_TYPE (sym) = TOKEN_FUNC;
SYMBOL_MACRO_ARGS (sym) = bp->groks_macro_args;
SYMBOL_BLIND_NO_ARGS (sym) = bp->blind_if_no_args;
@@ -443,7 +444,7 @@ define_user_macro (const char *name, size_t name_len, const char *text,
symbol *s;
char *defn = xstrdup (text ? text : "");
- s = lookup_symbol (name, mode);
+ s = lookup_symbol (name, name_len, mode);
if (SYMBOL_TYPE (s) == TOKEN_TEXT)
free (SYMBOL_TEXT (s));
@@ -468,16 +469,20 @@ define_user_macro (const char *name, size_t name_len, const char *text,
else
{
offset = regs->end[0];
- m4_warn (0, NULL,
- _("definition of `%s' contains sequence `%.*s'"),
- name, (int) (regs->end[0] - regs->start[0]),
- defn + regs->start[0]);
+ /* Safe to use slot 1 since we don't pass a macro name
+ to m4_warn. */
+ m4_warn (0, NULL, _("definition of %s contains sequence %s"),
+ quotearg_style_mem (locale_quoting_style, name,
+ name_len),
+ quotearg_n_style_mem (1, locale_quoting_style,
+ defn + regs->start[0],
+ regs->end[0] - regs->start[0]));
}
}
if (offset == -2)
m4_warn (0, NULL,
- _("problem checking --warn-macro-sequence for macro `%s'"),
- name);
+ _("problem checking --warn-macro-sequence for macro %s"),
+ quotearg_style_mem (locale_quoting_style, name, name_len));
}
}
@@ -495,14 +500,15 @@ builtin_init (void)
for (bp = &builtin_tab[0]; bp->name != NULL; bp++)
if (!no_gnu_extensions || !bp->gnu_extension)
{
+ size_t len = strlen (bp->name);
if (prefix_all_builtins)
{
string = xasprintf ("m4_%s", bp->name);
- define_builtin (string, bp, SYMBOL_INSERT);
+ define_builtin (string, len + 3, bp, SYMBOL_INSERT);
free (string);
}
else
- define_builtin (bp->name, bp, SYMBOL_INSERT);
+ define_builtin (bp->name, len, bp, SYMBOL_INSERT);
}
for (pp = &predefined_tab[0]; pp->func != NULL; pp++)
@@ -530,7 +536,7 @@ builtin_init (void)
`------------------------------------------------------------------*/
bool
-bad_argc (const char *name, int argc, unsigned int min, unsigned int max)
+bad_argc (const call_info *name, int argc, unsigned int min, unsigned int max)
{
if (argc - 1 < min)
{
@@ -549,7 +555,7 @@ bad_argc (const char *name, int argc, unsigned int min, unsigned int max)
`-------------------------------------------------------------------*/
static bool
-numeric_arg (const char *name, const char *arg, int *valuep)
+numeric_arg (const call_info *name, const char *arg, int *valuep)
{
char *endp;
@@ -657,7 +663,7 @@ static void
define_macro (int argc, macro_arguments *argv, symbol_lookup mode)
{
const builtin *bp;
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
if (bad_argc (me, argc, 1, 2))
return;
@@ -688,7 +694,7 @@ define_macro (int argc, macro_arguments *argv, symbol_lookup mode)
if (bp == NULL)
return;
else
- define_builtin (ARG (1), bp, mode);
+ define_builtin (ARG (1), ARG_LEN (1), bp, mode);
break;
default:
@@ -706,7 +712,7 @@ m4_define (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_undefine (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
int i;
if (bad_argc (me, argc, 1, -1))
return;
@@ -714,7 +720,7 @@ m4_undefine (struct obstack *obs, int argc, macro_arguments *argv)
if (arg_type (argv, i) != TOKEN_TEXT)
m4_warn (0, me, _("invalid macro name ignored"));
else
- lookup_symbol (ARG (i), SYMBOL_DELETE);
+ lookup_symbol (ARG (i), ARG_LEN (i), SYMBOL_DELETE);
}
static void
@@ -726,7 +732,7 @@ m4_pushdef (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_popdef (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
int i;
if (bad_argc (me, argc, 1, -1))
return;
@@ -734,7 +740,7 @@ m4_popdef (struct obstack *obs, int argc, macro_arguments *argv)
if (arg_type (argv, i) != TOKEN_TEXT)
m4_warn (0, me, _("invalid macro name ignored"));
else
- lookup_symbol (ARG (i), SYMBOL_POPDEF);
+ lookup_symbol (ARG (i), ARG_LEN (i), SYMBOL_POPDEF);
}
/*---------------------.
@@ -744,7 +750,7 @@ m4_popdef (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_ifdef (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
symbol *s;
if (bad_argc (me, argc, 2, 3))
@@ -755,14 +761,14 @@ m4_ifdef (struct obstack *obs, int argc, macro_arguments *argv)
push_arg (obs, argv, 3);
return;
}
- s = lookup_symbol (ARG (1), SYMBOL_LOOKUP);
+ s = lookup_symbol (ARG (1), ARG_LEN (1), SYMBOL_LOOKUP);
push_arg (obs, argv, (s && SYMBOL_TYPE (s) != TOKEN_VOID) ? 2 : 3);
}
static void
m4_ifelse (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
int i;
if (argc == 2 || bad_argc (me, argc, 3, -1))
@@ -832,8 +838,15 @@ dump_symbol (symbol *sym, void *arg)
static int
dumpdef_cmp (const void *s1, const void *s2)
{
- return strcmp (SYMBOL_NAME (* (symbol *const *) s1),
- SYMBOL_NAME (* (symbol *const *) s2));
+ const symbol *sym1 = *(const symbol **) s1;
+ const symbol *sym2 = *(const symbol **) s2;
+ size_t len1 = SYMBOL_NAME_LEN (sym1);
+ size_t len2 = SYMBOL_NAME_LEN (sym2);
+ int result = memcmp (SYMBOL_NAME (sym1), SYMBOL_NAME (sym2),
+ len1 < len2 ? len1 : len2);
+ if (!result)
+ result = len1 < len2 ? -1 : len2 < len1;
+ return result;
}
/*-------------------------------------------------------------------------.
@@ -844,12 +857,16 @@ dumpdef_cmp (const void *s1, const void *s2)
static void
m4_dumpdef (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
symbol *s;
int i;
struct dump_symbol_data data;
const builtin *bp;
+ /* If there's no debug stream to dump to, skip all of this work. */
+ if (!debug)
+ return;
+
data.obs = obs;
data.base = (symbol **) obstack_base (obs);
data.size = 0;
@@ -867,23 +884,27 @@ m4_dumpdef (struct obstack *obs, int argc, macro_arguments *argv)
m4_warn (0, me, _("invalid macro name ignored"));
continue;
}
- s = lookup_symbol (ARG (i), SYMBOL_LOOKUP);
+ s = lookup_symbol (ARG (i), ARG_LEN (i), SYMBOL_LOOKUP);
if (s != NULL && SYMBOL_TYPE (s) != TOKEN_VOID)
dump_symbol (s, &data);
else
- m4_warn (0, me, _("undefined macro `%s'"), ARG (i));
+ m4_warn (0, me, _("undefined macro %s"),
+ quotearg_style_mem (locale_quoting_style, ARG (i),
+ ARG_LEN (i)));
}
}
/* Make table of symbols invisible to expand_macro (). */
-
obstack_finish (obs);
qsort (data.base, data.size, sizeof (symbol *), dumpdef_cmp);
-
for (; data.size > 0; --data.size, data.base++)
{
- DEBUG_PRINT1 ("%s:\t", SYMBOL_NAME (data.base[0]));
+ /* TODO - add debugmode(b) option to control quoting style? */
+ fwrite (SYMBOL_NAME (data.base[0]), 1, SYMBOL_NAME_LEN (data.base[0]),
+ debug);
+ fputc (':', debug);
+ fputc ('\t', debug);
switch (SYMBOL_TYPE (data.base[0]))
{
@@ -924,7 +945,7 @@ m4_dumpdef (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_builtin (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
const builtin *bp;
const char *name;
@@ -939,7 +960,8 @@ m4_builtin (struct obstack *obs, int argc, macro_arguments *argv)
name = ARG (1);
bp = find_builtin_by_name (name);
if (bp->func == m4_placeholder)
- m4_warn (0, me, _("undefined builtin `%s'"), name);
+ m4_warn (0, me, _("undefined builtin %s"),
+ quotearg_style_mem (locale_quoting_style, name, ARG_LEN (1)));
else
{
macro_arguments *new_argv = make_argv_ref (argv, name, ARG_LEN (1),
@@ -958,9 +980,10 @@ m4_builtin (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_indir (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
symbol *s;
const char *name;
+ size_t len;
if (bad_argc (me, argc, 1, -1))
return;
@@ -971,12 +994,14 @@ m4_indir (struct obstack *obs, int argc, macro_arguments *argv)
}
name = ARG (1);
- s = lookup_symbol (name, SYMBOL_LOOKUP);
+ len = ARG_LEN (1);
+ s = lookup_symbol (name, len, SYMBOL_LOOKUP);
if (s == NULL || SYMBOL_TYPE (s) == TOKEN_VOID)
- m4_warn (0, me, _("undefined macro `%s'"), name);
+ m4_warn (0, me, _("undefined macro %s"),
+ quotearg_style_mem (locale_quoting_style, name, len));
else
{
- macro_arguments *new_argv = make_argv_ref (argv, name, ARG_LEN (1),
+ macro_arguments *new_argv = make_argv_ref (argv, name, len,
!SYMBOL_MACRO_ARGS (s),
SYMBOL_TRACED (s));
trace_prepre (arg_info (new_argv));
@@ -993,7 +1018,7 @@ m4_indir (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_defn (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
symbol *s;
builtin_func *b;
int i;
@@ -1008,10 +1033,12 @@ m4_defn (struct obstack *obs, int argc, macro_arguments *argv)
m4_warn (0, me, _("invalid macro name ignored"));
continue;
}
- s = lookup_symbol (ARG (i), SYMBOL_LOOKUP);
+ s = lookup_symbol (ARG (i), ARG_LEN (i), SYMBOL_LOOKUP);
if (s == NULL)
{
- m4_warn (0, me, _("undefined macro `%s'"), ARG (i));
+ m4_warn (0, me, _("undefined macro %s"),
+ quotearg_style_mem (locale_quoting_style, ARG (i),
+ ARG_LEN (i)));
continue;
}
@@ -1080,7 +1107,7 @@ static int sysval;
static void
m4_syscmd (struct obstack *obs, int argc, macro_arguments *argv)
{
- if (bad_argc (ARG (0), argc, 1, 1))
+ if (bad_argc (arg_info (argv), argc, 1, 1))
{
/* The empty command is successful. */
sysval = 0;
@@ -1104,7 +1131,7 @@ m4_syscmd (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_esyscmd (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
FILE *pin;
int ch;
@@ -1147,7 +1174,7 @@ m4_sysval (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_eval (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
int32_t value = 0;
int radix = 10;
int min = 1;
@@ -1211,7 +1238,7 @@ m4_eval (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_incr (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
int value;
if (bad_argc (me, argc, 1, 1))
@@ -1226,7 +1253,7 @@ m4_incr (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_decr (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
int value;
if (bad_argc (me, argc, 1, 1))
@@ -1249,7 +1276,7 @@ m4_decr (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_divert (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
int i = 0;
bad_argc (me, argc, 0, 1);
@@ -1266,7 +1293,7 @@ m4_divert (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_divnum (struct obstack *obs, int argc, macro_arguments *argv)
{
- bad_argc (ARG (0), argc, 0, 0);
+ bad_argc (arg_info (argv), argc, 0, 0);
shipout_int (obs, current_diversion);
}
@@ -1280,7 +1307,7 @@ m4_divnum (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_undivert (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
int i;
int file;
FILE *fp;
@@ -1324,7 +1351,7 @@ m4_undivert (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_dnl (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
bad_argc (me, argc, 0, 0);
skip_line (me);
@@ -1338,7 +1365,7 @@ m4_dnl (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_shift (struct obstack *obs, int argc, macro_arguments *argv)
{
- if (bad_argc (ARG (0), argc, 1, -1))
+ if (bad_argc (arg_info (argv), argc, 1, -1))
return;
push_args (obs, argv, true, true);
}
@@ -1350,7 +1377,7 @@ m4_shift (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_changequote (struct obstack *obs, int argc, macro_arguments *argv)
{
- bad_argc (ARG (0), argc, 0, 2);
+ bad_argc (arg_info (argv), argc, 0, 2);
/* Explicit NULL distinguishes between empty and missing argument. */
set_quotes ((argc >= 2) ? ARG (1) : NULL,
@@ -1365,7 +1392,7 @@ m4_changequote (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_changecom (struct obstack *obs, int argc, macro_arguments *argv)
{
- bad_argc (ARG (0), argc, 0, 2);
+ bad_argc (arg_info (argv), argc, 0, 2);
/* Explicit NULL distinguishes between empty and missing argument. */
set_comment ((argc >= 2) ? ARG (1) : NULL,
@@ -1382,7 +1409,7 @@ m4_changecom (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_changeword (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
if (bad_argc (me, argc, 1, 1))
return;
@@ -1403,7 +1430,7 @@ m4_changeword (struct obstack *obs, int argc, macro_arguments *argv)
static void
include (int argc, macro_arguments *argv, bool silent)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
FILE *fp;
char *name;
@@ -1453,7 +1480,7 @@ m4_sinclude (struct obstack *obs, int argc, macro_arguments *argv)
securely create the file, and place the quoted new file name on
OBS. Report errors on behalf of ME. */
static void
-mkstemp_helper (struct obstack *obs, const char *me, const char *pattern,
+mkstemp_helper (struct obstack *obs, const call_info *me, const char *pattern,
size_t len)
{
int fd;
@@ -1490,7 +1517,7 @@ mkstemp_helper (struct obstack *obs, const char *me, const char *pattern,
static void
m4_maketemp (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
if (bad_argc (me, argc, 1, 1))
return;
@@ -1535,7 +1562,7 @@ m4_maketemp (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_mkstemp (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
if (bad_argc (me, argc, 1, 1))
return;
@@ -1551,7 +1578,7 @@ m4_errprint (struct obstack *obs, int argc, macro_arguments *argv)
{
size_t len;
- if (bad_argc (ARG (0), argc, 1, -1))
+ if (bad_argc (arg_info (argv), argc, 1, -1))
return;
arg_print (obs, argv, 1, NULL, true, NULL, " ", NULL, false);
debug_flush_files ();
@@ -1565,7 +1592,7 @@ m4_errprint (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4___file__ (struct obstack *obs, int argc, macro_arguments *argv)
{
- bad_argc (ARG (0), argc, 0, 0);
+ bad_argc (arg_info (argv), argc, 0, 0);
obstack_grow (obs, curr_quote.str1, curr_quote.len1);
obstack_grow (obs, current_file, strlen (current_file));
obstack_grow (obs, curr_quote.str2, curr_quote.len2);
@@ -1574,14 +1601,14 @@ m4___file__ (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4___line__ (struct obstack *obs, int argc, macro_arguments *argv)
{
- bad_argc (ARG (0), argc, 0, 0);
+ bad_argc (arg_info (argv), argc, 0, 0);
shipout_int (obs, current_line);
}
static void
m4___program__ (struct obstack *obs, int argc, macro_arguments *argv)
{
- bad_argc (ARG (0), argc, 0, 0);
+ bad_argc (arg_info (argv), argc, 0, 0);
obstack_grow (obs, curr_quote.str1, curr_quote.len1);
obstack_grow (obs, program_name, strlen (program_name));
obstack_grow (obs, curr_quote.str2, curr_quote.len2);
@@ -1599,7 +1626,7 @@ m4___program__ (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_m4exit (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
int exit_code = EXIT_SUCCESS;
/* Warn on bad arguments, but still exit. */
@@ -1632,7 +1659,7 @@ m4_m4exit (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_m4wrap (struct obstack *obs, int argc, macro_arguments *argv)
{
- if (bad_argc (ARG (0), argc, 1, -1))
+ if (bad_argc (arg_info (argv), argc, 1, -1))
return;
wrap_args (argv);
}
@@ -1654,13 +1681,13 @@ set_trace (symbol *sym, void *data)
SYMBOL_TRACED (sym) = data != NULL;
/* Remove placeholder from table if macro is undefined and untraced. */
if (SYMBOL_TYPE (sym) == TOKEN_VOID && data == NULL)
- lookup_symbol (SYMBOL_NAME (sym), SYMBOL_POPDEF);
+ lookup_symbol (SYMBOL_NAME (sym), SYMBOL_NAME_LEN (sym), SYMBOL_POPDEF);
}
static void
m4_traceon (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
symbol *s;
int i;
@@ -1674,9 +1701,9 @@ m4_traceon (struct obstack *obs, int argc, macro_arguments *argv)
m4_warn (0, me, _("invalid macro name ignored"));
continue;
}
- s = lookup_symbol (ARG (i), SYMBOL_LOOKUP);
+ s = lookup_symbol (ARG (i), ARG_LEN (i), SYMBOL_LOOKUP);
if (!s)
- s = lookup_symbol (ARG (i), SYMBOL_INSERT);
+ s = lookup_symbol (ARG (i), ARG_LEN (i), SYMBOL_INSERT);
set_trace (s, obs);
}
}
@@ -1688,7 +1715,7 @@ m4_traceon (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_traceoff (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
symbol *s;
int i;
@@ -1702,7 +1729,7 @@ m4_traceoff (struct obstack *obs, int argc, macro_arguments *argv)
m4_warn (0, me, _("invalid macro name ignored"));
continue;
}
- s = lookup_symbol (ARG (i), SYMBOL_LOOKUP);
+ s = lookup_symbol (ARG (i), ARG_LEN (i), SYMBOL_LOOKUP);
if (s != NULL)
set_trace (s, NULL);
}
@@ -1717,7 +1744,7 @@ m4_traceoff (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_debugmode (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
const char *str = ARG (1);
int new_debug_level;
int change_flag;
@@ -1769,7 +1796,7 @@ m4_debugmode (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_debugfile (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
bad_argc (me, argc, 0, 1);
@@ -1790,7 +1817,7 @@ m4_debugfile (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_len (struct obstack *obs, int argc, macro_arguments *argv)
{
- if (bad_argc (ARG (0), argc, 1, 1))
+ if (bad_argc (arg_info (argv), argc, 1, 1))
return;
shipout_int (obs, ARG_LEN (1));
}
@@ -1808,7 +1835,7 @@ m4_index (struct obstack *obs, int argc, macro_arguments *argv)
const char *result = NULL;
int retval = -1;
- if (bad_argc (ARG (0), argc, 2, 2))
+ if (bad_argc (arg_info (argv), argc, 2, 2))
{
/* builtin(`index') is blank, but index(`abc') is 0. */
if (argc == 2)
@@ -1838,7 +1865,7 @@ m4_index (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_substr (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
int start = 0;
int length;
int avail;
@@ -1929,7 +1956,7 @@ m4_translit (struct obstack *obs, int argc, macro_arguments *argv)
char found[UCHAR_MAX + 1] = {0};
unsigned char ch;
- if (bad_argc (ARG (0), argc, 2, 3))
+ if (bad_argc (arg_info (argv), argc, 2, 3))
{
/* builtin(`translit') is blank, but translit(`abc') is abc. */
if (argc == 2)
@@ -1981,7 +2008,7 @@ m4_translit (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_format (struct obstack *obs, int argc, macro_arguments *argv)
{
- if (bad_argc (ARG (0), argc, 1, -1))
+ if (bad_argc (arg_info (argv), argc, 1, -1))
return;
expand_format (obs, argc, argv);
}
@@ -1998,7 +2025,7 @@ m4_format (struct obstack *obs, int argc, macro_arguments *argv)
static int substitute_warned = 0;
static void
-substitute (struct obstack *obs, const char *me, const char *victim,
+substitute (struct obstack *obs, const call_info *me, const char *victim,
const char *repl, struct re_registers *regs)
{
int ch;
@@ -2078,7 +2105,7 @@ init_pattern_buffer (struct re_pattern_buffer *buf, struct re_registers *regs)
static void
m4_regexp (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
const char *victim; /* first argument */
const char *regexp; /* regular expression */
const char *repl; /* replacement string */
@@ -2148,7 +2175,7 @@ m4_regexp (struct obstack *obs, int argc, macro_arguments *argv)
static void
m4_patsubst (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0);
+ const call_info *me = arg_info (argv);
const char *victim; /* first argument */
const char *regexp; /* regular expression */
const char *repl;
diff --git a/src/debug.c b/src/debug.c
index 0298fc88..2b2388f4 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -30,7 +30,7 @@ FILE *debug = NULL;
/* Obstack for trace messages. */
static struct obstack trace;
-static void debug_set_file (const char *, FILE *);
+static void debug_set_file (const call_info *, FILE *);
/*----------------------------------.
| Initialize the debugging module. |
@@ -121,7 +121,7 @@ debug_decode (const char *opts)
`-----------------------------------------------------------------*/
static void
-debug_set_file (const char *caller, FILE *fp)
+debug_set_file (const call_info *caller, FILE *fp)
{
struct stat stdout_stat, debug_stat;
@@ -189,7 +189,7 @@ debug_flush_files (void)
`-------------------------------------------------------------------*/
bool
-debug_set_output (const char *caller, const char *name)
+debug_set_output (const call_info *caller, const char *name)
{
FILE *fp;
@@ -313,13 +313,16 @@ trace_header (const call_info *info)
static void
trace_flush (unsigned int start)
{
- char *line;
+ char *base = (char *) obstack_base (&trace);
+ size_t len = obstack_object_size (&trace);
- obstack_1grow (&trace, '\0');
- line = (char *) obstack_base (&trace);
- DEBUG_PRINT1 ("%s\n", &line[start]);
- start -= obstack_object_size (&trace);
- obstack_blank (&trace, start);
+ if (debug)
+ {
+ /* TODO - quote nonprintable characters if debug is tty? */
+ fwrite (&base[start], 1, len - start, debug);
+ fputc ('\n', debug);
+ }
+ obstack_blank (&trace, start - len);
}
/*-------------------------------------------------------------------.
@@ -333,7 +336,8 @@ trace_prepre (const call_info *info)
if (info->trace && (info->debug_level & DEBUG_TRACE_CALL))
{
unsigned int start = trace_header (info);
- trace_format ("%s ...", info->name);
+ obstack_grow (&trace, info->name, info->name_len);
+ obstack_grow (&trace, " ...", 4);
trace_flush (start);
}
}
@@ -353,7 +357,7 @@ trace_pre (macro_arguments *argv)
unsigned int start = trace_header (info);
assert (info->trace);
- trace_format ("%s", info->name);
+ obstack_grow (&trace, ARG (0), ARG_LEN (0));
if (1 < arg_argc (argv) && (trace_level & DEBUG_TRACE_ARGS))
{
size_t len = max_debug_argument_length;
diff --git a/src/eval.c b/src/eval.c
index fdb50b7a..e2e600b0 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1,6 +1,6 @@
/* GNU m4 -- A simple macro processor
- Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2006, 2007
+ Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GNU M4.
@@ -62,19 +62,19 @@ typedef enum eval_error
}
eval_error;
-static eval_error logical_or_term (const char *, eval_token, int32_t *);
-static eval_error logical_and_term (const char *, eval_token, int32_t *);
-static eval_error or_term (const char *, eval_token, int32_t *);
-static eval_error xor_term (const char *, eval_token, int32_t *);
-static eval_error and_term (const char *, eval_token, int32_t *);
-static eval_error equality_term (const char *, eval_token, int32_t *);
-static eval_error cmp_term (const char *, eval_token, int32_t *);
-static eval_error shift_term (const char *, eval_token, int32_t *);
-static eval_error add_term (const char *, eval_token, int32_t *);
-static eval_error mult_term (const char *, eval_token, int32_t *);
-static eval_error exp_term (const char *, eval_token, int32_t *);
-static eval_error unary_term (const char *, eval_token, int32_t *);
-static eval_error simple_term (const char *, eval_token, int32_t *);
+static eval_error logical_or_term (const call_info *, eval_token, int32_t *);
+static eval_error logical_and_term (const call_info *, eval_token, int32_t *);
+static eval_error or_term (const call_info *, eval_token, int32_t *);
+static eval_error xor_term (const call_info *, eval_token, int32_t *);
+static eval_error and_term (const call_info *, eval_token, int32_t *);
+static eval_error equality_term (const call_info *, eval_token, int32_t *);
+static eval_error cmp_term (const call_info *, eval_token, int32_t *);
+static eval_error shift_term (const call_info *, eval_token, int32_t *);
+static eval_error add_term (const call_info *, eval_token, int32_t *);
+static eval_error mult_term (const call_info *, eval_token, int32_t *);
+static eval_error exp_term (const call_info *, eval_token, int32_t *);
+static eval_error unary_term (const call_info *, eval_token, int32_t *);
+static eval_error simple_term (const call_info *, eval_token, int32_t *);
/*--------------------.
| Lexical functions. |
@@ -287,7 +287,7 @@ eval_lex (int32_t *val)
`---------------------------------------*/
bool
-evaluate (const char *me, const char *expr, int32_t *val)
+evaluate (const call_info *me, const char *expr, int32_t *val)
{
eval_token et;
eval_error err;
@@ -355,7 +355,7 @@ evaluate (const char *me, const char *expr, int32_t *val)
`---------------------------*/
static eval_error
-logical_or_term (const char *me, eval_token et, int32_t *v1)
+logical_or_term (const call_info *me, eval_token et, int32_t *v1)
{
int32_t v2;
eval_error er;
@@ -386,7 +386,7 @@ logical_or_term (const char *me, eval_token et, int32_t *v1)
}
static eval_error
-logical_and_term (const char *me, eval_token et, int32_t *v1)
+logical_and_term (const call_info *me, eval_token et, int32_t *v1)
{
int32_t v2;
eval_error er;
@@ -417,7 +417,7 @@ logical_and_term (const char *me, eval_token et, int32_t *v1)
}
static eval_error
-or_term (const char *me, eval_token et, int32_t *v1)
+or_term (const call_info *me, eval_token et, int32_t *v1)
{
int32_t v2;
eval_error er;
@@ -444,7 +444,7 @@ or_term (const char *me, eval_token et, int32_t *v1)
}
static eval_error
-xor_term (const char *me, eval_token et, int32_t *v1)
+xor_term (const call_info *me, eval_token et, int32_t *v1)
{
int32_t v2;
eval_error er;
@@ -471,7 +471,7 @@ xor_term (const char *me, eval_token et, int32_t *v1)
}
static eval_error
-and_term (const char *me, eval_token et, int32_t *v1)
+and_term (const call_info *me, eval_token et, int32_t *v1)
{
int32_t v2;
eval_error er;
@@ -498,7 +498,7 @@ and_term (const char *me, eval_token et, int32_t *v1)
}
static eval_error
-equality_term (const char *me, eval_token et, int32_t *v1)
+equality_term (const call_info *me, eval_token et, int32_t *v1)
{
eval_token op;
int32_t v2;
@@ -534,7 +534,7 @@ equality_term (const char *me, eval_token et, int32_t *v1)
}
static eval_error
-cmp_term (const char *me, eval_token et, int32_t *v1)
+cmp_term (const call_info *me, eval_token et, int32_t *v1)
{
eval_token op;
int32_t v2;
@@ -585,7 +585,7 @@ cmp_term (const char *me, eval_token et, int32_t *v1)
}
static eval_error
-shift_term (const char *me, eval_token et, int32_t *v1)
+shift_term (const call_info *me, eval_token et, int32_t *v1)
{
eval_token op;
int32_t v2;
@@ -638,7 +638,7 @@ shift_term (const char *me, eval_token et, int32_t *v1)
}
static eval_error
-add_term (const char *me, eval_token et, int32_t *v1)
+add_term (const call_info *me, eval_token et, int32_t *v1)
{
eval_token op;
int32_t v2;
@@ -673,7 +673,7 @@ add_term (const char *me, eval_token et, int32_t *v1)
}
static eval_error
-mult_term (const char *me, eval_token et, int32_t *v1)
+mult_term (const call_info *me, eval_token et, int32_t *v1)
{
eval_token op;
int32_t v2;
@@ -734,7 +734,7 @@ mult_term (const char *me, eval_token et, int32_t *v1)
}
static eval_error
-exp_term (const char *me, eval_token et, int32_t *v1)
+exp_term (const call_info *me, eval_token et, int32_t *v1)
{
uint32_t result;
int32_t v2;
@@ -773,7 +773,7 @@ exp_term (const char *me, eval_token et, int32_t *v1)
}
static eval_error
-unary_term (const char *me, eval_token et, int32_t *v1)
+unary_term (const call_info *me, eval_token et, int32_t *v1)
{
eval_token et2 = et;
eval_error er;
@@ -805,7 +805,7 @@ unary_term (const char *me, eval_token et, int32_t *v1)
}
static eval_error
-simple_term (const char *me, eval_token et, int32_t *v1)
+simple_term (const call_info *me, eval_token et, int32_t *v1)
{
int32_t v2;
eval_error er;
diff --git a/src/format.c b/src/format.c
index 717a0702..c783d11e 100644
--- a/src/format.c
+++ b/src/format.c
@@ -29,7 +29,7 @@
/* Parse STR as an integer, reporting warnings on behalf of ME. */
static int
-arg_int (const char *me, const char *str)
+arg_int (const call_info *me, const char *str)
{
char *endp;
long value;
@@ -54,7 +54,7 @@ arg_int (const char *me, const char *str)
/* Parse STR as a long, reporting warnings on behalf of ME. */
static long
-arg_long (const char *me, const char *str)
+arg_long (const call_info *me, const char *str)
{
char *endp;
long value;
@@ -79,7 +79,7 @@ arg_long (const char *me, const char *str)
/* Parse STR as a double, reporting warnings on behalf of ME. */
static double
-arg_double (const char *me, const char *str)
+arg_double (const call_info *me, const char *str)
{
char *endp;
double value;
@@ -124,7 +124,7 @@ arg_double (const char *me, const char *str)
void
expand_format (struct obstack *obs, int argc, macro_arguments *argv)
{
- const char *me = ARG (0); /* Macro name. */
+ const call_info *me = arg_info (argv);/* Macro name. */
const char *f; /* Format control string. */
const char *fmt; /* Position within f. */
char fstart[] = "%'+- 0#*.*hhd"; /* Current format spec. */
diff --git a/src/freeze.c b/src/freeze.c
index c88a2664..e67bcc82 100644
--- a/src/freeze.c
+++ b/src/freeze.c
@@ -98,9 +98,9 @@ produce_frozen_state (const char *name)
{
case TOKEN_TEXT:
xfprintf (file, "T%d,%d\n",
- (int) strlen (SYMBOL_NAME (sym)),
+ (int) SYMBOL_NAME_LEN (sym),
(int) strlen (SYMBOL_TEXT (sym)));
- fputs (SYMBOL_NAME (sym), file);
+ fwrite (SYMBOL_NAME (sym), 1, SYMBOL_NAME_LEN (sym), file);
fputs (SYMBOL_TEXT (sym), file);
fputc ('\n', file);
break;
@@ -113,9 +113,9 @@ produce_frozen_state (const char *name)
abort ();
}
xfprintf (file, "F%d,%d\n",
- (int) strlen (SYMBOL_NAME (sym)),
+ (int) SYMBOL_NAME_LEN (sym),
(int) strlen (bp->name));
- fputs (SYMBOL_NAME (sym), file);
+ fwrite (SYMBOL_NAME (sym), 1, SYMBOL_NAME_LEN (sym), file);
fputs (bp->name, file);
fputc ('\n', file);
break;
@@ -346,7 +346,7 @@ reload_frozen_state (const char *name)
/* Enter a macro having a builtin function as a definition. */
bp = find_builtin_by_name (string[1]);
- define_builtin (string[0], bp, SYMBOL_PUSHDEF);
+ define_builtin (string[0], number[0], bp, SYMBOL_PUSHDEF);
break;
case 'T':
diff --git a/src/input.c b/src/input.c
index c1f609b4..acbc3704 100644
--- a/src/input.c
+++ b/src/input.c
@@ -322,7 +322,7 @@ push_macro (struct obstack *obs, builtin_func *func)
`--------------------------------------------------------------*/
struct obstack *
-push_string_init (void)
+push_string_init (const char *file, int line)
{
/* Free any memory occupied by completely parsed strings. */
assert (next == NULL);
@@ -331,8 +331,8 @@ push_string_init (void)
/* Reserve the next location on the obstack. */
next = (input_block *) obstack_alloc (current_input, sizeof *next);
next->type = INPUT_STRING;
- next->file = current_file;
- next->line = current_line;
+ next->file = file;
+ next->line = line;
next->u.u_s.len = 0;
return current_input;
@@ -544,7 +544,7 @@ push_string_finish (void)
`--------------------------------------------------------------*/
struct obstack *
-push_wrapup_init (token_chain ***end)
+push_wrapup_init (const call_info *caller, token_chain ***end)
{
input_block *i;
token_chain *chain;
@@ -560,8 +560,8 @@ push_wrapup_init (token_chain ***end)
{
i = (input_block *) obstack_alloc (wrapup_stack, sizeof *i);
i->prev = wsp;
- i->file = current_file;
- i->line = current_line;
+ i->file = caller->file;
+ i->line = caller->line;
i->type = INPUT_CHAIN;
i->u.u_c.chain = i->u.u_c.end = NULL;
wsp = i;
@@ -575,8 +575,8 @@ push_wrapup_init (token_chain ***end)
chain->next = NULL;
chain->type = CHAIN_LOC;
chain->quote_age = 0;
- chain->u.u_l.file = current_file;
- chain->u.u_l.line = current_line;
+ chain->u.u_l.file = caller->file;
+ chain->u.u_l.line = caller->line;
*end = &i->u.u_c.end;
return wrapup_stack;
}
@@ -859,7 +859,7 @@ peek_input (bool allow_argv)
/* Rather than directly parse argv here, we push
another input block containing the next unparsed
argument from argv. */
- push_string_init ();
+ push_string_init (block->file, block->line);
push_arg_quote (current_input, chain->u.u_a.argv,
chain->u.u_a.index,
quote_cache (NULL, chain->quote_age,
@@ -997,7 +997,7 @@ next_char_1 (bool allow_quote, bool allow_argv)
/* Rather than directly parse argv here, we push
another input block containing the next unparsed
argument from argv. */
- push_string_init ();
+ push_string_init (isp->file, isp->line);
push_arg_quote (current_input, chain->u.u_a.argv,
chain->u.u_a.index,
quote_cache (NULL, chain->quote_age,
@@ -1040,26 +1040,14 @@ next_char_1 (bool allow_quote, bool allow_argv)
`-------------------------------------------------------------------*/
void
-skip_line (const char *name)
+skip_line (const call_info *name)
{
int ch;
- const char *file = current_file;
- int line = current_line;
while ((ch = next_char (false, false)) != CHAR_EOF && ch != '\n')
;
if (ch == CHAR_EOF)
- /* current_file changed to "" if we see CHAR_EOF, use the
- previous value we stored earlier. */
- m4_warn_at_line (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 changeword
- 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 informs next_char to fix things again. */
- if (file != current_file || line != current_line)
- input_change = true;
+ m4_warn (0, name, _("end of file treated as newline"));
}
/*------------------------------------------------------------------.
@@ -1250,7 +1238,7 @@ match_input (const char *s, bool consume)
}
/* Failed or shouldn't consume, push back input. */
- push_string_init ();
+ push_string_init (current_file, current_line);
obstack_grow (current_input, t, n);
push_string_finish ();
return result;
@@ -1396,7 +1384,7 @@ set_comment (const char *bc, const char *ec)
`-------------------------------------------------------------------*/
void
-set_word_regexp (const char *caller, const char *regexp)
+set_word_regexp (const call_info *caller, const char *regexp)
{
const char *msg;
struct re_pattern_buffer new_word_regexp;
@@ -1586,7 +1574,7 @@ quote_cache (struct obstack *obs, unsigned int age, const string_pair *quotes)
token_type
next_token (token_data *td, int *line, struct obstack *obs, bool allow_argv,
- const char *caller)
+ const call_info *caller)
{
int ch;
int quote_level;
@@ -1594,20 +1582,21 @@ next_token (token_data *td, int *line, struct obstack *obs, bool allow_argv,
#ifdef ENABLE_CHANGEWORD
char *orig_text = NULL;
#endif /* ENABLE_CHANGEWORD */
- const char *file;
- int dummy;
+ const char *file = NULL;
/* The obstack where token data is stored. Generally token_stack,
for tokens where argument collection might not use the literal
token. But for comments and strings, we can output directly into
the argument collection obstack obs, if one was provided. */
struct obstack *obs_td = &token_stack;
-
obstack_free (&token_stack, token_bottom);
- if (!line)
- line = &dummy;
TOKEN_DATA_TYPE (td) = TOKEN_VOID;
ch = next_char (false, allow_argv && current_quote_age);
+ if (line)
+ {
+ *line = current_line;
+ file = current_file;
+ }
if (ch == CHAR_EOF)
{
#ifdef DEBUG_INPUT
@@ -1636,8 +1625,6 @@ next_token (token_data *td, int *line, struct obstack *obs, bool allow_argv,
return TOKEN_ARGV;
}
- file = current_file;
- *line = current_line;
if (MATCH (ch, curr_comm.str1, true))
{
if (obs)
@@ -1647,10 +1634,17 @@ next_token (token_data *td, int *line, struct obstack *obs, bool allow_argv,
{
ch = next_char (false, false);
if (ch == CHAR_EOF)
- /* Current_file changed to "" if we see CHAR_EOF, use the
- previous value we stored earlier. */
- m4_error_at_line (EXIT_FAILURE, 0, file, *line, caller,
- _("end of file in comment"));
+ {
+ /* Current_file changed to "" if we see CHAR_EOF, use
+ the previous value we stored earlier. */
+ if (!caller)
+ {
+ assert (line);
+ current_line = *line;
+ current_file = file;
+ }
+ m4_error (EXIT_FAILURE, 0, caller, _("end of file in comment"));
+ }
if (ch == CHAR_MACRO)
{
init_macro_token (obs, obs ? td : NULL);
@@ -1699,8 +1693,10 @@ next_token (token_data *td, int *line, struct obstack *obs, bool allow_argv,
next_char (false, false);
}
+ TOKEN_DATA_ORIG_LEN (td) = obstack_object_size (&token_stack);
obstack_1grow (&token_stack, '\0');
orig_text = (char *) obstack_finish (&token_stack);
+ TOKEN_DATA_ORIG_TEXT (td) = orig_text;
if (regs.start[1] != -1)
obstack_grow (&token_stack, orig_text + regs.start[1],
@@ -1743,11 +1739,17 @@ next_token (token_data *td, int *line, struct obstack *obs, bool allow_argv,
{
ch = next_char (obs != NULL && current_quote_age, false);
if (ch == CHAR_EOF)
- /* Current_file changed to "" if we see CHAR_EOF, use
- the previous value we stored earlier. */
- m4_error_at_line (EXIT_FAILURE, 0, file, *line, caller,
- _("end of file in string"));
-
+ {
+ /* Current_file changed to "" if we see CHAR_EOF, use
+ the previous value we stored earlier. */
+ if (!caller)
+ {
+ assert (line);
+ current_line = *line;
+ current_file = file;
+ }
+ m4_error (EXIT_FAILURE, 0, caller, _("end of file in string"));
+ }
if (ch == CHAR_MACRO)
init_macro_token (obs, obs ? td : NULL);
else if (ch == CHAR_QUOTE)
@@ -1784,12 +1786,10 @@ next_token (token_data *td, int *line, struct obstack *obs, bool allow_argv,
TOKEN_DATA_TEXT (td) = NULL;
TOKEN_DATA_QUOTE_AGE (td) = current_quote_age;
#ifdef ENABLE_CHANGEWORD
- if (orig_text == NULL)
- TOKEN_DATA_ORIG_TEXT (td) = TOKEN_DATA_TEXT (td);
- else
+ if (!orig_text)
{
- TOKEN_DATA_ORIG_TEXT (td) = orig_text;
- TOKEN_DATA_LEN (td) = strlen (orig_text);
+ TOKEN_DATA_ORIG_TEXT (td) = TOKEN_DATA_TEXT (td);
+ TOKEN_DATA_ORIG_LEN (td) = TOKEN_DATA_LEN (td);
}
#endif /* ENABLE_CHANGEWORD */
#ifdef DEBUG_INPUT
@@ -1948,6 +1948,10 @@ print_token (const char *s, token_type t, token_data *td)
xfprintf (stderr, "macro: %p\n", TOKEN_DATA_FUNC (td));
break;
+ case TOKEN_ARGV:
+ xfprintf (stderr, "argv:");
+ break;
+
case TOKEN_EOF:
xfprintf (stderr, "eof\n");
break;
@@ -1960,8 +1964,9 @@ lex_debug (void)
{
token_type t;
token_data td;
+ int line;
- while ((t = next_token (&td, NULL, NULL, false, "<debug>")) != TOKEN_EOF)
+ while ((t = next_token (&td, &line, NULL, false, NULL)) != TOKEN_EOF)
print_token ("lex", t, &td);
}
#endif /* DEBUG_INPUT */
diff --git a/src/m4.c b/src/m4.c
index 84cb8e07..e2ef4bc3 100644
--- a/src/m4.c
+++ b/src/m4.c
@@ -86,46 +86,53 @@ typedef struct macro_definition macro_definition;
/*------------------------------------------------------------------.
| Helper for all the error reporting, as a wrapper around |
| error_at_line. Report error message based on FORMAT and ARGS, on |
-| behalf of MACRO, at the location FILE and LINE (but with no |
-| location if LINE is 0). If ERRNUM, decode the errno value that |
-| caused the error. If STATUS, exit immediately with that status. |
-| If WARN, prepend 'Warning: '. |
+| behalf of CALLER (if any), otherwise at the global current |
+| location. If ERRNUM, decode the errno value that caused the |
+| error. If STATUS, exit immediately with that status. If WARN, |
+| prepend 'Warning: '. |
`------------------------------------------------------------------*/
static void
-m4_verror_at_line (bool warn, int status, int errnum, const char *file,
- int line, const char *macro, const char *format,
- va_list args)
+m4_verror_at_line (bool warn, int status, int errnum, const call_info *caller,
+ const char *format, va_list args)
{
char *full = NULL;
char *safe_macro = NULL;
+ const char *macro = caller ? caller->name : NULL;
+ size_t len = caller ? caller->name_len : 0;
+ const char *file = caller ? caller->file : current_file;
+ int line = caller ? caller->line : current_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 changeword. */
- if (macro && strchr (macro, '%'))
+ if (macro && memchr (macro, '%', len))
{
- char *p = safe_macro = xcharalloc (2 * strlen (macro) + 1);
- do
+ char *p = safe_macro = xcharalloc (2 * len);
+ const char *end = macro + len;
+ while (macro != end)
{
if (*macro == '%')
- *p++ = '%';
+ {
+ *p++ = '%';
+ len++;
+ }
*p++ = *macro++;
}
- while (*macro);
- *p = '\0';
}
+ if (macro)
+ /* Use slot 1, so that the rest of the code can use the simpler
+ quotearg interface in slot 0. */
+ macro = quotearg_n_mem (1, safe_macro ? safe_macro : macro, len);
/* Prepend warning and the macro name, as needed. But if that fails
for non-memory reasons (unlikely), then still use the original
format. */
if (warn && macro)
- full = xasprintf (_("Warning: %s: %s"),
- quotearg (safe_macro ? safe_macro : macro), format);
+ full = xasprintf (_("Warning: %s: %s"), macro, format);
else if (warn)
full = xasprintf (_("Warning: %s"), format);
else if (macro)
- full = xasprintf (_("%s: %s"),
- quotearg (safe_macro ? safe_macro : macro), format);
+ full = xasprintf (_("%s: %s"), macro, format);
verror_at_line (status, errnum, line ? file : NULL, line,
full ? full : format, args);
free (full);
@@ -134,82 +141,40 @@ m4_verror_at_line (bool warn, int status, int errnum, const char *file,
retcode = EXIT_FAILURE;
}
-/*----------------------------------------------------------------.
-| Wrapper around error. Report error message based on FORMAT and |
-| subsequent args, on behalf of MACRO, and the current input line |
-| (if any). If ERRNUM, decode the errno value that caused the |
-| error. If STATUS, exit immediately with that status. |
-`----------------------------------------------------------------*/
-
-void
-m4_error (int status, int errnum, const char *macro, const char *format, ...)
-{
- va_list args;
- va_start (args, format);
- if (status == EXIT_SUCCESS && warning_status)
- status = EXIT_FAILURE;
- m4_verror_at_line (false, status, errnum, current_file, current_line,
- macro, format, args);
- va_end (args);
-}
-
-/*----------------------------------------------------------------.
-| Wrapper around error_at_line. Report error message based on |
-| FORMAT and subsequent args, on behalf of MACRO, at the location |
-| FILE and LINE (but with no location if LINE is 0). If ERRNUM, |
-| decode the errno value that caused the error. If STATUS, exit |
-| immediately with that status. |
-`----------------------------------------------------------------*/
+/*------------------------------------------------------------------.
+| Wrapper around error. Report error message based on FORMAT and |
+| subsequent args, on behalf of CALLER (if any), and the current |
+| input line (if any). If ERRNUM, decode the errno value that |
+| caused the error. If STATUS, exit immediately with that status. |
+`------------------------------------------------------------------*/
void
-m4_error_at_line (int status, int errnum, const char *file, int line,
- const char *macro, const char *format, ...)
+m4_error (int status, int errnum, const call_info *caller,
+ const char *format, ...)
{
va_list args;
va_start (args, format);
if (status == EXIT_SUCCESS && warning_status)
status = EXIT_FAILURE;
- m4_verror_at_line (false, status, errnum, file, line, macro, format, args);
+ m4_verror_at_line (false, status, errnum, caller, format, args);
va_end (args);
}
/*------------------------------------------------------------------.
| Wrapper around error. Report warning message based on FORMAT and |
-| subsequent args, on behalf of MACRO, and the current input line |
-| (if any). If ERRNUM, decode the errno value that caused the |
-| warning. |
+| subsequent args, on behalf of CALLER (if any), and the current |
+| input line (if any). If ERRNUM, decode the errno value that |
+| caused the warning. |
`------------------------------------------------------------------*/
void
-m4_warn (int errnum, const char *macro, const char *format, ...)
-{
- va_list args;
- if (!suppress_warnings)
- {
- va_start (args, format);
- m4_verror_at_line (true, warning_status, errnum, current_file,
- current_line, macro, format, args);
- va_end (args);
- }
-}
-
-/*----------------------------------------------------------------.
-| Wrapper around error_at_line. Report warning message based on |
-| FORMAT and subsequent args, on behalf of MACRO, at the location |
-| FILE and LINE (but with no location if LINE is 0). If ERRNUM, |
-| decode the errno value that caused the warning. |
-`----------------------------------------------------------------*/
-
-void
-m4_warn_at_line (int errnum, const char *file, int line, const char *macro,
- const char *format, ...)
+m4_warn (int errnum, const call_info *caller, const char *format, ...)
{
va_list args;
if (!suppress_warnings)
{
va_start (args, format);
- m4_verror_at_line (true, warning_status, errnum, file, line, macro,
- format, args);
+ m4_verror_at_line (true, warning_status, errnum, caller, format, args);
va_end (args);
}
}
@@ -239,7 +204,7 @@ usage (int status)
{
if (status != EXIT_SUCCESS)
xfprintf (stderr, _("Try `%s --help' for more information.\n"),
- program_name);
+ program_name);
else
{
xprintf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
@@ -652,23 +617,20 @@ main (int argc, char *const *argv, char *const *envp)
{
case 'D':
{
- /* defines->arg is read-only, so we need a copy. */
- char *macro_name = xstrdup (defines->arg);
- char *macro_value = strchr (macro_name, '=');
- if (macro_value)
- *macro_value++ = '\0';
- define_user_macro (macro_name, strlen (macro_name),
- macro_value, SYMBOL_INSERT);
- free (macro_name);
+ const char *value = strchr (defines->arg, '=');
+ size_t len = value ? value - defines->arg : strlen (defines->arg);
+ define_user_macro (defines->arg, len, value ? value + 1 : "",
+ SYMBOL_INSERT);
}
break;
case 'U':
- lookup_symbol (defines->arg, SYMBOL_DELETE);
+ lookup_symbol (defines->arg, strlen (defines->arg), SYMBOL_DELETE);
break;
case 't':
- sym = lookup_symbol (defines->arg, SYMBOL_INSERT);
+ sym = lookup_symbol (defines->arg, strlen (defines->arg),
+ SYMBOL_INSERT);
SYMBOL_TRACED (sym) = true;
break;
diff --git a/src/m4.h b/src/m4.h
index b2e55e57..d16d87ab 100644
--- a/src/m4.h
+++ b/src/m4.h
@@ -50,6 +50,7 @@
#include "vasnprintf.h"
#include "verror.h"
#include "xalloc.h"
+#include "xmemdup0.h"
#include "xprintf.h"
#include "xvasprintf.h"
@@ -150,19 +151,16 @@ struct call_info
int trace : 1; /* True to trace this macro. */
int debug_level : 31; /* The debug level for tracing the macro call. */
const char *name; /* The macro name. */
+ size_t name_len; /* The length of name. */
};
typedef struct call_info call_info;
extern int retcode;
extern const char *program_name;
-void m4_error (int, int, const char *, const char *, ...)
+void m4_error (int, int, const call_info *, const char *, ...)
M4_GNUC_PRINTF (4, 5);
-void m4_error_at_line (int, int, const char *, int, const char *,
- const char *, ...) M4_GNUC_PRINTF (6, 7);
-void m4_warn (int, const char *, const char *, ...) M4_GNUC_PRINTF (3, 4);
-void m4_warn_at_line (int, const char *, int, const char *,
- const char *, ...) M4_GNUC_PRINTF (5, 6);
+void m4_warn (int, const call_info *, const char *, ...) M4_GNUC_PRINTF (3, 4);
#ifdef USE_STACKOVF
void setup_stackovf_trap (char *const *, char *const *,
@@ -256,7 +254,7 @@ extern FILE *debug;
void debug_init (void);
int debug_decode (const char *);
void debug_flush_files (void);
-bool debug_set_output (const char *, const char *);
+bool debug_set_output (const call_info *, const char *);
void debug_message_prefix (void);
void trace_prepre (const call_info *);
@@ -366,6 +364,7 @@ struct token_data
portion that matched the () group to form a macro name.
Otherwise, this field is unused. */
const char *original_text;
+ size_t original_len; /* Length of original_text. */
#endif
}
u_t;
@@ -391,6 +390,7 @@ struct token_data
#define TOKEN_DATA_QUOTE_AGE(Td) ((Td)->u.u_t.quote_age)
#ifdef ENABLE_CHANGEWORD
# define TOKEN_DATA_ORIG_TEXT(Td) ((Td)->u.u_t.original_text)
+# define TOKEN_DATA_ORIG_LEN(Td) ((Td)->u.u_t.original_len)
#endif
#define TOKEN_DATA_FUNC(Td) ((Td)->u.func)
@@ -400,8 +400,8 @@ typedef enum token_data_type token_data_type;
void input_init (void);
token_type peek_token (void);
token_type next_token (token_data *, int *, struct obstack *, bool,
- const char *);
-void skip_line (const char *);
+ const call_info *);
+void skip_line (const call_info *);
/* push back input */
void make_text_link (struct obstack *, token_chain **, token_chain **);
@@ -409,10 +409,10 @@ void push_file (FILE *, const char *, bool);
void append_macro (struct obstack *, builtin_func *, token_chain **,
token_chain **);
void push_macro (struct obstack *, builtin_func *);
-struct obstack *push_string_init (void);
+struct obstack *push_string_init (const char *, int);
bool push_token (token_data *, int, bool);
void push_string_finish (void);
-struct obstack *push_wrapup_init (token_chain ***);
+struct obstack *push_wrapup_init (const call_info *, token_chain ***);
void push_wrapup_finish (void);
bool pop_wrapup (void);
void input_print (struct obstack *);
@@ -433,7 +433,7 @@ extern string_pair curr_quote;
void set_quotes (const char *, const char *);
void set_comment (const char *, const char *);
#ifdef ENABLE_CHANGEWORD
-void set_word_regexp (const char *, const char *);
+void set_word_regexp (const call_info *, const char *);
#endif
unsigned int quote_age (void);
bool safe_quotes (void);
@@ -478,6 +478,7 @@ struct symbol
int pending_expansions;
char *name;
+ size_t len;
token_data data; /* Type should be only TOKEN_TEXT or TOKEN_FUNC. */
};
@@ -489,6 +490,7 @@ struct symbol
#define SYMBOL_DELETED(S) ((S)->deleted)
#define SYMBOL_PENDING_EXPANSIONS(S) ((S)->pending_expansions)
#define SYMBOL_NAME(S) ((S)->name)
+#define SYMBOL_NAME_LEN(S) ((S)->len)
#define SYMBOL_TYPE(S) (TOKEN_DATA_TYPE (&(S)->data))
#define SYMBOL_TEXT(S) (TOKEN_DATA_TEXT (&(S)->data))
#define SYMBOL_FUNC(S) (TOKEN_DATA_FUNC (&(S)->data))
@@ -503,7 +505,7 @@ extern symbol **symtab;
void free_symbol (symbol *sym);
void symtab_init (void);
-symbol *lookup_symbol (const char *, symbol_lookup);
+symbol *lookup_symbol (const char *, size_t, symbol_lookup);
void hack_all_symbols (hack_symbol *, void *);
/* File: macro.c --- macro expansion. */
@@ -573,8 +575,8 @@ struct re_registers;
#define DEFAULT_MACRO_SEQUENCE "\\$\\({[^}]*}\\|[0-9][0-9]+\\)"
void builtin_init (void);
-bool bad_argc (const char *, int, unsigned int, unsigned int);
-void define_builtin (const char *, const builtin *, symbol_lookup);
+bool bad_argc (const call_info *, int, unsigned int, unsigned int);
+void define_builtin (const char *, size_t, const builtin *, symbol_lookup);
void set_macro_sequence (const char *);
void free_regex (void);
void define_user_macro (const char *, size_t, const char *, symbol_lookup);
@@ -598,7 +600,7 @@ FILE *m4_path_search (const char *, char **);
/* File: eval.c --- expression evaluation. */
-bool evaluate (const char *, const char *, int32_t *);
+bool evaluate (const call_info *, const char *, int32_t *);
/* File: format.c --- printf like formatting. */
diff --git a/src/macro.c b/src/macro.c
index 2a5b52a3..0b574363 100644
--- a/src/macro.c
+++ b/src/macro.c
@@ -29,7 +29,7 @@
#endif /* DEBUG_MACRO */
/* Opaque structure describing all arguments to a macro, including the
- macro name at index 0. The lifetime of argv0 is only guaranteed
+ macro name at index 0. The lifetime of info is only guaranteed
within a call to expand_macro, whereas the lifetime of the array
members is guaranteed as long as the input engine can parse text
with a reference to $@. */
@@ -53,8 +53,6 @@ struct macro_arguments
bool_bitfield flatten : 1;
/* True if any token contains builtins. */
bool_bitfield has_func : 1;
- const char *argv0; /* The macro name being expanded. */
- size_t argv0_len; /* Length of argv0. */
/* The value of quote_age used when parsing all arguments in this
object, or 0 if quote_age changed during parsing or if any of the
arguments might contain content that can affect rescan. */
@@ -221,6 +219,7 @@ expand_input (void)
TOKEN_DATA_LEN (&empty_token) = 0;
#ifdef ENABLE_CHANGEWORD
TOKEN_DATA_ORIG_TEXT (&empty_token) = "";
+ TOKEN_DATA_ORIG_LEN (&empty_token) = 0;
#endif
while ((t = next_token (&td, &line, NULL, false, NULL)) != TOKEN_EOF)
@@ -301,7 +300,8 @@ expand_token (struct obstack *obs, token_type t, token_data *td, int line,
break;
case TOKEN_WORD:
- sym = lookup_symbol (TOKEN_DATA_TEXT (td), SYMBOL_LOOKUP);
+ sym = lookup_symbol (TOKEN_DATA_TEXT (td), TOKEN_DATA_LEN (td),
+ SYMBOL_LOOKUP);
if (sym == NULL || SYMBOL_TYPE (sym) == TOKEN_VOID
|| (SYMBOL_TYPE (sym) == TOKEN_FUNC
&& SYMBOL_BLIND_NO_ARGS (sym)
@@ -309,7 +309,7 @@ expand_token (struct obstack *obs, token_type t, token_data *td, int line,
{
#ifdef ENABLE_CHANGEWORD
divert_text (obs, TOKEN_DATA_ORIG_TEXT (td),
- TOKEN_DATA_LEN (td), line);
+ TOKEN_DATA_ORIG_LEN (td), line);
#else
divert_text (obs, TOKEN_DATA_TEXT (td), TOKEN_DATA_LEN (td), line);
#endif /* !ENABLE_CHANGEWORD */
@@ -344,12 +344,12 @@ expand_token (struct obstack *obs, token_type t, token_data *td, int line,
`-------------------------------------------------------------------*/
static bool
-expand_argument (struct obstack *obs, token_data *argp, const char *caller)
+expand_argument (struct obstack *obs, token_data *argp,
+ const call_info *caller)
{
token_type t;
token_data td;
int paren_level;
- const char *file = current_file;
int line = current_line;
unsigned int age = quote_age ();
bool first = true;
@@ -414,10 +414,8 @@ expand_argument (struct obstack *obs, token_data *argp, const char *caller)
break;
case TOKEN_EOF:
- /* Current_file changed to "" if we see TOKEN_EOF, use the
- previous value we stored earlier. */
- m4_error_at_line (EXIT_FAILURE, 0, file, line, caller,
- _("end of file in argument list"));
+ m4_error (EXIT_FAILURE, 0, caller,
+ _("end of file in argument list"));
break;
case TOKEN_WORD:
@@ -495,8 +493,6 @@ collect_arguments (symbol *sym, call_info *info, struct obstack *arguments,
args.has_ref = false;
args.flatten = !groks_macro_args;
args.has_func = false;
- args.argv0 = SYMBOL_NAME (sym);
- args.argv0_len = strlen (args.argv0);
args.quote_age = quote_age ();
args.info = info;
args.level = expansion_level - 1;
@@ -506,11 +502,11 @@ collect_arguments (symbol *sym, call_info *info, struct obstack *arguments,
if (peek_token () == TOKEN_OPEN)
{
/* gobble parenthesis */
- next_token (&td, NULL, NULL, false, SYMBOL_NAME (sym));
+ next_token (&td, NULL, NULL, false, info);
do
{
tdp = (token_data *) obstack_alloc (arguments, sizeof *tdp);
- more_args = expand_argument (arguments, tdp, SYMBOL_NAME (sym));
+ more_args = expand_argument (arguments, tdp, info);
if ((TOKEN_DATA_TYPE (tdp) == TOKEN_TEXT && !TOKEN_DATA_LEN (tdp))
|| (!groks_macro_args && TOKEN_DATA_TYPE (tdp) == TOKEN_FUNC))
@@ -622,10 +618,6 @@ expand_macro (symbol *sym)
int level = expansion_level; /* Expansion level of this macro. */
call_info my_call_info; /* Context of this macro. */
- /* TODO - make m4_warn use optional call_info, so we don't need these. */
- const char *loc_close_file;
- int loc_close_line;
-
/* Obstack preparation. */
if (level >= stacks_count)
{
@@ -670,6 +662,7 @@ expand_macro (symbol *sym)
my_call_info.trace = (debug_level & DEBUG_TRACE_ALL) || SYMBOL_TRACED (sym);
my_call_info.debug_level = debug_level;
my_call_info.name = SYMBOL_NAME (sym);
+ my_call_info.name_len = SYMBOL_NAME_LEN (sym);
trace_prepre (&my_call_info);
/* Collect the arguments. */
@@ -677,23 +670,13 @@ expand_macro (symbol *sym)
stacks[level].argv);
args_scratch = obstack_finish (stacks[level].args);
- /* Temporarily reset the location so that error messages are
- tracked to the macro name. */
- loc_close_file = current_file;
- loc_close_line = current_line;
- current_file = my_call_info.file;
- current_line = my_call_info.line;
-
/* The actual macro call. */
- expansion = push_string_init ();
+ expansion = push_string_init (my_call_info.file, my_call_info.line);
call_macro (sym, argv, expansion);
push_string_finish ();
/* Cleanup. */
- current_file = loc_close_file;
- current_line = loc_close_line;
argv->info = NULL;
-
--expansion_level;
--SYMBOL_PENDING_EXPANSIONS (sym);
@@ -714,7 +697,7 @@ expand_macro (symbol *sym)
if (debug_macro_level & PRINT_ARGCOUNT_CHANGES)
xfprintf (debug, "m4debug: -%d- `%s' in use, level=%d, "
"refcount=%zu, argcount=%zu\n", my_call_info.call_id,
- argv->argv0, level, stacks[level].refcount,
+ my_call_info.name, level, stacks[level].refcount,
stacks[level].argcount);
}
else
@@ -916,7 +899,10 @@ arg_text (macro_arguments *argv, unsigned int arg, bool flatten)
struct obstack *obs; /* Scratch space; cleaned at end of macro_expand. */
if (arg == 0)
- return argv->argv0;
+ {
+ assert (argv->info);
+ return argv->info->name;
+ }
if (arg >= argv->argc)
return "";
token = arg_token (argv, arg, NULL, flatten);
@@ -1119,7 +1105,10 @@ bool
arg_empty (macro_arguments *argv, unsigned int arg)
{
if (arg == 0)
- return argv->argv0_len == 0;
+ {
+ assert (argv->info);
+ return argv->info->name_len == 0;
+ }
if (arg >= argv->argc)
return true;
return arg_token (argv, arg, NULL, false) == &empty_token;
@@ -1135,7 +1124,10 @@ arg_len (macro_arguments *argv, unsigned int arg)
size_t len;
if (arg == 0)
- return argv->argv0_len;
+ {
+ assert (argv->info);
+ return argv->info->name_len;
+ }
if (arg >= argv->argc)
return 0;
token = arg_token (argv, arg, NULL, false);
@@ -1450,12 +1442,11 @@ make_argv_ref (macro_arguments *argv, const char *argv0, size_t argv0_len,
}
new_argv->argc = argv->argc - 1;
new_argv->inuse = false;
- new_argv->argv0 = argv0;
- new_argv->argv0_len = argv0_len;
new_argv->quote_age = argv->quote_age;
new_argv->info = info;
info->trace = (argv->info->debug_level & DEBUG_TRACE_ALL) || trace;
info->name = argv0;
+ info->name_len = argv0_len;
new_argv->level = argv->level;
return new_argv;
}
@@ -1469,7 +1460,8 @@ push_arg (struct obstack *obs, macro_arguments *argv, unsigned int arg)
{
/* Always push copy of arg 0, since its lifetime is not
guaranteed beyond expand_macro. */
- obstack_grow (obs, argv->argv0, argv->argv0_len);
+ assert (argv->info);
+ obstack_grow (obs, argv->info->name, argv->info->name_len);
return;
}
if (arg >= argv->argc)
@@ -1538,7 +1530,7 @@ wrap_args (macro_arguments *argv)
if ((argv->argc == 2 || no_gnu_extensions) && arg_empty (argv, 1))
return;
- obs = push_wrapup_init (&end);
+ obs = push_wrapup_init (argv->info, &end);
for (i = 1; i < (no_gnu_extensions ? 2 : argv->argc); i++)
{
if (i != 1)
diff --git a/src/symtab.c b/src/symtab.c
index dac49d7c..d4da2009 100644
--- a/src/symtab.c
+++ b/src/symtab.c
@@ -62,19 +62,20 @@ show_profile (void)
}
}
-/* Like strcmp (S1, S2), but also track profiling statistics. */
+/* Like memcmp (S1, S2, L), but also track profiling statistics. */
static int
-profile_strcmp (const char *s1, const char *s2)
+profile_memcmp (const char *s1, const char *s2, size_t l)
{
- int i = 1;
+ int i = 0;
int result;
- while (*s1 && *s1 == *s2)
+ while (l && *s1 == *s2)
{
s1++;
s2++;
i++;
+ l--;
}
- result = (unsigned char) *s1 - (unsigned char) *s2;
+ result = l ? (unsigned char) *s1 - (unsigned char) *s2 : 0;
profiles[current_mode].comparisons++;
if (result != 0)
profiles[current_mode].misses++;
@@ -82,7 +83,7 @@ profile_strcmp (const char *s1, const char *s2)
return result;
}
-# define strcmp profile_strcmp
+# define memcmp profile_memcmp
#endif /* DEBUG_SYM */
@@ -111,19 +112,18 @@ symtab_init (void)
}
/*--------------------------------------------------.
-| Return a hashvalue for a string, from GNU-emacs. |
+| Return a hashvalue for a string S of length LEN. |
`--------------------------------------------------*/
static size_t
-hash (const char *s)
+hash (const char *s, size_t len)
{
- register size_t val = 0;
+ size_t val = len;
- register const char *ptr = s;
- register char ch;
-
- while ((ch = *ptr++) != '\0')
- val = (val << 7) + (val >> (sizeof (val) * CHAR_BIT - 7)) + ch;
+ /* This algorithm was originally borrowed from GNU Emacs, but has
+ been modified to allow embedded NUL. */
+ while (len--)
+ val = (val << 7) + (val >> (sizeof val * CHAR_BIT - 7)) + to_uchar (*s++);
return val;
}
@@ -146,20 +146,20 @@ free_symbol (symbol *sym)
}
/*-------------------------------------------------------------------.
-| Search in, and manipulation of the symbol table, are all done by |
-| lookup_symbol (). It basically hashes NAME to a list in the |
-| symbol table, and searches this list for the first occurrence of a |
-| symbol with the name. |
-| |
+| Searches and manipulation of the symbol table are all done by |
+| lookup_symbol (). It basically hashes NAME, of length LEN, to a |
+| list in the symbol table, and searches this list for the first |
+| occurrence of a symbol with the name. |
+| |
| The MODE parameter determines what lookup_symbol () will do. It |
-| can either just do a lookup, do a lookup and insert if not |
+| can either just do a lookup, do a lookup and insert if not |
| present, do an insertion even if the name is already in the list, |
| delete the first occurrence of the name on the list, or delete all |
-| occurrences of the name on the list. |
+| occurrences of the name on the list. |
`-------------------------------------------------------------------*/
symbol *
-lookup_symbol (const char *name, symbol_lookup mode)
+lookup_symbol (const char *name, size_t len, symbol_lookup mode)
{
size_t h;
int cmp = 1;
@@ -171,12 +171,13 @@ lookup_symbol (const char *name, symbol_lookup mode)
profiles[mode].entry++;
#endif /* DEBUG_SYM */
- h = hash (name);
+ h = hash (name, len);
sym = symtab[h % hash_table_size];
for (prev = NULL; sym != NULL; prev = sym, sym = sym->next)
{
- cmp = strcmp (SYMBOL_NAME (sym), name);
+ cmp = (len < SYMBOL_NAME_LEN (sym) ? -1 : len > SYMBOL_NAME_LEN (sym) ? 1
+ : memcmp (SYMBOL_NAME (sym), name, len));
if (cmp >= 0)
break;
}
@@ -210,7 +211,8 @@ lookup_symbol (const char *name, symbol_lookup mode)
sym = (symbol *) xmalloc (sizeof (symbol));
SYMBOL_TYPE (sym) = TOKEN_VOID;
SYMBOL_TRACED (sym) = SYMBOL_TRACED (old);
- SYMBOL_NAME (sym) = xstrdup (name);
+ SYMBOL_NAME (sym) = xmemdup0 (name, len);
+ SYMBOL_NAME_LEN (sym) = len;
SYMBOL_SHADOWED (sym) = false;
SYMBOL_MACRO_ARGS (sym) = false;
SYMBOL_BLIND_NO_ARGS (sym) = false;
@@ -234,7 +236,8 @@ lookup_symbol (const char *name, symbol_lookup mode)
sym = (symbol *) xmalloc (sizeof (symbol));
SYMBOL_TYPE (sym) = TOKEN_VOID;
SYMBOL_TRACED (sym) = false;
- SYMBOL_NAME (sym) = xstrdup (name);
+ SYMBOL_NAME (sym) = xmemdup0 (name, len);
+ SYMBOL_NAME_LEN (sym) = len;
SYMBOL_SHADOWED (sym) = false;
SYMBOL_MACRO_ARGS (sym) = false;
SYMBOL_BLIND_NO_ARGS (sym) = false;
@@ -287,7 +290,8 @@ lookup_symbol (const char *name, symbol_lookup mode)
sym = (symbol *) xmalloc (sizeof (symbol));
SYMBOL_TYPE (sym) = TOKEN_VOID;
SYMBOL_TRACED (sym) = true;
- SYMBOL_NAME (sym) = xstrdup (name);
+ SYMBOL_NAME (sym) = xmemdup0 (name, len);
+ SYMBOL_NAME_LEN (sym) = len;
SYMBOL_SHADOWED (sym) = false;
SYMBOL_MACRO_ARGS (sym) = false;
SYMBOL_BLIND_NO_ARGS (sym) = false;
@@ -348,28 +352,32 @@ symtab_debug (void)
const char *text;
symbol *s;
int delete;
+ size_t len;
+ int line;
static int i;
- while (next_token (&td, NULL, NULL, false, "<debug>") == TOKEN_WORD)
+ while (next_token (&td, &line, NULL, false, NULL) == TOKEN_WORD)
{
text = TOKEN_DATA_TEXT (&td);
+ len = TOKEN_DATA_LEN (&td);
if (*text == '_')
{
delete = 1;
text++;
+ len--;
}
else
delete = 0;
- s = lookup_symbol (text, SYMBOL_LOOKUP);
+ s = lookup_symbol (text, len, SYMBOL_LOOKUP);
if (s == NULL)
xprintf ("Name `%s' is unknown\n", text);
if (delete)
- (void) lookup_symbol (text, SYMBOL_DELETE);
+ lookup_symbol (text, len, SYMBOL_DELETE);
else
- (void) lookup_symbol (text, SYMBOL_INSERT);
+ lookup_symbol (text, len, SYMBOL_INSERT);
}
symtab_print_list (i++);
}
@@ -383,9 +391,9 @@ symtab_print_list (int i)
xprintf ("Symbol dump #%d:\n", i);
for (h = 0; h < hash_table_size; h++)
for (sym = symtab[h]; sym != NULL; sym = sym->next)
- xprintf ("\tname %s, bucket %lu, addr %p, next %p, "
+ xprintf ("\tname %s, len %zu, bucket %lu, addr %p, next %p, "
"flags%s%s%s, pending %d\n",
- SYMBOL_NAME (sym),
+ SYMBOL_NAME (sym), SYMBOL_NAME_LEN (sym),
(unsigned long int) h, sym, SYMBOL_NEXT (sym),
SYMBOL_TRACED (sym) ? " traced" : "",
SYMBOL_SHADOWED (sym) ? " shadowed" : "",