This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "GNU M4 source repository".
http://git.sv.gnu.org/gitweb/?p=m4.git;a=commitdiff;h=50fabc46c235da6682f1bd76b1b43151e147c7bc The branch, branch-1.6 has been updated via 50fabc46c235da6682f1bd76b1b43151e147c7bc (commit) from 26b3c17ceb4f4155ff5dd13bcd9cc63039b3f242 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 50fabc46c235da6682f1bd76b1b43151e147c7bc Author: Eric Blake <[EMAIL PROTECTED]> Date: Thu Dec 6 14:47:26 2007 -0700 Stage 22: allow builtin token concatenation outside [EMAIL PROTECTED] * src/m4.h (arg_text): Add parameter. (ARG): Adjust callers. * src/input.c (init_macro_token): Add parameter. (next_token): Support concatenating builtins. * src/macro.c (warn_builtin_concat): Delete warning. (expand_argument, arg_adjust_refcount): Handle builtin tokens. (arg_text): Add parameter. (arg_print): Adjust caller. * src/builtin.c (define_macro): Flatten builtins, rather than doing nothing. (defn): Warn on undefined macro name. * src/m4.c (main): Avoid atoi. * src/output.c: Whitespace fixes. * doc/m4.texinfo (Defn): Document the new semantics. (Ifelse, Debug Levels, M4wrap): Enhance tests. * NEWS: Document this change. (cherry picked from commit 8a47a2029b7eb60ac61abb1b6423d4a67b371281) Signed-off-by: Eric Blake <[EMAIL PROTECTED]> ----------------------------------------------------------------------- Summary of changes: ChangeLog | 25 ++++++++++++++++ NEWS | 10 ++++++ doc/m4.texinfo | 80 ++++++++++++++++++++++++++++------------------------ src/builtin.c | 21 ++++++------- src/input.c | 84 +++++++++++++++++++++++-------------------------------- src/m4.c | 2 +- src/m4.h | 6 ++-- src/macro.c | 76 ++++++++++++++++++++------------------------------ src/output.c | 4 +- 9 files changed, 159 insertions(+), 149 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6362809..91c1845 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2008-05-05 Eric Blake <[EMAIL PROTECTED]> + + Stage 22: allow builtin token concatenation outside [EMAIL PROTECTED] + Adjust the input and argument parsing engines to append builtins + alongside text. Make define warn when builtins must be + flattened. + Memory impact: slight penalty, with fewer builtins flattened. + Speed impact: slight penalty, from more bookkeeping. + * src/m4.h (arg_text): Add parameter. + (ARG): Adjust callers. + * src/input.c (init_macro_token): Add parameter. + (next_token): Support concatenating builtins. + * src/macro.c (warn_builtin_concat): Delete warning. + (expand_argument, arg_adjust_refcount): Handle builtin tokens. + (arg_text): Add parameter. + (arg_print): Adjust caller. + * src/builtin.c (define_macro): Flatten builtins, rather than + doing nothing. + (defn): Warn on undefined macro name. + * src/m4.c (main): Avoid atoi. + * src/output.c: Whitespace fixes. + * doc/m4.texinfo (Defn): Document the new semantics. + (Ifelse, Debug Levels, M4wrap): Enhance tests. + * NEWS: Document this change. + 2008-05-03 Eric Blake <[EMAIL PROTECTED]> Document define_blind. diff --git a/NEWS b/NEWS index 0ca3094..052cbbc 100644 --- a/NEWS +++ b/NEWS @@ -33,9 +33,19 @@ Foundation, Inc. then apply this patch: http://git.sv.gnu.org/gitweb/?p=autoconf.git;a=commitdiff;h=56d42fa71 +** The `defn' builtin now warns when operating on an undefined macro name. + To simulate 1.4.x behavior, use: + pushdef(`defn', `ifdef(`$1', `builtin(`defn', `$1')')') + ** Enhance the `ifdef', `ifelse', and `shift' builtins, as well as all user macros, to transparently handle builtin tokens generated by `defn'. +** Allow the concatenation of builtin macros with arbitrary text in + several contexts, via the `defn' builtin or argument expansion, rather + than warning and converting the builtin token to an empty string. + However, it is still not possible to use a concatenated builtin when + defining a macro. + ** Enhance the `defn', `dumpdef', `ifdef', `popdef', `traceon', `traceoff', and `undefine' macros to warn when encountering a builtin token in the context of a macro name, rather than acting on the empty string. This diff --git a/doc/m4.texinfo b/doc/m4.texinfo index 4781567..fd04622 100644 --- a/doc/m4.texinfo +++ b/doc/m4.texinfo @@ -2112,17 +2112,14 @@ the builtin @code{defn}: @deffn Builtin defn (@[EMAIL PROTECTED]) Expands to the @emph{quoted definition} of each @var{name}. If an argument is not a defined macro, the expansion for that argument is -empty. +empty and triggers a warning. If @var{name} is a user-defined macro, the quoted definition is simply -the quoted expansion text. If, instead, there is only one @var{name} -and it is a builtin, the +the quoted expansion text. If, instead, @var{name} is a builtin, the expansion is a special token, which points to the builtin's internal -definition. This token is only meaningful as the second argument to +definition. This token meaningful primarily as the second argument to @code{define} (and @code{pushdef}), and is silently converted to an -empty string in most other contexts. Using multiple @var{name} to -combine a builtin with anything else is not supported; a warning is -issued and the builtin is omitted from the final expansion. +empty string in many other contexts. The macro @code{defn} is recognized only with parameters. @end deffn @@ -2281,14 +2278,18 @@ bar @result{}0 @end example -Also note that as of M4 1.6, @code{defn} with multiple arguments can -join text with builtin tokens. However, when collecting macro -arguments, a builtin token is preserved only when it occurs in -isolation. A future version of @acronym{GNU} M4 may lift this -restriction. +A warning is issued if @var{name} is undefined. Also note that as of M4 +1.6, @code{defn} with multiple arguments can join text with builtin +tokens. However, when defining a macro via @code{define} or [EMAIL PROTECTED], a warning is issued and the builtin token ignored if the +builtin token does not occur in isolation. A future version of [EMAIL PROTECTED] M4 may lift this restriction. @example $ @kbd{m4 -d} +defn(`foo') [EMAIL PROTECTED]:stdin:1: Warning: defn: undefined macro `foo' [EMAIL PROTECTED] define(`a', `A')define(`AA', `b') @result{} traceon(`defn', `define') @@ -2298,29 +2299,28 @@ defn(`a', `divnum', `a') @result{}AA define(`mydivnum', defn(`divnum', `divnum'))mydivnum @error{}m4trace: -2- defn(`divnum', `divnum') -> `<divnum><divnum>' [EMAIL PROTECTED]:stdin:4: Warning: define: cannot concatenate builtin `divnum' [EMAIL PROTECTED]:stdin:4: Warning: define: cannot concatenate builtin `divnum' [EMAIL PROTECTED]: -1- define(`mydivnum', `') [EMAIL PROTECTED]:stdin:5: Warning: define: cannot concatenate builtins [EMAIL PROTECTED]: -1- define(`mydivnum', `<divnum><divnum>') @result{} -traceoff(`defn', `define') +traceoff(`defn', `define')dumpdef(`mydivnum') [EMAIL PROTECTED]:@tabchar{}`' @result{} define(`mydivnum', defn(`divnum')defn(`divnum'))mydivnum [EMAIL PROTECTED]:stdin:6: Warning: define: cannot concatenate builtin `divnum' [EMAIL PROTECTED]:stdin:6: Warning: define: cannot concatenate builtin `divnum' [EMAIL PROTECTED]:stdin:7: Warning: define: cannot concatenate builtins @result{} define(`mydivnum', defn(`divnum')`a')mydivnum [EMAIL PROTECTED]:stdin:7: Warning: define: cannot concatenate builtin `divnum' [EMAIL PROTECTED]:stdin:8: Warning: define: cannot concatenate builtins @result{}A define(`mydivnum', `a'defn(`divnum'))mydivnum [EMAIL PROTECTED]:stdin:8: Warning: define: cannot concatenate builtin `divnum' [EMAIL PROTECTED]:stdin:9: Warning: define: cannot concatenate builtins @result{}A define(`q', ``$@@'') @result{} define(`foo', q(`a', defn(`divnum')))foo [EMAIL PROTECTED]:stdin:10: Warning: define: cannot concatenate builtins [EMAIL PROTECTED] [EMAIL PROTECTED]:stdin:11: Warning: define: cannot concatenate builtins [EMAIL PROTECTED], ifdef(`foo', `yes', `no') [EMAIL PROTECTED] [EMAIL PROTECTED] @end example @node Pushdef @@ -2853,6 +2853,8 @@ ifelse(defn(`defn'), defn(`divnum'), `yes', `no') @result{}no ifelse(defn(`defn'), defn(`defn'), `yes', `no') @result{}yes +ifelse(defn(`defn', `divnum'), defn(`defn')defn(`divnum'), `yes', `no') [EMAIL PROTECTED] define(`foo', ifelse(`', `', defn(`divnum'))) @result{} foo @@ -2917,8 +2919,6 @@ ifelse(`-01234567890123456789', `-'e(long)`-', `yes', `no') @result{}no @end example [EMAIL PROTECTED] It would be nice to allow concatenation of builtins without [EMAIL PROTECTED] using $@ handling. @example define(`e', `$@@')define(`q', ``$@@'')define(`u', `$*') @result{} @@ -2928,16 +2928,12 @@ cmp(`defn(`defn')', `defn(`d')') @result{}yes cmp(`defn(`defn')', ``<defn>'') @result{}no -cmp(`q(defn(`defn'))', `q(defn(`d'))')-fixme [EMAIL PROTECTED]:stdin:5: Warning: ifelse: cannot quote builtin [EMAIL PROTECTED]:stdin:5: Warning: ifelse: cannot quote builtin [EMAIL PROTECTED] -cmp(`q(defn(`defn'))', `q(`<defn>')')-fixme [EMAIL PROTECTED]:stdin:6: Warning: ifelse: cannot quote builtin [EMAIL PROTECTED] -cmp(`q(defn(`defn'))', ``'')-fixme [EMAIL PROTECTED]:stdin:7: Warning: ifelse: cannot quote builtin [EMAIL PROTECTED] +cmp(`q(defn(`defn'))', `q(defn(`d'))') [EMAIL PROTECTED] +cmp(`q(defn(`defn'))', `q(`<defn>')') [EMAIL PROTECTED] +cmp(`q(defn(`defn'))', ``'') [EMAIL PROTECTED] cmp(`q(`1', `2', defn(`defn'))', `q(`1', `2', defn(`d'))') @result{}yes cmp(`q(`1', `2', defn(`defn'))', `q(`1', `2', `<defn>')') @@ -3834,7 +3830,17 @@ debugmode() foo @error{}m4trace: -1- foo -> `FOO' @result{}FOO +debugmode(`V') [EMAIL PROTECTED] +foo(`ignored') [EMAIL PROTECTED]:stdin:6: -1- id 6: foo ... [EMAIL PROTECTED]:stdin:6: -1- id 6: foo(`ignored') -> ??? [EMAIL PROTECTED]:stdin:6: -1- id 6: foo(...) -> `FOO' [EMAIL PROTECTED] debugmode [EMAIL PROTECTED]:stdin:7: -1- id 7: debugmode ... [EMAIL PROTECTED]:stdin:7: -1- id 7: debugmode -> ??? [EMAIL PROTECTED] @result{} foo @error{}m4trace: -1- foo @@ -3842,7 +3848,7 @@ foo debugmode(`+l') @result{} foo [EMAIL PROTECTED]:8: -1- foo [EMAIL PROTECTED]:10: -1- foo @result{}FOO @end example @@ -4799,7 +4805,7 @@ than computing the builtin token up front, as is done for @code{bar}. m4wrap(`define(`foo', defn(`divnum'))foo ') @result{} -m4wrap(`define(`bar', ')m4wrap(defn(`divnum'))m4wrap(`)bar +m4wrap(`define(`bar', 'defn(`divnum')`)bar ') @result{} ^D diff --git a/src/builtin.c b/src/builtin.c index 2e963e3..8ce6cf7 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -678,13 +678,9 @@ define_macro (int argc, macro_arguments *argv, symbol_lookup mode) { case TOKEN_COMP: m4_warn (0, me, _("cannot concatenate builtins")); - /* TODO fall through instead. */ - break; - + /* fallthru */ case TOKEN_TEXT: - /* TODO flatten TOKEN_COMP value, or support concatenation of - builtins in definitions. */ - define_user_macro (ARG (1), ARG_LEN (1), ARG (2), mode); + define_user_macro (ARG (1), ARG_LEN (1), arg_text (argv, 2, true), mode); break; case TOKEN_FUNC: @@ -1012,7 +1008,10 @@ m4_defn (struct obstack *obs, int argc, macro_arguments *argv) } s = lookup_symbol (ARG (i), SYMBOL_LOOKUP); if (s == NULL) - continue; + { + m4_warn (0, me, _("undefined macro `%s'"), ARG (i)); + continue; + } switch (SYMBOL_TYPE (s)) { @@ -1046,10 +1045,10 @@ m4_defn (struct obstack *obs, int argc, macro_arguments *argv) /* Helper macros for readability. */ #if UNIX || defined WEXITSTATUS -# define M4SYSVAL_EXITBITS(status) \ - (WIFEXITED (status) ? WEXITSTATUS (status) : 0) -# define M4SYSVAL_TERMSIGBITS(status) \ - (WIFSIGNALED (status) ? WTERMSIG (status) << 8 : 0) +# define M4SYSVAL_EXITBITS(status) \ + (WIFEXITED (status) ? WEXITSTATUS (status) : 0) +# define M4SYSVAL_TERMSIGBITS(status) \ + (WIFSIGNALED (status) ? WTERMSIG (status) << 8 : 0) #else /* !UNIX && !defined WEXITSTATUS */ /* Platforms such as mingw do not support the notion of reporting diff --git a/src/input.c b/src/input.c index aacab61..df5a791 100644 --- a/src/input.c +++ b/src/input.c @@ -340,18 +340,18 @@ push_string_init (void) | rather than copying everything consecutively onto the input stack. | | Must be called between push_string_init and push_string_finish. | | | -| If TOKEN contains text, then convert the current input block into | -| a chain if it is not one already, and add the contents of TOKEN as | -| a new link in the chain. LEVEL describes the current expansion | -| level, or -1 if TOKEN is composite, its contents reside entirely | -| on the current_input stack, and TOKEN lives in temporary storage. | -| If TOKEN is a simple string, then it belongs to the current macro | -| expansion. If TOKEN is composite, then each text link has a level | -| of -1 if it belongs to the current macro expansion, otherwise it | -| is a back-reference where level tracks which stack it came from. | -| The resulting input block chain contains links with a level of -1 | -| if the text belongs to the input stack, otherwise the level where | -| the back-reference comes from. | +| Convert the current input block into a chain if it is not one | +| already, and add the contents of TOKEN as a new link in the chain. | +| LEVEL describes the current expansion level, or -1 if TOKEN is | +| composite, its contents reside entirely on the current_input | +| stack, and TOKEN lives in temporary storage. If TOKEN is a simple | +| string, then it belongs to the current macro expansion. If TOKEN | +| is composite, then each text link has a level of -1 if it belongs | +| to the current macro expansion, otherwise it is a back-reference | +| where level tracks which stack it came from. The resulting input | +| block chain contains links with a level of -1 if the text belongs | +| to the input stack, otherwise the level where the back-reference | +| comes from. | | | | Return true only if a reference was created to the contents of | | TOKEN, in which case, LEVEL was non-negative and the lifetime of | @@ -1062,19 +1062,35 @@ skip_line (const char *name) | When next_token() sees a builtin token with peek_input, this | | retrieves the value of the function pointer, stores it in TD, and | | consumes the input so the caller does not need to do next_char. | -| If TD is NULL, discard the token instead. | +| If OBS, TD will be converted to a composite token using storage | +| from OBS as necessary; otherwise, if TD is NULL, the builtin is | +| discarded. | `------------------------------------------------------------------*/ static void -init_macro_token (token_data *td) +init_macro_token (struct obstack *obs, token_data *td) { token_chain *chain; assert (isp->type == INPUT_CHAIN); chain = isp->u.u_c.chain; assert (!chain->quote_age && chain->type == CHAIN_FUNC && chain->u.func); - if (td) + if (obs) { + assert (td); + if (TOKEN_DATA_TYPE (td) == TOKEN_VOID) + { + TOKEN_DATA_TYPE (td) = TOKEN_COMP; + td->u.u_c.chain = td->u.u_c.end = NULL; + td->u.u_c.wrapper = false; + td->u.u_c.has_func = true; + } + assert (TOKEN_DATA_TYPE (td) == TOKEN_COMP); + append_macro (obs, chain->u.func, &td->u.u_c.chain, &td->u.u_c.end); + } + else if (td) + { + assert (TOKEN_DATA_TYPE (td) == TOKEN_VOID); TOKEN_DATA_TYPE (td) = TOKEN_FUNC; TOKEN_DATA_FUNC (td) = chain->u.func; } @@ -1597,7 +1613,7 @@ next_token (token_data *td, int *line, struct obstack *obs, bool allow_argv, } if (ch == CHAR_MACRO) { - init_macro_token (td); + init_macro_token (obs, td); #ifdef DEBUG_INPUT xfprintf (stderr, "next_token -> MACDEF (%s)\n", find_builtin_by_addr (TOKEN_DATA_FUNC (td))->name); @@ -1633,10 +1649,7 @@ next_token (token_data *td, int *line, struct obstack *obs, bool allow_argv, _("end of file in comment")); if (ch == CHAR_MACRO) { - /* TODO support concatenation of builtins. */ - m4_warn_at_line (0, file, *line, caller, - _("cannot comment builtin")); - init_macro_token (NULL); + init_macro_token (obs, obs ? td : NULL); continue; } if (MATCH (ch, curr_comm.str2, true)) @@ -1732,35 +1745,8 @@ next_token (token_data *td, int *line, struct obstack *obs, bool allow_argv, _("end of file in string")); if (ch == CHAR_MACRO) - { - /* TODO support concatenation of builtins. */ - if (obstack_object_size (obs_td) == 0 - && TOKEN_DATA_TYPE (td) == TOKEN_VOID) - { - assert (quote_level == 1); - init_macro_token (td); - ch = peek_input (false); - if (MATCH (ch, curr_quote.str2, false)) - { -#ifdef DEBUG_INPUT - const builtin *bp - = find_builtin_by_addr (TOKEN_DATA_FUNC (td)); - xfprintf (stderr, "next_token -> MACDEF (%s)\n", - bp->name); -#endif - ch = next_char (false, false); - MATCH (ch, curr_quote.str2, true); - return TOKEN_MACDEF; - } - TOKEN_DATA_TYPE (td) = TOKEN_VOID; - } - else - init_macro_token (NULL); - m4_warn_at_line (0, file, *line, caller, - _("cannot quote builtin")); - continue; - } - if (ch == CHAR_QUOTE) + init_macro_token (obs, obs ? td : NULL); + else if (ch == CHAR_QUOTE) append_quote_token (obs, td); else if (MATCH (ch, curr_quote.str2, true)) { diff --git a/src/m4.c b/src/m4.c index fe8c548..2ad82c2 100644 --- a/src/m4.c +++ b/src/m4.c @@ -573,7 +573,7 @@ main (int argc, char *const *argv, char *const *envp) case 'l': { - int tmp = atoi (optarg); + long tmp = strtol (optarg, NULL, 10); max_debug_argument_length = tmp <= 0 ? SIZE_MAX : (size_t) tmp; } break; diff --git a/src/m4.h b/src/m4.h index 59d9be3..b3cb7e1 100644 --- a/src/m4.h +++ b/src/m4.h @@ -266,7 +266,7 @@ enum token_type TOKEN_COMMA, /* Active character `,', TOKEN_TEXT. */ TOKEN_CLOSE, /* Active character `)', TOKEN_TEXT. */ TOKEN_SIMPLE, /* Any other single character, TOKEN_TEXT. */ - TOKEN_MACDEF, /* A macro's definition (see "defn"), TOKEN_FUNC. */ + TOKEN_MACDEF, /* A builtin macro, TOKEN_FUNC or TOKEN_COMP. */ TOKEN_ARGV /* A series of parameters, TOKEN_COMP. */ }; @@ -504,7 +504,7 @@ size_t adjust_refcount (int, bool); bool arg_adjust_refcount (macro_arguments *, bool); unsigned int arg_argc (macro_arguments *); token_data_type arg_type (macro_arguments *, unsigned int); -const char *arg_text (macro_arguments *, unsigned int); +const char *arg_text (macro_arguments *, unsigned int, bool); bool arg_equal (macro_arguments *, unsigned int, unsigned int); bool arg_empty (macro_arguments *, unsigned int); size_t arg_len (macro_arguments *, unsigned int); @@ -523,7 +523,7 @@ void wrap_args (macro_arguments *); /* Grab the text at argv index I. Assumes macro_argument *argv is in scope, and aborts if the argument is not text. */ -#define ARG(i) arg_text (argv, i) +#define ARG(i) arg_text (argv, i, false) /* Grab the text length at argv index I. Assumes macro_argument *argv is in scope, and aborts if the argument is not text. */ diff --git a/src/macro.c b/src/macro.c index d871fc2..8290818 100644 --- a/src/macro.c +++ b/src/macro.c @@ -329,18 +329,6 @@ expand_token (struct obstack *obs, token_type t, token_data *td, int line, } -/*---------------------------------------------------------------. -| Helper function to print warning about concatenating FUNC with | -| text. | -`---------------------------------------------------------------*/ -static void -warn_builtin_concat (const char *caller, builtin_func *func) -{ - const builtin *bp = find_builtin_by_addr (func); - assert (bp); - m4_warn (0, caller, _("cannot concatenate builtin `%s'"), bp->name); -} - /*-------------------------------------------------------------------. | This function parses one argument to a macro call. It expects the | | first left parenthesis or the separating comma to have been read | @@ -383,15 +371,10 @@ expand_argument (struct obstack *obs, token_data *argp, const char *caller) case TOKEN_CLOSE: if (paren_level == 0) { - size_t len = obstack_object_size (obs); - if (TOKEN_DATA_TYPE (argp) == TOKEN_FUNC) - { - if (!len) - return t == TOKEN_COMMA; - warn_builtin_concat (caller, TOKEN_DATA_FUNC (argp)); - } + assert (TOKEN_DATA_TYPE (argp) != TOKEN_FUNC); if (TOKEN_DATA_TYPE (argp) != TOKEN_COMP) { + size_t len = obstack_object_size (obs); TOKEN_DATA_TYPE (argp) = TOKEN_TEXT; if (len) { @@ -404,7 +387,16 @@ expand_argument (struct obstack *obs, token_data *argp, const char *caller) TOKEN_DATA_QUOTE_AGE (argp) = age; } else - make_text_link (obs, NULL, &argp->u.u_c.end); + { + make_text_link (obs, NULL, &argp->u.u_c.end); + if (argp->u.u_c.chain == argp->u.u_c.end + && argp->u.u_c.chain->type == CHAIN_FUNC) + { + builtin_func *func = argp->u.u_c.chain->u.func; + TOKEN_DATA_TYPE (argp) = TOKEN_FUNC; + TOKEN_DATA_FUNC (argp) = func; + } + } return t == TOKEN_COMMA; } /* fallthru */ @@ -427,14 +419,13 @@ expand_argument (struct obstack *obs, token_data *argp, const char *caller) case TOKEN_WORD: case TOKEN_STRING: + case TOKEN_MACDEF: if (!expand_token (obs, t, &td, line, first)) age = 0; if (TOKEN_DATA_TYPE (&td) == TOKEN_COMP) { if (TOKEN_DATA_TYPE (argp) != TOKEN_COMP) { - if (TOKEN_DATA_TYPE (argp) == TOKEN_FUNC) - warn_builtin_concat (caller, TOKEN_DATA_FUNC (argp)); TOKEN_DATA_TYPE (argp) = TOKEN_COMP; argp->u.u_c.chain = td.u.u_c.chain; argp->u.u_c.wrapper = argp->u.u_c.has_func = false; @@ -450,22 +441,6 @@ expand_argument (struct obstack *obs, token_data *argp, const char *caller) } break; - case TOKEN_MACDEF: - if (TOKEN_DATA_TYPE (argp) == TOKEN_VOID - && obstack_object_size (obs) == 0) - { - TOKEN_DATA_TYPE (argp) = TOKEN_FUNC; - TOKEN_DATA_FUNC (argp) = TOKEN_DATA_FUNC (&td); - } - else - { - if (TOKEN_DATA_TYPE (argp) == TOKEN_FUNC) - warn_builtin_concat (caller, TOKEN_DATA_FUNC (argp)); - warn_builtin_concat (caller, TOKEN_DATA_FUNC (&td)); - TOKEN_DATA_TYPE (argp) = TOKEN_TEXT; - } - break; - case TOKEN_ARGV: assert (paren_level == 0 && TOKEN_DATA_TYPE (argp) == TOKEN_VOID && obstack_object_size (obs) == 0 @@ -798,6 +773,8 @@ arg_adjust_refcount (macro_arguments *argv, bool increase) if (chain->u.u_s.level >= 0) adjust_refcount (chain->u.u_s.level, increase); break; + case CHAIN_FUNC: + break; case CHAIN_ARGV: assert (chain->u.u_a.argv->inuse); arg_adjust_refcount (chain->u.u_a.argv, increase); @@ -914,10 +891,11 @@ arg_type (macro_arguments *argv, unsigned int arg) /* Given ARGV, return the text at argument ARG. Abort if the argument is not text. Arg 0 is always text, and indices beyond argc return - the empty string. The result is always NUL-terminated, even if it - includes embedded NUL characters. */ + the empty string. If FLATTEN, builtins are ignored. The result is + always NUL-terminated, even if it includes embedded NUL + characters. */ const char * -arg_text (macro_arguments *argv, unsigned int arg) +arg_text (macro_arguments *argv, unsigned int arg, bool flatten) { token_data *token; token_chain *chain; @@ -927,7 +905,7 @@ arg_text (macro_arguments *argv, unsigned int arg) return argv->argv0; if (arg >= argv->argc) return ""; - token = arg_token (argv, arg, NULL, false); + token = arg_token (argv, arg, NULL, flatten); switch (TOKEN_DATA_TYPE (token)) { case TOKEN_TEXT: @@ -942,13 +920,18 @@ arg_text (macro_arguments *argv, unsigned int arg) case CHAIN_STR: obstack_grow (obs, chain->u.u_s.str, chain->u.u_s.len); break; + case CHAIN_FUNC: + if (flatten) + break; + assert (!"arg_text"); + abort (); case CHAIN_ARGV: - assert (!chain->u.u_a.has_func || argv->flatten); + assert (!chain->u.u_a.has_func || flatten || argv->flatten); arg_print (obs, chain->u.u_a.argv, chain->u.u_a.index, quote_cache (NULL, chain->quote_age, chain->u.u_a.quotes), - argv->flatten || chain->u.u_a.flatten, NULL, NULL, - NULL, false); + flatten || argv->flatten || chain->u.u_a.flatten, + NULL, NULL, NULL, false); break; default: assert (!"arg_text"); @@ -969,7 +952,7 @@ arg_text (macro_arguments *argv, unsigned int arg) /* Given ARGV, compare text arguments INDEXA and INDEXB for equality. Both indices must be non-zero and less than argc. Return true if the arguments contain the same contents; often more efficient than - strcmp (arg_text (argv, indexa), arg_text (argv, indexb)) == 0. */ + strcmp (arg_text (argv, a, 1), arg_text (argv, b, 1)) == 0. */ bool arg_equal (macro_arguments *argv, unsigned int indexa, unsigned int indexb) { @@ -1249,6 +1232,7 @@ arg_print (struct obstack *obs, macro_arguments *argv, unsigned int arg, size_t sep_len; size_t *plen = quote_each ? NULL : &len; + flatten |= argv->flatten; if (chainp) assert (!max_len && *chainp); if (!sep) diff --git a/src/output.c b/src/output.c index d7f8570..ee1907b 100644 --- a/src/output.c +++ b/src/output.c @@ -199,7 +199,7 @@ m4_tmpname (int divnum) obstack_1grow (&diversion_storage, '-'); offset = obstack_object_size (&diversion_storage); buffer = (char *) obstack_alloc (&diversion_storage, - INT_BUFSIZE_BOUND (divnum)); + INT_BUFSIZE_BOUND (divnum)); } if (snprintf (&buffer[offset], INT_BUFSIZE_BOUND (divnum), "%d", divnum) < 0) m4_error (EXIT_FAILURE, errno, NULL, @@ -387,7 +387,7 @@ make_room_for (int length) /* The current buffer may be safely reallocated. */ output_diversion->u.buffer = xrealloc (output_diversion->u.buffer, - (size_t) wanted_size); + (size_t) wanted_size); total_buffer_size += wanted_size - output_diversion->size; output_diversion->size = wanted_size; hooks/post-receive -- GNU M4 source repository
