[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[SCM] GNU M4 source repository branch, branch-1.6, updated. v1.5.89a-71-
From: |
Eric Blake |
Subject: |
[SCM] GNU M4 source repository branch, branch-1.6, updated. v1.5.89a-71-g715c421 |
Date: |
Thu, 04 Dec 2008 04:31:21 +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=715c42128d8d357e3e751ec605069137d693c757
The branch, branch-1.6 has been updated
via 715c42128d8d357e3e751ec605069137d693c757 (commit)
from 9f5e389c810aacbd70b04f2530aa52a897cd0ad9 (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 715c42128d8d357e3e751ec605069137d693c757
Author: Eric Blake <address@hidden>
Date: Thu Jan 17 14:34:36 2008 -0700
Stage 27: Allow embedded NUL in text processing macros.
* src/m4.h (evaluate): Add parameter.
* src/builtin.c (compile_pattern) [DEBUG_REGEX]: Support NUL in
output messages.
(set_macro_sequence): Likewise.
(m4_eval): Normalize messages, and adjust caller.
(expand_ranges, substitute): Support NUL in macro expansion.
(m4_translit, m4_regexp, m4_patsubst): Adjust callers, to manage
NUL bytes.
* src/format.c (expand_format): Manage NUL bytes.
* src/eval.c (eval_error): Add EMPTY_ARGUMENT.
(end_text): New variable.
(eval_init_lex): Add parameter.
(eval_lex, evaluate): Detect NUL in macro expansion.
* doc/m4.texinfo (Format): Update to cover new behavior.
(Eval): Mention that result is unquoted.
* examples/null.m4: Enhance test.
* examples/null.err: Update expected output.
* examples/null.out: Likewise.
Signed-off-by: Eric Blake <address@hidden>
(cherry picked from commit 948d1ed0ca4089c2db579fe3d8b3ce172b3e616f)
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 26 ++++++
doc/m4.texinfo | 15 +++-
examples/null.err | Bin 713 -> 1078 bytes
examples/null.m4 | Bin 6499 -> 6667 bytes
examples/null.out | Bin 510 -> 553 bytes
src/builtin.c | 232 ++++++++++++++++++++++++++++++++++------------------
src/eval.c | 33 ++++++--
src/format.c | 43 ++++++----
src/m4.h | 2 +-
9 files changed, 241 insertions(+), 110 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 2085dea..e991a8c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2008-12-03 Eric Blake <address@hidden>
+
+ Stage 27: Allow embedded NUL in text processing macros.
+ Pass NUL through regular expressions, format, and translit, and
+ diagnose it in eval. Improve warning capabilities of format.
+ Memory impact: none.
+ Speed impact: none noticed.
+ * src/m4.h (evaluate): Add parameter.
+ * src/builtin.c (compile_pattern) [DEBUG_REGEX]: Support NUL in
+ output messages.
+ (set_macro_sequence): Likewise.
+ (m4_eval): Normalize messages, and adjust caller.
+ (expand_ranges, substitute): Support NUL in macro expansion.
+ (m4_translit, m4_regexp, m4_patsubst): Adjust callers, to manage
+ NUL bytes.
+ * src/format.c (expand_format): Manage NUL bytes.
+ * src/eval.c (eval_error): Add EMPTY_ARGUMENT.
+ (end_text): New variable.
+ (eval_init_lex): Add parameter.
+ (eval_lex, evaluate): Detect NUL in macro expansion.
+ * doc/m4.texinfo (Format): Update to cover new behavior.
+ (Eval): Mention that result is unquoted.
+ * examples/null.m4: Enhance test.
+ * examples/null.err: Update expected output.
+ * examples/null.out: Likewise.
+
2008-11-28 Eric Blake <address@hidden>
Add extension to divert builtin.
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index 8301bb7..2fb676d 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -6448,7 +6448,7 @@ Likewise, escape sequences are not yet recognized.
@example
format(`%p', `0')
@error{}m4:stdin:1: Warning: format: unrecognized specifier in `%p'
address@hidden
address@hidden
format(`%*d', `')
@error{}m4:stdin:2: Warning: format: empty string treated as 0
@error{}m4:stdin:2: Warning: format: too few arguments: 2 < 3
@@ -6734,7 +6734,9 @@ expansion. The default radix is 10; this is also the
case if
@var{radix} is the empty string. A warning results if the radix is
outside the range of 1 through 36, inclusive. The result of @code{eval}
is always taken to be signed. No radix prefix is output, and for
-radices greater than 10, the digits are lower case. The @var{width}
+radices greater than 10, the digits are lower case (although some
+other implementations use upper case). The output is unquoted, and
+subject to further macro expansion. The @var{width}
argument specifies the minimum output width, excluding any negative
sign. The result is zero-padded to extend the expansion to the
requested width. A warning results if the width is negative. If
@@ -6759,14 +6761,19 @@ eval(`10', `', `0')
eval(`10', `16')
@result{}a
eval(`1', `37')
address@hidden:stdin:9: Warning: eval: radix 37 out of range
address@hidden:stdin:9: Warning: eval: radix out of range: 37
@result{}
eval(`1', , `-1')
address@hidden:stdin:10: Warning: eval: negative width
address@hidden:stdin:10: Warning: eval: negative width: -1
@result{}
eval()
@error{}m4:stdin:11: Warning: eval: empty string treated as 0
@result{}0
+eval(` ')
address@hidden:stdin:12: Warning: eval: empty string treated as 0
address@hidden
+define(`a', `hi')eval(` 10 ', `16')
address@hidden
@end example
@node Shell commands
diff --git a/examples/null.err b/examples/null.err
index 897ce34..977b3b7 100644
Binary files a/examples/null.err and b/examples/null.err differ
diff --git a/examples/null.m4 b/examples/null.m4
index 1823073..e60aec5 100644
Binary files a/examples/null.m4 and b/examples/null.m4 differ
diff --git a/examples/null.out b/examples/null.out
index dd83416..c2c1cb9 100644
Binary files a/examples/null.out and b/examples/null.out differ
diff --git a/src/builtin.c b/src/builtin.c
index 24f2df6..613e1d2 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -311,7 +311,11 @@ compile_pattern (const char *str, size_t len, struct
re_pattern_buffer **buf,
regex_cache[i].count++;
#ifdef DEBUG_REGEX
if (trace_file)
- xfprintf (trace_file, "cached:{%s}\n", str);
+ {
+ fputs ("cached:{", trace_file);
+ fwrite (str, 1, len, trace_file);
+ fputs ("}\n", trace_file);
+ }
#endif /* DEBUG_REGEX */
return NULL;
}
@@ -321,7 +325,11 @@ compile_pattern (const char *str, size_t len, struct
re_pattern_buffer **buf,
msg = re_compile_pattern (str, len, new_buf);
#ifdef DEBUG_REGEX
if (trace_file)
- xfprintf (trace_file, "compile:{%s}\n", str);
+ {
+ fputs ("compile:{", trace_file);
+ fwrite (str, 1, len, trace_file);
+ fputs ("}\n", trace_file);
+ }
#endif /* DEBUG_REGEX */
if (msg)
{
@@ -356,7 +364,11 @@ compile_pattern (const char *str, size_t len, struct
re_pattern_buffer **buf,
{
#ifdef DEBUG_REGEX
if (trace_file)
- xfprintf (trace_file, "flush:{%s}\n", victim->str);
+ {
+ fputs ("flush:{", trace_file);
+ fwrite (victim->str, 1, victim->len, trace_file);
+ fputs ("}\n", trace_file);
+ }
#endif /* DEBUG_REGEX */
free (victim->str);
regfree (victim->buf);
@@ -404,8 +416,8 @@ set_macro_sequence (const char *regexp)
msg = re_compile_pattern (regexp, strlen (regexp), ¯o_sequence_buf);
if (msg != NULL)
m4_error (EXIT_FAILURE, 0, NULL,
- _("--warn-macro-sequence: bad regular expression `%s': %s"),
- regexp, msg);
+ _("--warn-macro-sequence: bad regular expression %s: %s"),
+ quotearg_style (locale_quoting_style, regexp), msg);
re_set_registers (¯o_sequence_buf, ¯o_sequence_regs,
macro_sequence_regs.num_regs,
macro_sequence_regs.start, macro_sequence_regs.end);
@@ -1208,7 +1220,7 @@ m4_eval (struct obstack *obs, int argc, macro_arguments
*argv)
if (radix < 1 || radix > 36)
{
- m4_warn (0, me, _("radix %d out of range"), radix);
+ m4_warn (0, me, _("radix out of range: %d"), radix);
return;
}
@@ -1216,13 +1228,11 @@ m4_eval (struct obstack *obs, int argc, macro_arguments
*argv)
return;
if (min < 0)
{
- m4_warn (0, me, _("negative width"));
+ m4_warn (0, me, _("negative width: %d"), min);
return;
}
- if (arg_empty (argv, 1))
- m4_warn (0, me, _("empty string treated as 0"));
- else if (evaluate (me, ARG (1), &value))
+ if (evaluate (me, ARG (1), ARG_LEN (1), &value))
return;
if (radix == 1)
@@ -1887,34 +1897,42 @@ m4_substr (struct obstack *obs, int argc,
macro_arguments *argv)
obstack_grow (obs, ARG (1) + start, length);
}
-/*------------------------------------------------------------------------.
-| For "translit", ranges are allowed in the second and third argument. |
-| They are expanded in the following function, and the expanded strings, |
-| without any ranges left, are used to translate the characters of the |
-| first argument. A single - (dash) can be included in the strings by |
-| being the first or the last character in the string. If the first |
-| character in a range is after the first in the character set, the range |
-| is made backwards, thus 9-0 is the string 9876543210.
|
-`------------------------------------------------------------------------*/
+/*------------------------------------------------------------------.
+| For "translit", ranges are allowed in the second and third |
+| argument. They are expanded in the following function, and the |
+| expanded strings, without any ranges left, are used to translate |
+| the characters of the first argument. A single - (dash) can be |
+| included in the strings by being the first or the last character |
+| in the string. If the first character in a range is after the |
+| first in the character set, the range is made backwards, thus 9-0 |
+| is the string 9876543210. This function expands S of length *LEN |
+| using OBS for the expansion, sets *LEN to the new length, and |
+| returns the expansion. |
+`------------------------------------------------------------------*/
static const char *
-expand_ranges (const char *s, struct obstack *obs)
+expand_ranges (const char *s, size_t *len, struct obstack *obs)
{
unsigned char from;
unsigned char to;
+ const char *end = s + *len;
+
+ assert (s != end);
+ from = *s++;
+ obstack_1grow (obs, from);
- for (from = '\0'; *s != '\0'; from = to_uchar (*s++))
+ for ( ; s != end; from = *s++)
{
- if (*s == '-' && from != '\0')
+ if (*s == '-')
{
- to = to_uchar (*++s);
- if (to == '\0')
+ if (++s == end)
{
/* trailing dash */
obstack_1grow (obs, '-');
break;
}
- else if (from <= to)
+ to = *s;
+ if (from <= to)
{
while (from++ < to)
obstack_1grow (obs, from);
@@ -1928,7 +1946,7 @@ expand_ranges (const char *s, struct obstack *obs)
else
obstack_1grow (obs, *s);
}
- obstack_1grow (obs, '\0');
+ *len = obstack_object_size (obs);
return (char *) obstack_finish (obs);
}
@@ -1946,25 +1964,32 @@ m4_translit (struct obstack *obs, int argc,
macro_arguments *argv)
const char *data;
const char *from;
const char *to;
+ size_t from_len;
+ size_t to_len;
char map[UCHAR_MAX + 1] = {0};
char found[UCHAR_MAX + 1] = {0};
unsigned char ch;
- if (bad_argc (arg_info (argv), argc, 2, 3))
+ enum { ASIS, REPLACE, DELETE };
+
+ if (bad_argc (arg_info (argv), argc, 2, 3) || arg_empty (argv, 1)
+ || arg_empty (argv, 2))
{
/* builtin(`translit') is blank, but translit(`abc') is abc. */
- if (argc == 2)
+ if (argc >= 2)
push_arg (obs, argv, 1);
return;
}
from = ARG (2);
- if (strchr (from, '-') != NULL)
- from = expand_ranges (from, arg_scratch ());
+ from_len = ARG_LEN (2);
+ if (memchr (from, '-', from_len) != NULL)
+ from = expand_ranges (from, &from_len, arg_scratch ());
to = ARG (3);
- if (strchr (to, '-') != NULL)
- to = expand_ranges (to, arg_scratch ());
+ to_len = ARG_LEN (3);
+ if (memchr (to, '-', to_len) != NULL)
+ to = expand_ranges (to, &to_len, arg_scratch ());
assert (from && to);
@@ -1974,23 +1999,45 @@ m4_translit (struct obstack *obs, int argc,
macro_arguments *argv)
pass of data, for linear behavior. Traditional behavior is that
only the first instance of a character in from is consulted,
hence the found map. */
- for ( ; (ch = *from) != '\0'; from++)
+ while (from_len--)
{
- if (!found[ch])
+ ch = *from++;
+ if (found[ch] == ASIS)
+ {
+ if (to_len)
+ {
+ found[ch] = REPLACE;
+ map[ch] = *to;
+ }
+ else
+ found[ch] = DELETE;
+ }
+ if (to_len)
{
- found[ch] = 1;
- map[ch] = *to;
+ to++;
+ to_len--;
}
- if (*to != '\0')
- to++;
}
- for (data = ARG (1); (ch = *data) != '\0'; data++)
+ data = ARG (1);
+ from_len = ARG_LEN (1);
+ while (from_len--)
{
- if (!found[ch])
- obstack_1grow (obs, ch);
- else if (map[ch])
- obstack_1grow (obs, map[ch]);
+ ch = *data++;
+ switch (found[ch])
+ {
+ case ASIS:
+ obstack_1grow (obs, ch);
+ break;
+ case REPLACE:
+ obstack_1grow (obs, map[ch]);
+ break;
+ case DELETE:
+ break;
+ default:
+ assert (!"m4_translit");
+ abort ();
+ }
}
}
@@ -2020,20 +2067,27 @@ static int substitute_warned = 0;
static void
substitute (struct obstack *obs, const call_info *me, const char *victim,
- const char *repl, struct re_registers *regs)
+ const char *repl, size_t repl_len, struct re_registers *regs)
{
int ch;
- for (;;)
+ while (repl_len--)
{
- while ((ch = *repl++) != '\\')
+ ch = *repl++;
+ if (ch != '\\')
{
- if (ch == '\0')
- return;
obstack_1grow (obs, ch);
+ continue;
+ }
+ if (!repl_len)
+ {
+ m4_warn (0, me, _("trailing \\ ignored in replacement"));
+ return;
}
- switch ((ch = *repl++))
+ ch = *repl++;
+ repl_len--;
+ switch (ch)
{
case '0':
if (!substitute_warned)
@@ -2060,10 +2114,6 @@ substitute (struct obstack *obs, const call_info *me,
const char *victim,
regs->end[ch] - regs->start[ch]);
break;
- case '\0':
- m4_warn (0, me, _("trailing \\ ignored in replacement"));
- return;
-
default:
obstack_1grow (obs, ch);
break;
@@ -2122,26 +2172,36 @@ m4_regexp (struct obstack *obs, int argc,
macro_arguments *argv)
regexp = ARG (2);
repl = ARG (3);
- if (!*regexp)
+ if (arg_empty (argv, 2))
{
/* The empty regex matches everything! */
if (argc == 3)
shipout_int (obs, 0);
else
- substitute (obs, me, victim, repl, NULL);
+ substitute (obs, me, victim, repl, ARG_LEN (3), NULL);
return;
}
#ifdef DEBUG_REGEX
if (trace_file)
- xfprintf (trace_file, "r:{%s}:%s%s%s\n", regexp,
- argc == 3 ? "" : "{", repl, argc == 3 ? "" : "}");
+ {
+ fputs ("r:{", trace_file);
+ fwrite (regexp, 1, ARG_LEN (2), trace_file);
+ if (argc > 3)
+ {
+ fputs ("}:{", trace_file);
+ fwrite (repl, 1, ARG_LEN (3), trace_file);
+ }
+ fputs ("}\n", trace_file);
+ }
#endif /* DEBUG_REGEX */
msg = compile_pattern (regexp, ARG_LEN (2), &buf, ®s);
if (msg != NULL)
{
- m4_warn (0, me, _("bad regular expression: `%s': %s"), regexp, msg);
+ m4_warn (0, me, _("bad regular expression %s: %s"),
+ quotearg_style_mem (locale_quoting_style, regexp, ARG_LEN (2)),
+ msg);
return;
}
@@ -2151,11 +2211,12 @@ m4_regexp (struct obstack *obs, int argc,
macro_arguments *argv)
argc == 3 ? NULL : regs);
if (startpos == -2)
- m4_warn (0, me, _("problem matching regular expression `%s'"), regexp);
+ m4_warn (0, me, _("problem matching regular expression %s"),
+ quotearg_style_mem (locale_quoting_style, regexp, ARG_LEN (2)));
else if (argc == 3)
shipout_int (obs, startpos);
else if (startpos >= 0)
- substitute (obs, me, victim, repl, regs);
+ substitute (obs, me, victim, repl, ARG_LEN (3), regs);
}
/*------------------------------------------------------------------.
@@ -2170,16 +2231,17 @@ static void
m4_patsubst (struct obstack *obs, int argc, macro_arguments *argv)
{
const call_info *me = arg_info (argv);
- const char *victim; /* first argument */
- const char *regexp; /* regular expression */
- const char *repl;
-
- struct re_pattern_buffer *buf;/* compiled regular expression */
- struct re_registers *regs; /* for subexpression matches */
- const char *msg; /* error message from re_compile_pattern */
- int matchpos; /* start position of match */
- int offset; /* current match offset */
- int length; /* length of first argument */
+ const char *victim; /* First argument. */
+ const char *regexp; /* Regular expression. */
+ const char *repl; /* Replacement text. */
+
+ struct re_pattern_buffer *buf;/* Compiled regular expression. */
+ struct re_registers *regs; /* For subexpression matches. */
+ const char *msg; /* Error message from re_compile_pattern. */
+ int matchpos; /* Start position of match. */
+ int offset; /* Current match offset. */
+ int length; /* Length of first argument. */
+ size_t repl_len; /* Length of replacement. */
if (bad_argc (me, argc, 2, 3))
{
@@ -2189,27 +2251,36 @@ m4_patsubst (struct obstack *obs, int argc,
macro_arguments *argv)
return;
}
- victim = ARG (1);
- regexp = ARG (2);
- repl = ARG (3);
-
/* The empty regex matches everywhere, but if there is no
replacement, we need not waste time with it. */
- if (!*regexp && !*repl)
+ if (arg_empty (argv, 2) && arg_empty (argv, 3))
{
push_arg (obs, argv, 1);
return;
}
+ victim = ARG (1);
+ regexp = ARG (2);
+ repl = ARG (3);
+ repl_len = ARG_LEN (3);
+
#ifdef DEBUG_REGEX
if (trace_file)
- xfprintf (trace_file, "p:{%s}:{%s}\n", regexp, repl);
+ {
+ fputs ("p:{", trace_file);
+ fwrite (regexp, 1, ARG_LEN (2), trace_file);
+ fputs ("}:{", trace_file);
+ fwrite (repl, 1, repl_len, trace_file);
+ fputs ("}\n", trace_file);
+ }
#endif /* DEBUG_REGEX */
msg = compile_pattern (regexp, ARG_LEN (2), &buf, ®s);
if (msg != NULL)
{
- m4_warn (0, me, _("bad regular expression `%s': %s"), regexp, msg);
+ m4_warn (0, me, _("bad regular expression %s: %s"),
+ quotearg_style_mem (locale_quoting_style, regexp, ARG_LEN (2)),
+ msg);
return;
}
@@ -2229,8 +2300,9 @@ m4_patsubst (struct obstack *obs, int argc,
macro_arguments *argv)
copied verbatim. */
if (matchpos == -2)
- m4_warn (0, me, _("problem matching regular expression `%s'"),
- regexp);
+ m4_warn (0, me, _("problem matching regular expression %s"),
+ quotearg_style_mem (locale_quoting_style, regexp,
+ ARG_LEN (2)));
else if (offset < length)
obstack_grow (obs, victim + offset, length - offset);
break;
@@ -2243,7 +2315,7 @@ m4_patsubst (struct obstack *obs, int argc,
macro_arguments *argv)
/* Handle the part of the string that was covered by the match. */
- substitute (obs, me, victim, repl, regs);
+ substitute (obs, me, victim, repl, repl_len, regs);
/* Update the offset to the end of the match. If the regexp
matched a null string, advance offset one more, to avoid
diff --git a/src/eval.c b/src/eval.c
index e2e600b..1b617ed 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -58,7 +58,8 @@ typedef enum eval_error
MISSING_RIGHT,
UNKNOWN_INPUT,
EXCESS_INPUT,
- INVALID_OPERATOR
+ INVALID_OPERATOR,
+ EMPTY_ARGUMENT
}
eval_error;
@@ -87,10 +88,15 @@ static const char *eval_text;
can back up, if we have read too much. */
static const char *last_text;
+/* Detect when to end parsing. */
+static const char *end_text;
+
+/* Prime the lexer at the start of TEXT, with length LEN. */
static void
-eval_init_lex (const char *text)
+eval_init_lex (const char *text, size_t len)
{
eval_text = text;
+ end_text = text + len;
last_text = NULL;
}
@@ -105,12 +111,12 @@ eval_undo (void)
static eval_token
eval_lex (int32_t *val)
{
- while (isspace (to_uchar (*eval_text)))
+ while (eval_text != end_text && isspace (to_uchar (*eval_text)))
eval_text++;
last_text = eval_text;
- if (*eval_text == '\0')
+ if (eval_text == end_text)
return EOTEXT;
if (isdigit (to_uchar (*eval_text)))
@@ -287,14 +293,17 @@ eval_lex (int32_t *val)
`---------------------------------------*/
bool
-evaluate (const call_info *me, const char *expr, int32_t *val)
+evaluate (const call_info *me, const char *expr, size_t len, int32_t *val)
{
eval_token et;
eval_error err;
- eval_init_lex (expr);
+ eval_init_lex (expr, len);
et = eval_lex (val);
- err = logical_or_term (me, et, val);
+ if (et == EOTEXT)
+ err = EMPTY_ARGUMENT;
+ else
+ err = logical_or_term (me, et, val);
if (err == NO_ERROR && *eval_text != '\0')
{
@@ -306,9 +315,15 @@ evaluate (const call_info *me, const char *expr, int32_t
*val)
switch (err)
{
+ /* Cases where result is printed. */
case NO_ERROR:
- break;
+ return false;
+
+ case EMPTY_ARGUMENT:
+ m4_warn (0, me, _("empty string treated as 0"));
+ return false;
+ /* Cases where error makes result meaningless. */
case MISSING_RIGHT:
m4_warn (0, me, _("bad expression (missing right parenthesis): %s"),
expr);
@@ -347,7 +362,7 @@ evaluate (const call_info *me, const char *expr, int32_t
*val)
abort ();
}
- return err != NO_ERROR;
+ return true;
}
/*---------------------------.
diff --git a/src/format.c b/src/format.c
index 3325853..8b2b11a 100644
--- a/src/format.c
+++ b/src/format.c
@@ -126,11 +126,12 @@ expand_format (struct obstack *obs, int argc,
macro_arguments *argv)
{
const call_info *me = arg_info (argv);/* Macro name. */
const char *f; /* Format control string. */
+ size_t f_len; /* Length of f. */
const char *fmt; /* Position within f. */
char fstart[] = "%'+- 0#*.*hhd"; /* Current format spec. */
char *p; /* Position within fstart. */
unsigned char c; /* A simple character. */
- int i = 0; /* Index within argc used so far. */
+ int i = 1; /* Index within argc used so far. */
bool valid_format = true; /* True if entire format string ok. */
/* Flags. */
@@ -159,25 +160,24 @@ expand_format (struct obstack *obs, int argc,
macro_arguments *argv)
int result = 0;
enum {CHAR, INT, LONG, DOUBLE, STR} datatype;
- f = fmt = ARG_STR (i, argc, argv);
+ f = fmt = ARG (1);
+ f_len = ARG_LEN (1);
+ assert (!f[f_len]); /* Requiring a terminating NUL makes parsing simpler. */
memset (ok, 0, sizeof ok);
- while (true)
+ while (f_len--)
{
- while ((c = *fmt++) != '%')
+ c = *fmt++;
+ if (c != '%')
{
- if (c == '\0')
- {
- if (valid_format)
- bad_argc (me, argc, i, i);
- return;
- }
obstack_1grow (obs, c);
+ continue;
}
if (*fmt == '%')
{
obstack_1grow (obs, '%');
fmt++;
+ f_len--;
continue;
}
@@ -228,7 +228,7 @@ expand_format (struct obstack *obs, int argc,
macro_arguments *argv)
break;
}
}
- while (!(flags & DONE) && fmt++);
+ while (!(flags & DONE) && (f_len--, fmt++));
if (flags & THOUSANDS)
*p++ = '\'';
if (flags & PLUS)
@@ -250,12 +250,14 @@ expand_format (struct obstack *obs, int argc,
macro_arguments *argv)
{
width = ARG_INT (i, argc, argv);
fmt++;
+ f_len--;
}
else
while (isdigit (to_uchar (*fmt)))
{
width = 10 * width + *fmt - '0';
fmt++;
+ f_len--;
}
/* Maximum precision; an explicit negative precision is the same
@@ -266,10 +268,12 @@ expand_format (struct obstack *obs, int argc,
macro_arguments *argv)
if (*fmt == '.')
{
ok['c'] = 0;
+ f_len--;
if (*(++fmt) == '*')
{
prec = ARG_INT (i, argc, argv);
++fmt;
+ f_len--;
}
else
{
@@ -278,6 +282,7 @@ expand_format (struct obstack *obs, int argc,
macro_arguments *argv)
{
prec = 10 * prec + *fmt - '0';
fmt++;
+ f_len--;
}
}
}
@@ -288,30 +293,34 @@ expand_format (struct obstack *obs, int argc,
macro_arguments *argv)
*p++ = 'l';
lflag = 1;
fmt++;
+ f_len--;
ok['c'] = ok['s'] = 0;
}
else if (*fmt == 'h')
{
*p++ = 'h';
fmt++;
+ f_len--;
if (*fmt == 'h')
{
*p++ = 'h';
fmt++;
+ f_len--;
}
ok['a'] = ok['A'] = ok['c'] = ok['e'] = ok['E'] = ok['f'] = ok['F']
= ok['g'] = ok['G'] = ok['s'] = 0;
}
- c = *fmt++;
- if (c > sizeof ok || !ok[c])
+ c = *fmt;
+ if (c > sizeof ok || !ok[c] || !f_len)
{
- m4_warn (0, me, _("unrecognized specifier in `%s'"), f);
+ m4_warn (0, me, _("unrecognized specifier in %s"),
+ quotearg_style_mem (locale_quoting_style, f, ARG_LEN (1)));
valid_format = false;
- if (c == '\0')
- fmt--;
continue;
}
+ fmt++;
+ f_len--;
/* Specifiers. We don't yet recognize C, S, n, or p. */
switch (c)
@@ -385,4 +394,6 @@ expand_format (struct obstack *obs, int argc,
macro_arguments *argv)
we constructed fstart, the result should not be negative. */
assert (0 <= result);
}
+ if (valid_format)
+ bad_argc (me, argc, i, i);
}
diff --git a/src/m4.h b/src/m4.h
index f643e49..76c697b 100644
--- a/src/m4.h
+++ b/src/m4.h
@@ -549,7 +549,7 @@ FILE *m4_path_search (const char *, char **);
/* File: eval.c --- expression evaluation. */
-bool evaluate (const call_info *, const char *, int32_t *);
+bool evaluate (const call_info *, const char *, size_t, int32_t *);
/* File: format.c --- printf like formatting. */
hooks/post-receive
--
GNU M4 source repository
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [SCM] GNU M4 source repository branch, branch-1.6, updated. v1.5.89a-71-g715c421,
Eric Blake <=