[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. branch-cvs-r
From: |
Eric Blake |
Subject: |
[SCM] GNU M4 source repository branch, branch-1_4, updated. branch-cvs-readonly-35-ge2b843f |
Date: |
Fri, 21 Dec 2007 05:34:45 +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=e2b843f0aca9e296495f592e39d6a8cec69c6e8a
The branch, branch-1_4 has been updated
via e2b843f0aca9e296495f592e39d6a8cec69c6e8a (commit)
from c947bf47f48f9132155bc623596771e4a4e3f732 (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 e2b843f0aca9e296495f592e39d6a8cec69c6e8a
Author: Eric Blake <address@hidden>
Date: Fri Oct 26 09:24:06 2007 -0600
Stage 9: share rather than copy single-arg refs.
* m4/gnulib-cache.m4: Import quote and memmem modules.
* src/m4.h (arg_scratch): New prototype.
* src/input.c (INPUT_INLINE_THRESHOLD): New define.
(push_token): Use it to inline short text, and save references to
longer text.
(input_init, next_token): Simplify obstack handling.
* src/macro.c (expand_argument): Likewise.
(expand_macro): Track scratch space.
(arg_scratch): New function.
(make_argv_ref): Use it.
(push_args): Likewise, and simplify comma handling, since most
separators are short enough to be inlined.
* src/builtin.c (builtin_init): Avoid cast.
(m4_errprint, m4_index): Transparently support NUL.
(m4_translit): Use scratch space, rather than leaking memory on
expansion stack.
* doc/m4.texinfo (Syntax): Add new test of embedded NUL.
* checks/get-them: Extract test that uses external files.
* checks/check-them: Run the new test. Use unified diff if
possible, and force text mode when debugging NUL handling.
* examples/null.m4: New file.
* examples/null.out: Likewise.
* examples/null.err: Likewise.
* examples/Makefile.am (EXTRA_FILES): Distribute these files.
* .gitattributes: Treat new files as text, in spite of embedded
NUL.
(cherry picked from commit a6c94a314afa34958330b719d66c2d4e403a94af)
Signed-off-by: Eric Blake <address@hidden>
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 30 +++++++++++++++++++
checks/check-them | 30 ++++++++++++++++---
checks/get-them | 20 +++++++++++++
doc/m4.texinfo | 12 ++++++++
examples/.gitattributes | 1 +
examples/Makefile.am | 3 ++
examples/null.err | Bin 0 -> 18 bytes
examples/null.m4 | Bin 0 -> 3671 bytes
examples/null.out | Bin 0 -> 338 bytes
m4/gnulib-cache.m4 | 4 +-
src/builtin.c | 37 ++++++++++-------------
src/input.c | 47 +++++++++++++++++++------------
src/m4.h | 1 +
src/macro.c | 72 ++++++++++++++++++++++++++++------------------
14 files changed, 183 insertions(+), 74 deletions(-)
create mode 100644 examples/.gitattributes
create mode 100644 examples/null.err
create mode 100644 examples/null.m4
create mode 100644 examples/null.out
diff --git a/ChangeLog b/ChangeLog
index 2b2a0d0..e6fee41 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2007-12-21 Eric Blake <address@hidden>
+
+ Stage 9: share rather than copy single-arg refs.
+ * m4/gnulib-cache.m4: Import quote and memmem modules.
+ * src/m4.h (arg_scratch): New prototype.
+ * src/input.c (INPUT_INLINE_THRESHOLD): New define.
+ (push_token): Use it to inline short text, and save references to
+ longer text.
+ (input_init, next_token): Simplify obstack handling.
+ * src/macro.c (expand_argument): Likewise.
+ (expand_macro): Track scratch space.
+ (arg_scratch): New function.
+ (make_argv_ref): Use it.
+ (push_args): Likewise, and simplify comma handling, since most
+ separators are short enough to be inlined.
+ * src/builtin.c (builtin_init): Avoid cast.
+ (m4_errprint, m4_index): Transparently support NUL.
+ (m4_translit): Use scratch space, rather than leaking memory on
+ expansion stack.
+ * doc/m4.texinfo (Syntax): Add new test of embedded NUL.
+ * checks/get-them: Extract test that uses external files.
+ * checks/check-them: Run the new test. Use unified diff if
+ possible, and force text mode when debugging NUL handling.
+ * examples/null.m4: New file.
+ * examples/null.out: Likewise.
+ * examples/null.err: Likewise.
+ * examples/Makefile.am (EXTRA_FILES): Distribute these files.
+ * .gitattributes: Treat new files as text, in spite of embedded
+ NUL.
+
2007-12-18 Eric Blake <address@hidden>
Stage 8: extend life of references into argv.
diff --git a/checks/check-them b/checks/check-them
index b446f47..daa1b00 100755
--- a/checks/check-them
+++ b/checks/check-them
@@ -27,6 +27,7 @@ xerr=$tmp/m4-xerr
failed=
skipped=
strip_needed=false
+diffopts=-c
# Find out how the executable prints argv[0]
m4=`m4 --help | sed -e 's/Usage: \(.*\) \[OPTION.*/\1/' \
@@ -49,6 +50,14 @@ if test "x$1" = x-I ; then
shift; shift
fi
+# Find out if diff supports useful options.
+if diff -u /dev/null /dev/null 2>/dev/null ; then
+ diffopts="-u"
+fi
+if diff -a /dev/null /dev/null 2>/dev/null ; then
+ diffopts="$diffopts -a"
+fi
+
# Run the tests.
for file
do
@@ -77,9 +86,20 @@ do
;;
esac
- sed -e '/^dnl @result{}/!d' -e 's///' -e "s|\.\./examples|$examples|" \
- "$file" > $xout
- sed -e '/^dnl @error{}/!d' -e 's///' -e "s|^m4:|$m4:|" "$file" > $xerr
+ xoutfile=`sed -n 's/^dnl @ expected output: //p' "$file"`
+ if test -z "$xoutfile" ; then
+ sed -e '/^dnl @result{}/!d' -e 's///' -e "s|\.\./examples|$examples|" \
+ "$file" > $xout
+ else
+ cp "$examples/$xoutfile" $xout
+ fi
+
+ xerrfile=`sed -n 's/^dnl @ expected error: //p' "$file"`
+ if test -z "$xerrfile" ; then
+ sed -e '/^dnl @error{}/!d' -e 's///' -e "s|^m4:|$m4:|" "$file" > $xerr
+ else
+ cp "$examples/$xerrfile" $xerr
+ fi
# For the benefit of mingw, normalize \r\n line endings
if $strip_needed ; then
@@ -99,7 +119,7 @@ do
failed="$failed $file:out"
echo `sed -e 's/^dnl //' -e 1q $file`
echo "$file: stdout mismatch"
- diff $xout $out
+ diff $diffopts $xout $out
fi
if cmp -s $err $xerr; then
@@ -108,7 +128,7 @@ do
failed="$failed $file:err"
echo `sed -e 's/^dnl //' -e 1q $file`
echo "$file: stderr mismatch"
- diff $xerr $err
+ diff $diffopts $xerr $err
fi
done
diff --git a/checks/get-them b/checks/get-them
index 0d3e37b..e034962 100755
--- a/checks/get-them
+++ b/checks/get-them
@@ -16,6 +16,8 @@ BEGIN {
file = "NONE";
status = 0;
options = "";
+ xout = "";
+ xerr = "";
}
/address@hidden / {
@@ -39,6 +41,8 @@ BEGIN {
getline;
status = 0;
options = "";
+ xout = "";
+ xout = "";
next;
}
@@ -51,6 +55,16 @@ BEGIN {
gsub ("@comment options:", "", options);
}
+/address@hidden xout: / {
+ xout = $0;
+ gsub ("@comment xout: ", "", xout);
+}
+
+/address@hidden xerr: / {
+ xerr = $0;
+ gsub ("@comment xerr: ", "", xerr);
+}
+
/address@hidden/, /address@hidden example$/ {
if (seq < 0)
next;
@@ -68,8 +82,14 @@ BEGIN {
"dnl @ gives unlimited permission to copy and/or distribute it\n"\
"dnl @ with or without modifications, as long as this notice\n"\
"dnl @ is preserved.\n", FILENAME, NR, status, options) > file;
+ if (xout)
+ printf("dnl @ expected output: %s\n", xout) > file;
+ if (xerr)
+ printf("dnl @ expected error: %s\n", xerr) > file;
status = 0;
options = "";
+ xout = "";
+ xerr = "";
next;
}
if ($0 ~ /address@hidden example$/) {
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index eaec266..bfdb6f2 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -923,6 +923,18 @@ use address@hidden characters in quoted strings
(@pxref{Changequote}),
comments (@pxref{Changecom}), and macro names (@pxref{Indir}), with the
exception of the @sc{nul} character (the zero byte @samp{'\0'}).
address@hidden
address@hidden FIXME - each builtin needs to document how it handles NUL, then
address@hidden update the above paragraph to mention that NUL is now handled
address@hidden transparently. Meanwhile, test that we don't regress.
+
address@hidden xout: null.out
address@hidden xerr: null.err
address@hidden
+include(`null.m4')dnl
address@hidden example
address@hidden ignore
+
@menu
* Names:: Macro names
* Quoted strings:: Quoting input to @code{m4}
diff --git a/examples/.gitattributes b/examples/.gitattributes
new file mode 100644
index 0000000..b35e74c
--- /dev/null
+++ b/examples/.gitattributes
@@ -0,0 +1 @@
+null.* diff merge
diff --git a/examples/Makefile.am b/examples/Makefile.am
index c1dc522..3450eac 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -45,6 +45,9 @@ indir.m4 \
loop.m4 \
misc.m4 \
multiquotes.m4 \
+null.err \
+null.m4 \
+null.out \
patsubst.m4 \
pushpop.m4 \
quote.m4 \
diff --git a/examples/null.err b/examples/null.err
new file mode 100644
index 0000000..61518e8
Binary files /dev/null and b/examples/null.err differ
diff --git a/examples/null.m4 b/examples/null.m4
new file mode 100644
index 0000000..904a6ef
Binary files /dev/null and b/examples/null.m4 differ
diff --git a/examples/null.out b/examples/null.out
new file mode 100644
index 0000000..6e8a114
Binary files /dev/null and b/examples/null.out differ
diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4
index a89650c..3112f91 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 assert avltree-oset binary-io clean-temp cloexec
close-stream closein config-h error fdl fflush flexmember fopen-safer free
fseeko gendocs getopt gnupload gpl-3.0 mkstemp obstack regex stdbool stdint
stdlib-safer strtol unlocked-io 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 assert avltree-oset binary-io clean-temp cloexec
close-stream closein config-h error fdl fflush flexmember fopen-safer free
fseeko gendocs getopt gnupload gpl-3.0 memmem mkstemp obstack quote regex
stdbool stdint stdlib-safer strtol unlocked-io verror version-etc
version-etc-fsf xalloc xprintf xvasprintf-posix
# Specification in the form of a few gnulib-tool.m4 macro invocations:
gl_LOCAL_DIR([local])
-gl_MODULES([assert avltree-oset binary-io clean-temp cloexec close-stream
closein config-h error fdl fflush flexmember fopen-safer free fseeko gendocs
getopt gnupload gpl-3.0 mkstemp obstack regex stdbool stdint stdlib-safer
strtol unlocked-io verror version-etc version-etc-fsf xalloc xprintf
xvasprintf-posix])
+gl_MODULES([assert avltree-oset binary-io clean-temp cloexec close-stream
closein config-h error fdl fflush flexmember fopen-safer free fseeko gendocs
getopt gnupload gpl-3.0 memmem mkstemp obstack quote regex stdbool stdint
stdlib-safer strtol unlocked-io verror version-etc version-etc-fsf xalloc
xprintf xvasprintf-posix])
gl_AVOID([])
gl_SOURCE_BASE([lib])
gl_M4_BASE([m4])
diff --git a/src/builtin.c b/src/builtin.c
index e8edc4b..cb5f274 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -463,9 +463,10 @@ 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 = (char *) xmalloc (strlen (bp->name) + 4);
+ string = xcharalloc (len + 4);
strcpy (string, "m4_");
strcat (string, bp->name);
define_builtin (string, bp, SYMBOL_INSERT);
@@ -1514,12 +1515,16 @@ m4_mkstemp (struct obstack *obs, int argc,
macro_arguments *argv)
static void
m4_errprint (struct obstack *obs, int argc, macro_arguments *argv)
{
+ size_t len;
+
if (bad_argc (ARG (0), argc, 1, -1))
return;
dump_args (obs, 1, argv, " ", false);
- obstack_1grow (obs, '\0');
debug_flush_files ();
- xfprintf (stderr, "%s", (char *) obstack_finish (obs));
+ len = obstack_object_size (obs);
+ /* The close_stdin module makes it safe to skip checking the return
+ value here. */
+ fwrite (obstack_finish (obs), 1, len, stderr);
fflush (stderr);
}
@@ -1770,14 +1775,10 @@ m4_index (struct obstack *obs, int argc,
macro_arguments *argv)
haystack = ARG (1);
needle = ARG (2);
- /* Optimize searching for the empty string (always 0) and one byte
- (strchr tends to be more efficient than strstr). */
- if (!needle[0])
- retval = 0;
- else if (!needle[1])
- result = strchr (haystack, *needle);
- else
- result = strstr (haystack, needle);
+ /* Rely on the optimizations guaranteed by gnulib's memmem
+ module. */
+ result = (char *) memmem (haystack, arg_len (argv, 1),
+ needle, arg_len (argv, 2));
if (result)
retval = result - haystack;
@@ -1895,19 +1896,13 @@ m4_translit (struct obstack *obs, int argc,
macro_arguments *argv)
from = ARG (2);
if (strchr (from, '-') != NULL)
- {
- from = expand_ranges (from, obs);
- if (from == NULL)
- return;
- }
+ from = expand_ranges (from, arg_scratch ());
to = ARG (3);
if (strchr (to, '-') != NULL)
- {
- to = expand_ranges (to, obs);
- if (to == NULL)
- return;
- }
+ to = expand_ranges (to, arg_scratch ());
+
+ assert (from && to);
/* Calling strchr(from) for each character in data is quadratic,
since both strings can be arbitrarily long. Instead, create a
diff --git a/src/input.c b/src/input.c
index 8386061..1753be2 100644
--- a/src/input.c
+++ b/src/input.c
@@ -64,6 +64,11 @@
# include "regex.h"
#endif /* ENABLE_CHANGEWORD */
+/* Number of bytes where it is more efficient to inline the reference
+ as a string than it is to track reference bookkeeping for those
+ bytes. */
+#define INPUT_INLINE_THRESHOLD 16
+
/* Type of an input block. */
enum input_type
{
@@ -319,18 +324,29 @@ push_string_init (void)
| gathering input from multiple locations, rather than copying |
| everything consecutively onto the input stack. Must be called |
| between push_string_init and push_string_finish. Return true only |
-| if LEVEL is non-negative, and a reference was created to TOKEN. |
+| if LEVEL is non-negative, and a reference was created to TOKEN, in |
+| which case, the lifetime of TOKEN and its contents must last as |
+| long as the input engine can parse references to it. |
`-------------------------------------------------------------------*/
bool
push_token (token_data *token, int level)
{
token_chain *chain;
+ bool result = false;
assert (next);
/* TODO - also accept TOKEN_COMP chains. */
assert (TOKEN_DATA_TYPE (token) == TOKEN_TEXT);
- if (TOKEN_DATA_LEN (token) == 0)
- return false;
+
+ /* Speed consideration - for short enough tokens, the speed and
+ memory overhead of parsing another INPUT_CHAIN link outweighs the
+ time to inline the token text. */
+ if (TOKEN_DATA_LEN (token) <= INPUT_INLINE_THRESHOLD)
+ {
+ obstack_grow (current_input, TOKEN_DATA_TEXT (token),
+ TOKEN_DATA_LEN (token));
+ return false;
+ }
if (next->type == INPUT_STRING)
{
@@ -345,21 +361,18 @@ push_token (token_data *token, int level)
next->u.u_c.chain = chain;
next->u.u_c.end = chain;
chain->next = NULL;
- if (level >= 0)
- /* TODO - use token as-is, rather than copying data. This implies
- lengthening lifetime of $@ arguments until the rescan is
- complete, rather than the current approach of freeing them
- during expand_macro. */
- chain->str = (char *) obstack_copy (current_input, TOKEN_DATA_TEXT (token),
- TOKEN_DATA_LEN (token));
- else
- chain->str = TOKEN_DATA_TEXT (token);
+ chain->str = TOKEN_DATA_TEXT (token);
chain->len = TOKEN_DATA_LEN (token);
- chain->level = -1;
+ chain->level = level;
chain->argv = NULL;
chain->index = 0;
chain->flatten = false;
- return false; /* No reference exists when text is copied. */
+ if (level >= 0)
+ {
+ adjust_refcount (level, true);
+ result = true;
+ }
+ return result;
}
/*-------------------------------------------------------------------.
@@ -897,8 +910,7 @@ input_init (void)
will always work even if the first token parsed spills to a new
chunk. */
obstack_init (&token_stack);
- obstack_alloc (&token_stack, 1);
- token_bottom = obstack_base (&token_stack);
+ token_bottom = obstack_finish (&token_stack);
isp = NULL;
wsp = NULL;
@@ -1230,8 +1242,7 @@ next_token (token_data *td, int *line, const char *caller)
if (startpos != 0 ||
regs.end [0] != obstack_object_size (&token_stack))
{
- *(((char *) obstack_base (&token_stack)
- + obstack_object_size (&token_stack)) - 1) = '\0';
+ obstack_blank (&token_stack, -1);
break;
}
next_char ();
diff --git a/src/m4.h b/src/m4.h
index 854f28d..ce78455 100644
--- a/src/m4.h
+++ b/src/m4.h
@@ -449,6 +449,7 @@ bool arg_equal (macro_arguments *, unsigned int, unsigned
int);
bool arg_empty (macro_arguments *, unsigned int);
size_t arg_len (macro_arguments *, unsigned int);
builtin_func *arg_func (macro_arguments *, unsigned int);
+struct obstack *arg_scratch (void);
macro_arguments *make_argv_ref (macro_arguments *, const char *, size_t,
bool, bool);
void push_arg (struct obstack *, macro_arguments *, unsigned int);
diff --git a/src/macro.c b/src/macro.c
index 63d957d..964be5b 100644
--- a/src/macro.c
+++ b/src/macro.c
@@ -29,7 +29,10 @@
#endif /* DEBUG_MACRO */
/* Opaque structure describing all arguments to a macro, including the
- macro name at index 0. */
+ macro name at index 0. The lifetime of argv0 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 address@hidden */
struct macro_arguments
{
/* Number of arguments owned by this object, may be larger than
@@ -368,16 +371,17 @@ 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 (obstack_object_size (obs) == 0)
+ if (!len)
return t == TOKEN_COMMA;
warn_builtin_concat (caller, TOKEN_DATA_FUNC (argp));
}
- TOKEN_DATA_TYPE (argp) = TOKEN_TEXT;
- TOKEN_DATA_LEN (argp) = obstack_object_size (obs);
obstack_1grow (obs, '\0');
+ TOKEN_DATA_TYPE (argp) = TOKEN_TEXT;
TOKEN_DATA_TEXT (argp) = (char *) obstack_finish (obs);
+ TOKEN_DATA_LEN (argp) = len;
TOKEN_DATA_QUOTE_AGE (argp) = age;
return t == TOKEN_COMMA;
}
@@ -533,6 +537,7 @@ static void
expand_macro (symbol *sym)
{
void *args_base; /* Base of stacks[i].args on entry. */
+ void *args_scratch; /* Base of scratch space for call_macro. */
void *argv_base; /* Base of stacks[i].argv on entry. */
macro_arguments *argv; /* Arguments to the called macro. */
struct obstack *expansion; /* Collects the macro's expansion. */
@@ -594,6 +599,7 @@ expand_macro (symbol *sym)
trace_prepre (SYMBOL_NAME (sym), my_call_id);
argv = collect_arguments (sym, stacks[level].args, stacks[level].argv);
+ args_scratch = obstack_finish (stacks[level].args);
/* The actual macro call. */
loc_close_file = current_file;
@@ -633,6 +639,7 @@ expand_macro (symbol *sym)
{
if (argv->inuse)
{
+ obstack_free (stacks[level].args, args_scratch);
if (debug_macro_level & PRINT_ARGCOUNT_CHANGES)
xfprintf (debug, "m4debug: -%d- `%s' in use, level=%d, "
"refcount=%zu, argcount=%zu\n", my_call_id, argv->argv0,
@@ -850,6 +857,16 @@ arg_func (macro_arguments *argv, unsigned int index)
return TOKEN_DATA_FUNC (token);
}
+/* Return an obstack useful for scratch calculations that will not
+ interfere with macro expansion. The obstack will be reset when
+ expand_macro completes. */
+struct obstack *
+arg_scratch (void)
+{
+ assert (obstack_object_size (stacks[expansion_level - 1].args) == 0);
+ return stacks[expansion_level - 1].args;
+}
+
/* Create a new argument object using the same obstack as ARGV; thus,
the new object will automatically be freed when the original is
freed. Explicitly set the macro name (argv[0]) from ARGV0 with
@@ -865,9 +882,8 @@ make_argv_ref (macro_arguments *argv, const char *argv0,
size_t argv0_len,
token_data *token;
token_chain *chain;
unsigned int index = skip ? 2 : 1;
- struct obstack *obs = stacks[expansion_level - 1].argv;
+ struct obstack *obs = arg_scratch ();
- assert (obstack_object_size (obs) == 0);
/* When making a reference through a reference, point to the
original if possible. */
if (argv->has_ref)
@@ -924,6 +940,8 @@ push_arg (struct obstack *obs, macro_arguments *argv,
unsigned int index)
if (index == 0)
{
+ /* Always push copy of arg 0, since its lifetime is not
+ guaranteed beyond expand_macro. */
obstack_grow (obs, argv->argv0, argv->argv0_len);
return;
}
@@ -944,44 +962,42 @@ void
push_args (struct obstack *obs, macro_arguments *argv, bool skip, bool quote)
{
token_data *token;
- token_data sep;
unsigned int i = skip ? 2 : 1;
+ const char *sep = ",";
+ size_t sep_len = 1;
bool use_sep = false;
bool inuse = false;
- static char comma[2] = ",";
+ struct obstack *scratch = arg_scratch ();
if (i >= argv->argc)
return;
- TOKEN_DATA_TYPE (&sep) = TOKEN_TEXT;
- TOKEN_DATA_QUOTE_AGE (&sep) = 0;
- if (quote)
+ if (i + 1 == argv->argc)
{
- char *str;
- obstack_grow (obs, lquote.string, lquote.length);
- TOKEN_DATA_LEN (&sep) = obstack_object_size (obs);
- obstack_1grow (obs, '\0');
- str = (char *) obstack_finish (obs);
- TOKEN_DATA_TEXT (&sep) = str;
- push_token (&sep, -1);
- obstack_grow (obs, rquote.string, rquote.length);
- obstack_1grow (obs, ',');
- obstack_grow0 (obs, lquote.string, lquote.length);
- str = (char *) obstack_finish (obs);
- TOKEN_DATA_TEXT (&sep) = str;
- TOKEN_DATA_LEN (&sep) = rquote.length + 1 + lquote.length;
+ if (quote)
+ obstack_grow (obs, lquote.string, lquote.length);
+ push_arg (obs, argv, i);
+ if (quote)
+ obstack_grow (obs, rquote.string, rquote.length);
+ return;
}
- else
+
+ /* Compute the separator in the scratch space. */
+ if (quote)
{
- TOKEN_DATA_TEXT (&sep) = comma;
- TOKEN_DATA_LEN (&sep) = 1;
+ obstack_grow (obs, lquote.string, lquote.length);
+ obstack_grow (scratch, rquote.string, rquote.length);
+ obstack_1grow (scratch, ',');
+ obstack_grow0 (scratch, lquote.string, lquote.length);
+ sep = (char *) obstack_finish (scratch);
+ sep_len += lquote.length + rquote.length;
}
/* TODO push entire $@ reference, rather than pushing each arg. */
for ( ; i < argv->argc; i++)
{
token = arg_token (argv, i);
if (use_sep)
- push_token (&sep, -1);
+ obstack_grow (obs, sep, sep_len);
else
use_sep = true;
/* TODO handle func tokens? */
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. branch-cvs-readonly-35-ge2b843f,
Eric Blake <=