diff options
author | Eric Blake <ebb9@byu.net> | 2007-12-18 16:13:16 -0700 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2008-06-02 21:31:43 -0600 |
commit | f3fbfb92cc3f44af244f888b8be6b465493dc590 (patch) | |
tree | d28b83f9c5bc243b0be62713c38ae233f6957ef0 | |
parent | b9a0d949a0485213215c59b6df9283d4886d5fff (diff) | |
download | m4-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-- | ChangeLog | 61 | ||||
-rw-r--r-- | doc/m4.texinfo | 16 | ||||
-rw-r--r-- | examples/null.err | bin | 51 -> 505 bytes | |||
-rw-r--r-- | examples/null.m4 | bin | 5876 -> 5891 bytes | |||
-rw-r--r-- | examples/null.out | bin | 404 -> 404 bytes | |||
-rw-r--r-- | m4/gnulib-cache.m4 | 4 | ||||
-rw-r--r-- | src/builtin.c | 193 | ||||
-rw-r--r-- | src/debug.c | 26 | ||||
-rw-r--r-- | src/eval.c | 56 | ||||
-rw-r--r-- | src/format.c | 8 | ||||
-rw-r--r-- | src/freeze.c | 10 | ||||
-rw-r--r-- | src/input.c | 103 | ||||
-rw-r--r-- | src/m4.c | 130 | ||||
-rw-r--r-- | src/m4.h | 34 | ||||
-rw-r--r-- | src/macro.c | 68 | ||||
-rw-r--r-- | src/symtab.c | 74 |
16 files changed, 430 insertions, 353 deletions
@@ -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 Binary files differindex d8258182..05a1ba3c 100644 --- a/examples/null.err +++ b/examples/null.err diff --git a/examples/null.m4 b/examples/null.m4 Binary files differindex 10d15aed..c9283605 100644 --- a/examples/null.m4 +++ b/examples/null.m4 diff --git a/examples/null.out b/examples/null.out Binary files differindex cd3764f7..66f41b55 100644 --- a/examples/null.out +++ b/examples/null.out 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; @@ -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 */ @@ -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; @@ -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" : "", |