[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[SCM] GNU M4 source repository branch, branch-1_4, updated. v1.4.10b-14-
From: |
Eric Blake |
Subject: |
[SCM] GNU M4 source repository branch, branch-1_4, updated. v1.4.10b-14-gca0ae27 |
Date: |
Wed, 19 Mar 2008 02:08:25 +0000 |
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=ca0ae275710ba45df36fd076b72605345293b54b
The branch, branch-1_4 has been updated
via ca0ae275710ba45df36fd076b72605345293b54b (commit)
from c011c3f82cd89ca40907ace48f8f59215ea600cd (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 ca0ae275710ba45df36fd076b72605345293b54b
Author: Eric Blake <address@hidden>
Date: Mon Dec 3 11:53:45 2007 -0700
Stage 20: make m4wrap obey POSIX fifo ordering.
* src/m4.h (enum token_chain_type): Add CHAIN_LOC.
(struct token_chain): Add u_l member.
(wrap_args): New prototype.
* src/input.c (push_wrapup_init, push_wrapup_finish): Rewrite to
guarantee a FIFO chain in the wrapup stack.
(pop_input, peek_input, next_char_1): Support location link.
(next_char): Add parameter.
(init_macro_token, init_argv_token): Require user to consume empty
input.
(skip_line, match_input): Adjust callers.
(next_token): Always consume first character.
* src/macro.c (arg_text): Tighten assertion.
(wrap_args): New method.
* src/builtin.c (m4_m4wrap): Use it.
(define_macro): Issue warning when ignoring builtin token during
macro definition.
* doc/m4.texinfo (M4wrap, Location, Incompatibilities)
(Improved m4wrap): Adjust examples to corrected behavior.
* NEWS: Document this fix.
(cherry picked from commit f7f45337fa1bfba9512841e8d3d2251359944681)
Signed-off-by: Eric Blake <address@hidden>
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 28 ++++++++++++
NEWS | 4 ++
doc/m4.texinfo | 49 ++++++++++++++--------
src/builtin.c | 26 ++++++-----
src/input.c | 126 +++++++++++++++++++++++++++++++++++--------------------
src/m4.h | 10 ++++-
src/macro.c | 68 ++++++++++++++++++++++++++++--
7 files changed, 230 insertions(+), 81 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 3c4e2ad..49f9b80 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2008-03-19 Eric Blake <address@hidden>
+
+ Stage 20: make m4wrap obey POSIX fifo ordering.
+ Improve input engine to support location changes within symbol
+ chains, then convert m4wrap to always build symbol chain. Also,
+ avoid wasted peek at start of next_token, for fewer ungetc calls.
+ Memory impact: none.
+ Speed impact: noticeable improvement, from fewer function calls.
+ * src/m4.h (enum token_chain_type): Add CHAIN_LOC.
+ (struct token_chain): Add u_l member.
+ (wrap_args): New prototype.
+ * src/input.c (push_wrapup_init, push_wrapup_finish): Rewrite to
+ guarantee a FIFO chain in the wrapup stack.
+ (pop_input, peek_input, next_char_1): Support location link.
+ (next_char): Add parameter.
+ (init_macro_token, init_argv_token): Require user to consume empty
+ input.
+ (skip_line, match_input): Adjust callers.
+ (next_token): Always consume first character.
+ * src/macro.c (arg_text): Tighten assertion.
+ (wrap_args): New method.
+ * src/builtin.c (m4_m4wrap): Use it.
+ (define_macro): Issue warning when ignoring builtin token during
+ macro definition.
+ * doc/m4.texinfo (M4wrap, Location, Incompatibilities)
+ (Improved m4wrap): Adjust examples to corrected behavior.
+ * NEWS: Document this fix.
+
2008-03-17 Eric Blake <address@hidden>
Update for fresh bootstrap.
diff --git a/NEWS b/NEWS
index 7dc3aba..53f7282 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,10 @@ Foundation, Inc.
** Fix regression introduced in 1.4.10b where using `builtin' or `indir'
to perform nested `shift' calls triggered an assertion failure.
+** Fix the `m4wrap' builtin to accumulate wrapped text in FIFO order, as
+ required by POSIX. The manual mentions a way to restore the LIFO order
+ present in earlier GNU M4 versions.
+
** Enhance the `ifdef', `ifelse', and `shift' builtins, as well as all
user macros, to transparently handle builtin tokens generated by `defn'.
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index f0fbb96..67f1765 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -4582,6 +4582,9 @@ Stores @var{string} in a safe place, to be reread when
end of input is
reached. As a @acronym{GNU} extension, additional arguments are
concatenated with a space to the @var{string}.
+Successive invocations of @code{m4wrap} accumulate saved text in
+first-in, first-out order, as required by @acronym{POSIX}.
+
The expansion of @code{m4wrap} is void.
The macro @code{m4wrap} is recognized only with parameters.
@end deffn
@@ -4601,18 +4604,27 @@ This is the first and last normal input line.
The saved input is only reread when the end of normal input is seen, and
not if @code{m4exit} is used to exit @code{m4}.
address@hidden FIXME: this contradicts POSIX, which requires that "If the
address@hidden m4wrap macro is used multiple times, the arguments specified
address@hidden shall be processed in the order in which the m4wrap macros were
address@hidden processed."
-It is safe to call @code{m4wrap} from saved text, but then the order in
-which the saved text is reread is undefined. If @code{m4wrap} is not used
-recursively, the saved pieces of text are reread in the opposite order
-in which they were saved (LIFO---last in, first out). However, this
-behavior is likely to change in a future release, to match
address@hidden, so you should not depend on this order.
-
-It is possible to emulate @acronym{POSIX} behavior even
+It is safe to call @code{m4wrap} from wrapped text, where all the
+recursively wrapped text is deferred until the current wrapped text is
+exhausted. As of M4 1.4.11, when @code{m4wrap} is not used recursively,
+the saved pieces of text are reread in the same order in which they were
+saved (FIFO---first in, first out), as required by @acronym{POSIX}.
+
address@hidden
+m4wrap(`1
+')
address@hidden
+m4wrap(`2', `3
+')
address@hidden
+^D
address@hidden
address@hidden 3
address@hidden example
+
+However, earlier versions had reverse ordering (LIFO---last in, first
+out), as this behavior is more like the semantics of the C function
address@hidden It is possible to emulate @acronym{POSIX} behavior even
with older versions of @acronym{GNU} M4 by including the file
@address@hidden/@/examples/@/wrapfifo.m4} from the
distribution:
@@ -4688,13 +4700,13 @@ Invocations of @code{m4wrap} at the same recursion
level are
concatenated and rescanned as usual:
@example
-define(`aa', `AA
+define(`ab', `AB
')
@result{}
-m4wrap(`a')m4wrap(`a')
+m4wrap(`a')m4wrap(`b')
@result{}
^D
address@hidden
address@hidden
@end example
@noindent
@@ -6613,9 +6625,9 @@ m4wrap(`__line__
')
@result{}
^D
address@hidden
@result{}6
@result{}6
address@hidden
@end example
The @address@hidden macro behaves like @samp{$0} in shell
@@ -7057,7 +7069,8 @@ of @samp{-} on the command line.
@item
@acronym{POSIX} requires @code{m4wrap} (@pxref{M4wrap}) to act in FIFO
-(first-in, first-out) order, but @acronym{GNU} @code{m4} currently uses
+(first-in, first-out) order, and most other implementations obey this.
+However, versions of @acronym{GNU} @code{m4} earlier than 1.4.11 used
LIFO order. Furthermore, @acronym{POSIX} states that only the first
argument to @code{m4wrap} is saved for later evaluation, but
@acronym{GNU} @code{m4} saves and processes all arguments, with output
@@ -7745,8 +7758,8 @@ builtin(`m4wrap', ``'define(`bar',
``$0:'-$1-$*-$#-')bar(`a', `b')
')
@result{}
^D
address@hidden:-a-a,b-2-
@result{}m4wrap0:---0-
address@hidden:-a-a,b-2-
@end example
Additionally, the computation of @code{_m4wrap_level} and creation of
diff --git a/src/builtin.c b/src/builtin.c
index a441c4c..b5541cf 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -667,7 +667,14 @@ define_macro (int argc, macro_arguments *argv,
symbol_lookup mode)
switch (arg_type (argv, 2))
{
+ case TOKEN_COMP:
+ m4_warn (0, me, _("cannot concatenate builtins"));
+ /* TODO fall through instead. */
+ break;
+
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);
break;
@@ -1608,25 +1615,20 @@ m4_m4exit (struct obstack *obs, int argc,
macro_arguments *argv)
exit (exit_code);
}
-/*-------------------------------------------------------------------------.
-| Save the argument text until EOF has been seen, allowing for user |
-| specified cleanup action. GNU version saves all arguments, the standard |
-| version only the first. |
-`-------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------.
+| Save the argument text in FIFO order until EOF has been seen, |
+| allowing for user specified cleanup action. Extra arguments are |
+| saved when not in POSIX mode. |
+`-----------------------------------------------------------------*/
static void
m4_m4wrap (struct obstack *obs, int argc, macro_arguments *argv)
{
if (bad_argc (ARG (0), argc, 1, -1))
return;
- obs = push_wrapup_init ();
- if (no_gnu_extensions)
- obstack_grow (obs, ARG (1), ARG_LEN (1));
- else
- /* TODO - allow builtins, rather than always flattening. */
- arg_print (obs, argv, 1, NULL, true, " ", NULL, false);
- push_wrapup_finish ();
+ wrap_args (argv);
}
+
/* Enable tracing of all specified macros, or all, if none is specified.
Tracing is disabled by default, when a macro is defined. This can be
diff --git a/src/input.c b/src/input.c
index b8784d0..86db704 100644
--- a/src/input.c
+++ b/src/input.c
@@ -529,12 +529,36 @@ struct obstack *
push_wrapup_init (void)
{
input_block *i;
- i = (input_block *) obstack_alloc (wrapup_stack, sizeof *i);
- i->prev = wsp;
- i->type = INPUT_STRING;
- i->file = current_file;
- i->line = current_line;
- wsp = i;
+ token_chain *chain;
+
+ assert (obstack_object_size (wrapup_stack) == 0);
+ if (wsp)
+ {
+ i = wsp;
+ assert (i->type == INPUT_CHAIN && i->u.u_c.end
+ && i->u.u_c.end->type != CHAIN_LOC);
+ }
+ else
+ {
+ i = (input_block *) obstack_alloc (wrapup_stack, sizeof *i);
+ i->prev = wsp;
+ i->file = current_file;
+ i->line = current_line;
+ i->type = INPUT_CHAIN;
+ i->u.u_c.chain = i->u.u_c.end = NULL;
+ wsp = i;
+ }
+ chain = (token_chain *) obstack_alloc (wrapup_stack, sizeof *chain);
+ if (i->u.u_c.end)
+ i->u.u_c.end->next = chain;
+ else
+ i->u.u_c.chain = chain;
+ i->u.u_c.end = chain;
+ 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;
return wrapup_stack;
}
@@ -545,17 +569,7 @@ push_wrapup_init (void)
void
push_wrapup_finish (void)
{
- input_block *i = wsp;
- if (obstack_object_size (wrapup_stack) == 0)
- {
- wsp = i->prev;
- obstack_free (wrapup_stack, i);
- }
- else
- {
- i->u.u_s.len = obstack_object_size (wrapup_stack);
- i->u.u_s.str = (char *) obstack_finish (wrapup_stack);
- }
+ make_text_link (wrapup_stack, &wsp->u.u_c.chain, &wsp->u.u_c.end);
}
@@ -610,6 +624,8 @@ pop_input (bool cleanup)
return false;
arg_adjust_refcount (chain->u.u_a.argv, false);
break;
+ case CHAIN_LOC:
+ return false;
default:
assert (!"pop_input");
abort ();
@@ -837,6 +853,8 @@ peek_input (bool allow_argv)
chain->u.u_a.comma = true;
push_string_finish ();
return peek_input (allow_argv);
+ case CHAIN_LOC:
+ break;
default:
assert (!"peek_input");
abort ();
@@ -863,16 +881,18 @@ peek_input (bool allow_argv)
| string, so factor that out into a macro for speed. If |
| ALLOW_QUOTE, and the current input matches the current quote age, |
| return CHAR_QUOTE and leave consumption of data for |
-| append_quote_token. |
+| append_quote_token; otherwise, if ALLOW_ARGV and the current input |
+| matches an argv reference with the correct quoting, return |
+| CHAR_ARGV and leave consuption of data for init_argv_token. |
`-------------------------------------------------------------------*/
-#define next_char(AQ) \
+#define next_char(AQ, AA) \
(isp && isp->type == INPUT_STRING && isp->u.u_s.len && !input_change \
? (isp->u.u_s.len--, to_uchar (*isp->u.u_s.str++)) \
- : next_char_1 (AQ))
+ : next_char_1 (AQ, AA))
static int
-next_char_1 (bool allow_quote)
+next_char_1 (bool allow_quote, bool allow_argv)
{
int ch;
token_chain *chain;
@@ -929,6 +949,7 @@ next_char_1 (bool allow_quote)
chain = isp->u.u_c.chain;
while (chain)
{
+ unsigned int argc;
if (allow_quote && chain->quote_age == current_quote_age)
return CHAR_QUOTE;
switch (chain->type)
@@ -949,7 +970,8 @@ next_char_1 (bool allow_quote)
return CHAR_MACRO;
break;
case CHAIN_ARGV:
- if (chain->u.u_a.index == arg_argc (chain->u.u_a.argv))
+ argc = arg_argc (chain->u.u_a.argv);
+ if (chain->u.u_a.index == argc)
{
arg_adjust_refcount (chain->u.u_a.argv, false);
break;
@@ -959,6 +981,12 @@ next_char_1 (bool allow_quote)
chain->u.u_a.comma = false;
return ',';
}
+ /* Only return a reference if the quoting is correct
+ and the reference has more than one argument
+ left. */
+ if (allow_argv && chain->quote_age == current_quote_age
+ && chain->u.u_a.quotes && chain->u.u_a.index + 1 < argc)
+ return CHAR_ARGV;
/* Rather than directly parse argv here, we push
another input block containing the next unparsed
argument from argv. */
@@ -970,7 +998,13 @@ next_char_1 (bool allow_quote)
chain->u.u_a.index++;
chain->u.u_a.comma = true;
push_string_finish ();
- return next_char_1 (allow_quote);
+ return next_char_1 (allow_quote, allow_argv);
+ case CHAIN_LOC:
+ isp->file = chain->u.u_l.file;
+ isp->line = chain->u.u_l.line;
+ input_change = true;
+ isp->u.u_c.chain = chain->next;
+ return next_char_1 (allow_quote, allow_argv);
default:
assert (!"next_char_1");
abort ();
@@ -1002,7 +1036,7 @@ skip_line (const char *name)
const char *file = current_file;
int line = current_line;
- while ((ch = next_char (false)) != CHAR_EOF && ch != '\n')
+ 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
@@ -1028,25 +1062,28 @@ skip_line (const char *name)
static void
init_macro_token (token_data *td)
{
- int ch = next_char (false);
- assert (ch == CHAR_MACRO);
- if (td)
- TOKEN_DATA_TYPE (td) = TOKEN_FUNC;
+ token_chain *chain;
+
if (isp->type == INPUT_MACRO)
{
assert (isp->u.func);
if (td)
- TOKEN_DATA_FUNC (td) = isp->u.func;
+ {
+ TOKEN_DATA_TYPE (td) = TOKEN_FUNC;
+ TOKEN_DATA_FUNC (td) = isp->u.func;
+ }
isp->u.func = NULL;
}
else
{
- 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)
- TOKEN_DATA_FUNC (td) = chain->u.func;
+ {
+ TOKEN_DATA_TYPE (td) = TOKEN_FUNC;
+ TOKEN_DATA_FUNC (td) = chain->u.func;
+ }
chain->u.func = NULL;
}
}
@@ -1108,9 +1145,9 @@ init_argv_token (struct obstack *obs, token_data *td)
{
token_chain *src_chain;
token_chain *chain;
- int ch = next_char (true);
+ int ch;
- assert (ch == CHAR_QUOTE && TOKEN_DATA_TYPE (td) == TOKEN_VOID
+ assert (TOKEN_DATA_TYPE (td) == TOKEN_VOID
&& isp->type == INPUT_CHAIN && isp->u.u_c.chain->type == CHAIN_ARGV
&& obs && obstack_object_size (obs) == 0);
@@ -1146,7 +1183,7 @@ init_argv_token (struct obstack *obs, token_data *td)
decreased once the final element is parsed. */
assert (*curr_comm.str1 != ',' && *curr_comm.str1 != ')'
&& *curr_comm.str1 != *curr_quote.str1);
- ch = peek_input (false);
+ ch = peek_input (true);
if (ch != ',' && ch != ')')
{
isp->u.u_c.chain = src_chain;
@@ -1181,14 +1218,14 @@ match_input (const char *s, bool consume)
if (s[1] == '\0')
{
if (consume)
- next_char (false);
+ next_char (false, false);
return true; /* short match */
}
- next_char (false);
+ next_char (false, false);
for (n = 1, t = s++; (ch = peek_input (false)) == to_uchar (*s++); )
{
- next_char (false);
+ next_char (false, false);
n++;
if (*s == '\0') /* long match */
{
@@ -1556,15 +1593,13 @@ next_token (token_data *td, int *line, struct obstack
*obs, bool allow_argv,
if (!line)
line = &dummy;
- /* Can't consume character until after CHAR_MACRO is handled. */
TOKEN_DATA_TYPE (td) = TOKEN_VOID;
- ch = peek_input (allow_argv && current_quote_age);
+ ch = next_char (false, allow_argv && current_quote_age);
if (ch == CHAR_EOF)
{
#ifdef DEBUG_INPUT
xfprintf (stderr, "next_token -> EOF\n");
#endif /* DEBUG_INPUT */
- next_char (false);
return TOKEN_EOF;
}
if (ch == CHAR_MACRO)
@@ -1588,7 +1623,6 @@ next_token (token_data *td, int *line, struct obstack
*obs, bool allow_argv,
return TOKEN_ARGV;
}
- next_char (false); /* Consume character we already peeked at. */
file = current_file;
*line = current_line;
if (MATCH (ch, curr_comm.str1, true))
@@ -1598,7 +1632,7 @@ next_token (token_data *td, int *line, struct obstack
*obs, bool allow_argv,
obstack_grow (obs_td, curr_comm.str1, curr_comm.len1);
while (1)
{
- ch = next_char (false);
+ 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. */
@@ -1629,7 +1663,7 @@ next_token (token_data *td, int *line, struct obstack
*obs, bool allow_argv,
&& (isalnum (ch) || ch == '_'))
{
obstack_1grow (&token_stack, ch);
- next_char (false);
+ next_char (false, false);
}
type = TOKEN_WORD;
}
@@ -1652,7 +1686,7 @@ next_token (token_data *td, int *line, struct obstack
*obs, bool allow_argv,
obstack_blank (&token_stack, -1);
break;
}
- next_char (false);
+ next_char (false, false);
}
obstack_1grow (&token_stack, '\0');
@@ -1697,7 +1731,7 @@ next_token (token_data *td, int *line, struct obstack
*obs, bool allow_argv,
type = TOKEN_STRING;
while (1)
{
- ch = next_char (obs != NULL && current_quote_age);
+ 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. */
@@ -1721,7 +1755,7 @@ next_token (token_data *td, int *line, struct obstack
*obs, bool allow_argv,
xfprintf (stderr, "next_token -> MACDEF (%s)\n",
bp->name);
#endif
- ch = next_char (false);
+ ch = next_char (false, false);
MATCH (ch, curr_quote.str2, true);
return TOKEN_MACDEF;
}
diff --git a/src/m4.h b/src/m4.h
index ef45359..3e7fc76 100644
--- a/src/m4.h
+++ b/src/m4.h
@@ -283,7 +283,8 @@ enum token_chain_type
{
CHAIN_STR, /* Link contains a string, u.u_s is valid. */
CHAIN_FUNC, /* Builtin function definition, u.func is valid. */
- CHAIN_ARGV /* Link contains a $@ reference, u.u_a is valid. */
+ CHAIN_ARGV, /* Link contains a $@ reference, u.u_a is valid. */
+ CHAIN_LOC /* Link contains location of m4wrap, u.u_l is valid. */
};
/* Composite tokens are built of a linked list of chains. Each link
@@ -315,6 +316,12 @@ struct token_chain
const string_pair *quotes; /* NULL for $*, quotes for
address@hidden */
}
u_a;
+ struct
+ {
+ const char *file; /* File where subsequent links originate. */
+ int line; /* Line where subsequent links originate. */
+ }
+ u_l;
}
u;
};
@@ -508,6 +515,7 @@ void push_arg (struct obstack *, macro_arguments *,
unsigned int);
void push_arg_quote (struct obstack *, macro_arguments *, unsigned int,
const string_pair *);
void push_args (struct obstack *, macro_arguments *, bool, bool);
+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. */
diff --git a/src/macro.c b/src/macro.c
index f794d86..6a6a90c 100644
--- a/src/macro.c
+++ b/src/macro.c
@@ -946,11 +946,8 @@ arg_text (macro_arguments *argv, unsigned int index)
case CHAIN_STR:
obstack_grow (obs, chain->u.u_s.str, chain->u.u_s.len);
break;
- case CHAIN_FUNC:
- /* TODO concatenate builtins. */
- assert (!"implemented");
- abort ();
case CHAIN_ARGV:
+ assert (!chain->u.u_a.has_func || 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),
@@ -1515,3 +1512,66 @@ push_args (struct obstack *obs, macro_arguments *argv,
bool skip, bool quote)
if (push_token (token, -1, argv->inuse))
arg_mark (argv);
}
+
+/* Push arguments from ARGV, which can include builtins, onto the wrap
+ stack for later rescanning. If GNU extensions are disabled, only
+ the first argument is pushed; otherwise, all arguments are pushed
+ and separated with a space. */
+void
+wrap_args (macro_arguments *argv)
+{
+ int i;
+ struct obstack *obs;
+ token_data *token;
+ token_chain *chain;
+
+ if ((argv->argc == 2 || no_gnu_extensions) && arg_empty (argv, 1))
+ return;
+
+ obs = push_wrapup_init ();
+ for (i = 1; i < (no_gnu_extensions ? 2 : argv->argc); i++)
+ {
+ if (i != 1)
+ obstack_1grow (obs, ' ');
+ token = arg_token (argv, i, NULL, false);
+ switch (TOKEN_DATA_TYPE (token))
+ {
+ case TOKEN_TEXT:
+ obstack_grow (obs, TOKEN_DATA_TEXT (token), TOKEN_DATA_LEN (token));
+ break;
+ case TOKEN_FUNC:
+ /* TODO allow builtins through m4wrap. */
+ assert (false);
+ case TOKEN_COMP:
+ chain = token->u.u_c.chain;
+ while (chain)
+ {
+ switch (chain->type)
+ {
+ case CHAIN_STR:
+ obstack_grow (obs, chain->u.u_s.str, chain->u.u_s.len);
+ break;
+ case CHAIN_FUNC:
+ /* TODO allow builtins through m4wrap. */
+ assert (false);
+ break;
+ case CHAIN_ARGV:
+ arg_print (obs, chain->u.u_a.argv, chain->u.u_a.index,
+ quote_cache (NULL, chain->quote_age,
+ chain->u.u_a.quotes),
+ chain->u.u_a.flatten, NULL, NULL, false);
+ break;
+ default:
+ assert (!"wrap_args");
+ abort ();
+ }
+ chain = chain->next;
+ }
+ break;
+ default:
+ assert (!"wrap_args");
+ abort ();
+ }
+ }
+ push_wrapup_finish ();
+}
hooks/post-receive
--
GNU M4 source repository
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [SCM] GNU M4 source repository branch, branch-1_4, updated. v1.4.10b-14-gca0ae27,
Eric Blake <=