summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2007-12-19 17:16:28 -0700
committerEric Blake <ebb9@byu.net>2008-06-17 06:30:53 -0600
commit40c640f486bf7a99c6e16d91332f25872f501488 (patch)
treea9379e4a249893c6ad8b9212c545320ee13c1987
parent6167507cf07ddbc838e14e3d66803b360e63f6f2 (diff)
downloadm4-40c640f486bf7a99c6e16d91332f25872f501488.tar.gz
Stage25: allow NUL in quote, comment delimiters
-rw-r--r--doc/m4.texinfo7
-rw-r--r--examples/null.errbin505 -> 572 bytes
-rw-r--r--examples/null.m4bin5891 -> 6189 bytes
-rw-r--r--examples/null.outbin404 -> 468 bytes
-rw-r--r--m4/gnulib-cache.m44
-rw-r--r--src/builtin.c64
-rw-r--r--src/debug.c88
-rw-r--r--src/format.c47
-rw-r--r--src/freeze.c29
-rw-r--r--src/input.c175
-rw-r--r--src/m4.h59
-rw-r--r--src/output.c23
-rw-r--r--src/path.c6
13 files changed, 207 insertions, 295 deletions
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index be8a0d9c..d6b7b59f 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -7006,12 +7006,13 @@ ifdef(`__unix__', ,
`errprint(` skipping: syscmd does not have unix semantics
')m4exit(`77')')dnl
changequote(`[', `]')dnl
-syscmd([printf 'define(-\0-,hi)dnl
+syscmd([printf 'define(-\0-,hi)changequote([,\0])changecom(--\0)dnl
divert(1)undivert(null.out)' | ]__program__[ -F in.m4f \
- && printf 'errprint(indir(-\0-))' | ]__program__[ -R in.m4f \
+ && printf 'errprint([divnum\0] #-- indir(-\0-))' \
+ | ]__program__[ -R in.m4f \
&& rm in.m4f])errprint([ ]sysval[
])dnl
-@error{}hi 0
+@error{}divnum #-- hi 0
@end example
@end ignore
diff --git a/examples/null.err b/examples/null.err
index 05a1ba3c..5f989ee6 100644
--- a/examples/null.err
+++ b/examples/null.err
Binary files differ
diff --git a/examples/null.m4 b/examples/null.m4
index c9283605..de76742a 100644
--- a/examples/null.m4
+++ b/examples/null.m4
Binary files differ
diff --git a/examples/null.out b/examples/null.out
index 66f41b55..5e90221e 100644
--- a/examples/null.out
+++ b/examples/null.out
Binary files differ
diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4
index cb115a0d..dffdf8d1 100644
--- a/m4/gnulib-cache.m4
+++ b/m4/gnulib-cache.m4
@@ -15,11 +15,11 @@
# Specification in the form of a command-line invocation:
-# gnulib-tool --import --dir=. --local-dir=local --lib=libm4 --source-base=lib --m4-base=m4 --doc-base=doc --aux-dir=build-aux --with-tests --no-libtool --macro-prefix=M4 announce-gen assert avltree-oset binary-io clean-temp cloexec close-stream closein config-h error fdl fflush flexmember fopen-safer freadptr freadseek fseeko gendocs getopt git-version-gen gnumakefile gnupload gpl-3.0 intprops memchr2 memmem mkstemp obstack quote regex stdbool stdint stdlib-safer strtod strtol unlocked-io vasnprintf-posix verror version-etc version-etc-fsf xalloc xmemdup0 xprintf xvasprintf-posix
+# gnulib-tool --import --dir=. --local-dir=local --lib=libm4 --source-base=lib --m4-base=m4 --doc-base=doc --aux-dir=build-aux --with-tests --no-libtool --macro-prefix=M4 announce-gen assert autobuild avltree-oset binary-io c-stack clean-temp cloexec close-stream closein config-h error fdl fflush flexmember fopen-safer freadptr freadseek fseeko gendocs getopt git-version-gen gnumakefile gnupload gpl-3.0 intprops memchr2 memmem mkstemp obstack obstack-printf-posix progname quote regex stdbool stdint stdlib-safer strtod strtol unlocked-io vasnprintf-posix verror version-etc version-etc-fsf xalloc xmemdup0 xprintf xvasprintf-posix
# Specification in the form of a few gnulib-tool.m4 macro invocations:
gl_LOCAL_DIR([local])
-gl_MODULES([announce-gen assert avltree-oset binary-io clean-temp cloexec close-stream closein config-h error fdl fflush flexmember fopen-safer freadptr freadseek fseeko gendocs getopt git-version-gen gnumakefile gnupload gpl-3.0 intprops memchr2 memmem mkstemp obstack quote regex stdbool stdint stdlib-safer strtod strtol unlocked-io vasnprintf-posix verror version-etc version-etc-fsf xalloc xmemdup0 xprintf xvasprintf-posix])
+gl_MODULES([announce-gen assert autobuild avltree-oset binary-io c-stack clean-temp cloexec close-stream closein config-h error fdl fflush flexmember fopen-safer freadptr freadseek fseeko gendocs getopt git-version-gen gnumakefile gnupload gpl-3.0 intprops memchr2 memmem mkstemp obstack obstack-printf-posix progname quote regex stdbool stdint stdlib-safer strtod strtol unlocked-io vasnprintf-posix verror version-etc version-etc-fsf xalloc xmemdup0 xprintf xvasprintf-posix])
gl_AVOID([])
gl_SOURCE_BASE([lib])
gl_M4_BASE([m4])
diff --git a/src/builtin.c b/src/builtin.c
index 0fd7331e..c171ea96 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -586,7 +586,7 @@ numeric_arg (const call_info *name, const char *arg, int *valuep)
/* Digits for number to ascii conversions. */
static char const digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-const char *
+static const char *
ntoa (int32_t value, int radix)
{
bool negative;
@@ -628,10 +628,7 @@ ntoa (int32_t value, int radix)
static void
shipout_int (struct obstack *obs, int val)
{
- const char *s;
-
- s = ntoa ((int32_t) val, 10);
- obstack_grow (obs, s, strlen (s));
+ obstack_printf (obs, "%d", val);
}
@@ -907,11 +904,10 @@ m4_dumpdef (struct obstack *obs, int argc, macro_arguments *argv)
{
case TOKEN_TEXT:
if (debug_level & DEBUG_TRACE_QUOTE)
- DEBUG_PRINT3 ("%s%s%s\n",
- curr_quote.str1, SYMBOL_TEXT (data.base[0]),
- curr_quote.str2);
- else
- DEBUG_PRINT1 ("%s\n", SYMBOL_TEXT (data.base[0]));
+ fwrite (curr_quote.str1, 1, curr_quote.len1, debug);
+ fputs (SYMBOL_TEXT (data.base[0]), debug);
+ if (debug_level & DEBUG_TRACE_QUOTE)
+ fwrite (curr_quote.str2, 1, curr_quote.len2, debug);
break;
case TOKEN_FUNC:
@@ -921,7 +917,7 @@ m4_dumpdef (struct obstack *obs, int argc, macro_arguments *argv)
assert (!"m4_dumpdef");
abort ();
}
- DEBUG_PRINT1 ("<%s>\n", bp->name);
+ xfprintf (debug, "<%s>", bp->name);
break;
default:
@@ -929,6 +925,7 @@ m4_dumpdef (struct obstack *obs, int argc, macro_arguments *argv)
abort ();
break;
}
+ fputc ('\n', debug);
}
}
@@ -1210,11 +1207,14 @@ m4_eval (struct obstack *obs, int argc, macro_arguments *argv)
obstack_1grow (obs, '-');
value = -value;
}
- /* This assumes 2's-complement for correctly handling INT_MIN. */
- while (min-- - value > 0)
- obstack_1grow (obs, '0');
- while (value-- != 0)
- obstack_1grow (obs, '1');
+ if ((uint32_t) value < min)
+ {
+ obstack_blank (obs, min - value);
+ memset ((char *) obstack_next_free (obs) - (min - value), '0',
+ min - value);
+ }
+ obstack_blank (obs, value);
+ memset ((char *) obstack_next_free (obs) - value, '1', value);
return;
}
@@ -1226,10 +1226,9 @@ m4_eval (struct obstack *obs, int argc, macro_arguments *argv)
s++;
}
len = strlen (s);
- for (min -= len; --min >= 0;)
- obstack_1grow (obs, '0');
-
- obstack_grow (obs, s, len);
+ if (min < len)
+ min = len;
+ obstack_printf (obs, "%.*d%s", min - len, 0, s);
}
static void
@@ -1377,8 +1376,8 @@ m4_changequote (struct obstack *obs, int argc, macro_arguments *argv)
bad_argc (arg_info (argv), argc, 0, 2);
/* Explicit NULL distinguishes between empty and missing argument. */
- set_quotes ((argc >= 2) ? ARG (1) : NULL,
- (argc >= 3) ? ARG (2) : NULL);
+ set_quotes ((argc >= 2) ? ARG (1) : NULL, ARG_LEN (1),
+ (argc >= 3) ? ARG (2) : NULL, ARG_LEN (2));
}
/*--------------------------------------------------------------------.
@@ -1392,8 +1391,8 @@ m4_changecom (struct obstack *obs, int argc, macro_arguments *argv)
bad_argc (arg_info (argv), argc, 0, 2);
/* Explicit NULL distinguishes between empty and missing argument. */
- set_comment ((argc >= 2) ? ARG (1) : NULL,
- (argc >= 3) ? ARG (2) : NULL);
+ set_comment ((argc >= 2) ? ARG (1) : NULL, ARG_LEN (1),
+ (argc >= 3) ? ARG (2) : NULL, ARG_LEN (2));
}
#ifdef ENABLE_CHANGEWORD
@@ -1534,23 +1533,20 @@ m4_maketemp (struct obstack *obs, int argc, macro_arguments *argv)
const char *str = ARG (1);
size_t len = ARG_LEN (1);
size_t i;
- size_t len2;
+ struct obstack *scratch = arg_scratch ();
+ size_t pid_len = obstack_printf (scratch, "%lu",
+ (unsigned long) getpid ());
+ char *pid = (char *) obstack_copy0 (scratch, "", 0);
m4_warn (0, me, _("recommend using mkstemp instead"));
for (i = len; i > 1; i--)
if (str[i - 1] != 'X')
break;
obstack_grow (obs, str, i);
- str = ntoa ((int32_t) getpid (), 10);
- len2 = strlen (str);
- if (len2 > len - i)
- obstack_grow (obs, str + len2 - (len - i), len - i);
+ if (len - i < pid_len)
+ obstack_grow (obs, pid + pid_len - (len - i), len - i);
else
- {
- while (i++ < len - len2)
- obstack_1grow (obs, '0');
- obstack_grow (obs, str, len2);
- }
+ obstack_printf (obs, "%.*d%s", len - i - pid_len, 0, pid);
}
else
mkstemp_helper (obs, me, ARG (1), ARG_LEN (1));
diff --git a/src/debug.c b/src/debug.c
index 2b2388f4..c3f85bd6 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -215,17 +215,25 @@ debug_set_output (const call_info *caller, const char *name)
`-----------------------------------------------------------------------*/
void
-debug_message_prefix (void)
+debug_message (const char *format, ...)
{
- xfprintf (debug, "m4debug:");
- if (current_line)
- {
- if (debug_level & DEBUG_TRACE_FILE)
- xfprintf (debug, "%s:", current_file);
- if (debug_level & DEBUG_TRACE_LINE)
- xfprintf (debug, "%d:", current_line);
- }
- putc (' ', debug);
+ va_list args;
+ if (debug)
+ {
+ xfprintf (debug, "m4debug:");
+ if (current_line)
+ {
+ if (debug_level & DEBUG_TRACE_FILE)
+ xfprintf (debug, "%s:", current_file);
+ if (debug_level & DEBUG_TRACE_LINE)
+ xfprintf (debug, "%d:", current_line);
+ }
+ putc (' ', debug);
+ va_start (args, format);
+ xvfprintf (debug, format, args);
+ va_end (args);
+ putc ('\n', debug);
+ }
}
/* The rest of this file contains the functions for macro tracing output.
@@ -234,55 +242,6 @@ debug_message_prefix (void)
output from interfering with other debug messages generated by the
various builtins. */
-/*-------------------------------------------------------------------.
-| Tracing output to the obstack is formatted here, by a simplified |
-| printf-like function trace_format (). Understands only %s (1 arg: |
-| text), %d (1 arg: integer). |
-`-------------------------------------------------------------------*/
-
-static void
-trace_format (const char *fmt, ...)
-{
- va_list args;
- char ch;
- int d;
- const char *s;
- size_t maxlen;
-
- va_start (args, fmt);
-
- while (true)
- {
- while ((ch = *fmt++) != '\0' && ch != '%')
- obstack_1grow (&trace, ch);
-
- if (ch == '\0')
- break;
-
- maxlen = SIZE_MAX;
- switch (*fmt++)
- {
- case 's':
- s = va_arg (args, const char *);
- break;
-
- case 'd':
- d = va_arg (args, int);
- s = ntoa (d, 10);
- break;
-
- default:
- s = "";
- break;
- }
-
- if (shipout_string_trunc (&trace, s, SIZE_MAX, &maxlen))
- break;
- }
-
- va_end (args);
-}
-
/*------------------------------------------------------------------.
| Format the standard header attached to all tracing output lines, |
| using the context in INFO as appropriate. Return the offset into |
@@ -294,14 +253,15 @@ trace_header (const call_info *info)
{
int trace_level = info->debug_level;
unsigned int result = obstack_object_size (&trace);
- trace_format ("m4trace:");
+
+ obstack_grow (&trace, "m4trace:", 8);
if (trace_level & DEBUG_TRACE_FILE)
- trace_format ("%s:", info->file);
+ obstack_printf (&trace, "%s:", info->file);
if (trace_level & DEBUG_TRACE_LINE)
- trace_format ("%d:", info->line);
- trace_format (" -%d- ", expansion_level);
+ obstack_printf (&trace, "%d:", info->line);
+ obstack_printf (&trace, " -%d- ", expansion_level);
if (trace_level & DEBUG_TRACE_CALLID)
- trace_format ("id %d: ", info->call_id);
+ obstack_printf (&trace, "id %d: ", info->call_id);
return result;
}
diff --git a/src/format.c b/src/format.c
index c783d11e..33258534 100644
--- a/src/format.c
+++ b/src/format.c
@@ -156,9 +156,7 @@ expand_format (struct obstack *obs, int argc, macro_arguments *argv)
char ok[128];
/* Buffer and stuff. */
- char *base; /* Current position in obs. */
- size_t len; /* Length of formatted text. */
- char *str; /* Malloc'd buffer of formatted text. */
+ int result = 0;
enum {CHAR, INT, LONG, DOUBLE, STR} datatype;
f = fmt = ARG_STR (i, argc, argv);
@@ -352,56 +350,39 @@ expand_format (struct obstack *obs, int argc, macro_arguments *argv)
}
*p++ = c;
*p = '\0';
- base = obstack_next_free (obs);
- len = obstack_room (obs);
switch (datatype)
{
case CHAR:
- str = asnprintf (base, &len, fstart, width,
- ARG_INT (i, argc, argv));
+ result = obstack_printf (obs, fstart, width,
+ ARG_INT (i, argc, argv));
break;
case INT:
- str = asnprintf (base, &len, fstart, width, prec,
- ARG_INT (i, argc, argv));
+ result = obstack_printf (obs, fstart, width, prec,
+ ARG_INT (i, argc, argv));
break;
case LONG:
- str = asnprintf (base, &len, fstart, width, prec,
- ARG_LONG (i, argc, argv));
+ result = obstack_printf (obs, fstart, width, prec,
+ ARG_LONG (i, argc, argv));
break;
case DOUBLE:
- str = asnprintf (base, &len, fstart, width, prec,
- ARG_DOUBLE (i, argc, argv));
+ result = obstack_printf (obs, fstart, width, prec,
+ ARG_DOUBLE (i, argc, argv));
break;
case STR:
- str = asnprintf (base, &len, fstart, width, prec,
- ARG_STR (i, argc, argv));
+ result = obstack_printf (obs, fstart, width, prec,
+ ARG_STR (i, argc, argv));
break;
default:
abort ();
}
-
- if (str == NULL)
- /* NULL is unexpected (EILSEQ and EINVAL are not possible
- based on our construction of fstart, leaving only ENOMEM,
- which should always be fatal). */
- m4_error (EXIT_FAILURE, errno, me,
- _("unable to format output for `%s'"), f);
- else if (str == base)
- /* The output was already computed in place, but we need to
- account for its size. */
- obstack_blank_fast (obs, len);
- else
- {
- /* The output exceeded available obstack space, copy the
- allocated string. */
- obstack_grow (obs, str, len);
- free (str);
- }
+ /* Since obstack_printf can only fail with EILSEQ or EINVAL, but
+ we constructed fstart, the result should not be negative. */
+ assert (0 <= result);
}
}
diff --git a/src/freeze.c b/src/freeze.c
index 34ccca08..dd856337 100644
--- a/src/freeze.c
+++ b/src/freeze.c
@@ -71,16 +71,27 @@ produce_frozen_state (const char *name)
/* Dump quote delimiters. */
- if (strcmp (curr_quote.str1, DEF_LQUOTE)
- || strcmp (curr_quote.str2, DEF_RQUOTE))
- xfprintf (file, "Q%d,%d\n%s%s\n", (int) curr_quote.len1,
- (int) curr_quote.len2, curr_quote.str1, curr_quote.str2);
+ if (curr_quote.len1 != 1 || curr_quote.len2 != 1
+ || *curr_quote.str1 != *DEF_LQUOTE || *curr_quote.str2 != *DEF_RQUOTE)
+ {
+ xfprintf (file, "Q%d,%d\n", (int) curr_quote.len1,
+ (int) curr_quote.len2);
+ fwrite (curr_quote.str1, 1, curr_quote.len1, file);
+ fwrite (curr_quote.str2, 1, curr_quote.len2, file);
+ fputc ('\n', file);
+ }
/* Dump comment delimiters. */
- if (strcmp (curr_comm.str1, DEF_BCOMM) || strcmp (curr_comm.str2, DEF_ECOMM))
- xfprintf (file, "C%d,%d\n%s%s\n", (int) curr_comm.len1,
- (int) curr_comm.len2, curr_comm.str1, curr_comm.str2);
+ if (curr_comm.len1 != 1 || curr_comm.len2 != 1
+ || *curr_comm.str1 != *DEF_BCOMM || *curr_comm.str2 != *DEF_ECOMM)
+ {
+ xfprintf (file, "C%d,%d\n", (int) curr_comm.len1,
+ (int) curr_comm.len2);
+ fwrite (curr_comm.str1, 1, curr_comm.len1, file);
+ fwrite (curr_comm.str2, 1, curr_comm.len2, file);
+ fputc ('\n', file);
+ }
/* Dump all symbols. */
@@ -318,7 +329,7 @@ reload_frozen_state (const char *name)
/* Change comment strings. */
- set_comment (string[0], string[1]);
+ set_comment (string[0], number[0], string[1], number[1]);
break;
case 'D':
@@ -350,7 +361,7 @@ reload_frozen_state (const char *name)
/* Change quote strings. */
- set_quotes (string[0], string[1]);
+ set_quotes (string[0], number[0], string[1], number[1]);
break;
default:
diff --git a/src/input.c b/src/input.c
index 49a4d244..75f86146 100644
--- a/src/input.c
+++ b/src/input.c
@@ -255,7 +255,7 @@ push_file (FILE *fp, const char *title, bool close_when_done)
}
if (debug_level & DEBUG_TRACE_INPUT)
- DEBUG_MESSAGE1 ("input read from %s", title);
+ debug_message ("input read from %s", title);
i = (input_block *) obstack_alloc (current_input, sizeof *i);
i->type = INPUT_FILE;
@@ -656,10 +656,10 @@ pop_input (bool cleanup)
if (debug_level & DEBUG_TRACE_INPUT)
{
if (tmp != &input_eof)
- DEBUG_MESSAGE2 ("input reverted to %s, line %d",
- tmp->file, tmp->line);
+ debug_message ("input reverted to %s, line %d",
+ tmp->file, tmp->line);
else
- DEBUG_MESSAGE ("input exhausted");
+ debug_message ("input exhausted");
}
if (ferror (isp->u.u_f.fp))
@@ -1182,8 +1182,8 @@ init_argv_token (struct obstack *obs, token_data *td)
last element of the $@ ref is reparsed, we must increase the argv
refcount here, to compensate for the fact that it will be
decreased once the final element is parsed. */
- assert (*curr_comm.str1 != ',' && *curr_comm.str1 != ')'
- && *curr_comm.str1 != *curr_quote.str1);
+ assert (!curr_comm.len1 || (*curr_comm.str1 != ',' && *curr_comm.str1 != ')'
+ && *curr_comm.str1 != *curr_quote.str1));
ch = peek_input (true);
if (ch != ',' && ch != ')')
{
@@ -1198,25 +1198,26 @@ init_argv_token (struct obstack *obs, token_data *td)
/*------------------------------------------------------------------.
| This function is for matching a string against a prefix of the |
-| input stream. If the string S matches the input and CONSUME is |
-| true, the input is discarded; otherwise any characters read are |
-| pushed back again. The function is used only when multicharacter |
-| quotes or comment delimiters are used. |
+| input stream. If the string S of length SLEN matches the input |
+| and CONSUME is true, the input is discarded; otherwise any |
+| characters read are pushed back again. The function is used only |
+| when multicharacter quotes or comment delimiters are used. |
`------------------------------------------------------------------*/
static bool
-match_input (const char *s, bool consume)
+match_input (const char *s, size_t slen, bool consume)
{
int n; /* number of characters matched */
int ch; /* input character */
const char *t;
bool result = false;
+ assert (slen);
ch = peek_input (false);
if (ch != to_uchar (*s))
return false; /* fail */
- if (s[1] == '\0')
+ if (slen == 1)
{
if (consume)
next_char (false, false);
@@ -1228,7 +1229,7 @@ match_input (const char *s, bool consume)
{
next_char (false, false);
n++;
- if (*s == '\0') /* long match */
+ if (--slen == 1) /* long match */
{
if (consume)
return true;
@@ -1244,20 +1245,21 @@ match_input (const char *s, bool consume)
return result;
}
-/*--------------------------------------------------------------------.
-| The macro MATCH() is used to match a string S against the input. |
-| The first character is handled inline, for speed. Hopefully, this |
-| will not hurt efficiency too much when single character quotes and |
-| comment delimiters are used. If CONSUME, then CH is the result of |
-| next_char, and a successful match will discard the matched string. |
-| Otherwise, CH is the result of peek_input, and the input stream is |
-| effectively unchanged. |
-`--------------------------------------------------------------------*/
+/*---------------------------------------------------------------.
+| The macro MATCH() is used to match a string S of length SLEN |
+| against the input. The first character is handled inline, for |
+| speed. Hopefully, this will not hurt efficiency too much when |
+| single character quotes and comment delimiters are used. If |
+| CONSUME, then CH is the result of next_char, and a successful |
+| match will discard the matched string. Otherwise, CH is the |
+| result of peek_input, and the input stream is effectively |
+| unchanged. |
+`---------------------------------------------------------------*/
-#define MATCH(ch, s, consume) \
- (to_uchar ((s)[0]) == (ch) \
- && (ch) != '\0' \
- && ((s)[1] == '\0' || (match_input ((s) + (consume), consume))))
+#define MATCH(ch, s, slen, consume) \
+ ((slen) && to_uchar ((s)[0]) == (ch) \
+ && ((slen) == 1 \
+ || (match_input ((s) + (consume), (slen) - (consume), consume))))
/*----------------------------------------------------------.
@@ -1289,14 +1291,14 @@ input_init (void)
start_of_input_line = false;
- curr_quote.str1 = xstrdup (DEF_LQUOTE);
- curr_quote.len1 = strlen (curr_quote.str1);
- curr_quote.str2 = xstrdup (DEF_RQUOTE);
- curr_quote.len2 = strlen (curr_quote.str2);
- curr_comm.str1 = xstrdup (DEF_BCOMM);
- curr_comm.len1 = strlen (curr_comm.str1);
- curr_comm.str2 = xstrdup (DEF_ECOMM);
- curr_comm.len2 = strlen (curr_comm.str2);
+ curr_quote.str1 = xmemdup (DEF_LQUOTE, 1);
+ curr_quote.len1 = 1;
+ curr_quote.str2 = xmemdup (DEF_RQUOTE, 1);
+ curr_quote.len2 = 1;
+ curr_comm.str1 = xmemdup (DEF_BCOMM, 1);
+ curr_comm.len1 = 1;
+ curr_comm.str2 = xmemdup (DEF_ECOMM, 1);
+ curr_comm.len2 = 1;
#ifdef ENABLE_CHANGEWORD
set_word_regexp (NULL, user_word_regexp);
@@ -1306,14 +1308,15 @@ input_init (void)
}
-/*--------------------------------------------------------------------.
-| Set the quote delimiters to LQ and RQ. Used by m4_changequote (). |
-| Pass NULL if the argument was not present, to distinguish from an |
-| explicit empty string. |
-`--------------------------------------------------------------------*/
+/*-----------------------------------------------------------------.
+| Set the quote delimiters to LQ and RQ, with respective lengths |
+| LQ_LEN and RQ_LEN. Used by m4_changequote (). Pass NULL if the |
+| argument was not present, to distinguish from an explicit empty |
+| string. |
+`-----------------------------------------------------------------*/
void
-set_quotes (const char *lq, const char *rq)
+set_quotes (const char *lq, size_t lq_len, const char *rq, size_t rq_len)
{
/* POSIX states that with 0 arguments, the default quotes are used.
POSIX XCU ERN 112 states that behavior is implementation-defined
@@ -1325,31 +1328,39 @@ set_quotes (const char *lq, const char *rq)
if (!lq)
{
lq = DEF_LQUOTE;
+ lq_len = 1;
rq = DEF_RQUOTE;
+ rq_len = 1;
+ }
+ else if (!rq || (lq_len && !rq_len))
+ {
+ rq = DEF_RQUOTE;
+ rq_len = 1;
}
- else if (!rq || (*lq && !*rq))
- rq = DEF_RQUOTE;
- if (strcmp (curr_quote.str1, lq) == 0 && strcmp (curr_quote.str2, rq) == 0)
+ if (curr_quote.len1 == lq_len && curr_quote.len2 == rq_len
+ && memcmp (curr_quote.str1, lq, lq_len) == 0
+ && memcmp (curr_quote.str2, rq, rq_len) == 0)
return;
free (curr_quote.str1);
free (curr_quote.str2);
- curr_quote.str1 = xstrdup (lq);
- curr_quote.len1 = strlen (curr_quote.str1);
- curr_quote.str2 = xstrdup (rq);
- curr_quote.len2 = strlen (curr_quote.str2);
+ curr_quote.str1 = xmemdup (lq, lq_len);
+ curr_quote.len1 = lq_len;
+ curr_quote.str2 = xmemdup (rq, rq_len);
+ curr_quote.len2 = rq_len;
set_quote_age ();
}
-/*--------------------------------------------------------------------.
-| Set the comment delimiters to BC and EC. Used by m4_changecom (). |
-| Pass NULL if the argument was not present, to distinguish from an |
-| explicit empty string. |
-`--------------------------------------------------------------------*/
+/*-----------------------------------------------------------------.
+| Set the comment delimiters to BC and EC, with respective lengths |
+| BC_LEN and EC_LEN. Used by m4_changecom (). Pass NULL if the |
+| argument was not present, to distinguish from an explicit empty |
+| string. |
+`-----------------------------------------------------------------*/
void
-set_comment (const char *bc, const char *ec)
+set_comment (const char *bc, size_t bc_len, const char *ec, size_t ec_len)
{
/* POSIX requires no arguments to disable comments. It requires
empty arguments to be used as-is, but this is counter to
@@ -1359,19 +1370,27 @@ set_comment (const char *bc, const char *ec)
This implementation assumes the aardvark will be approved. See
the texinfo for what some other implementations do. */
if (!bc)
- bc = ec = "";
- else if (!ec || (*bc && !*ec))
- ec = DEF_ECOMM;
+ {
+ bc = ec = "";
+ bc_len = ec_len = 0;
+ }
+ else if (!ec || (bc_len && !ec_len))
+ {
+ ec = DEF_ECOMM;
+ ec_len = 1;
+ }
- if (strcmp (curr_comm.str1, bc) == 0 && strcmp (curr_comm.str2, ec) == 0)
+ if (curr_comm.len1 == bc_len && curr_comm.len2 == ec_len
+ && memcmp (curr_comm.str1, bc, bc_len) == 0
+ && memcmp (curr_comm.str2, ec, ec_len) == 0)
return;
free (curr_comm.str1);
free (curr_comm.str2);
- curr_comm.str1 = xstrdup (bc);
- curr_comm.len1 = strlen (curr_comm.str1);
- curr_comm.str2 = xstrdup (ec);
- curr_comm.len2 = strlen (curr_comm.str2);
+ curr_comm.str1 = xmemdup (bc, bc_len);
+ curr_comm.len1 = bc_len;
+ curr_comm.str2 = xmemdup (ec, ec_len);
+ curr_comm.len2 = ec_len;
set_quote_age ();
}
@@ -1461,18 +1480,26 @@ set_quote_age (void)
quote_age to zero, but at least a quote_age of zero always produces
correct results (although it may take more time in doing so). */
- /* Hueristic of characters that might impact rescan if they appear in
- a quote delimiter. */
+ /* Hueristic of characters that might impact rescan if they appear
+ in a quote delimiter. Using a single NUL as one of the two quote
+ delimiters is safe, but strchr matches it, so we must special
+ case the strchr below. If we were willing to guarantee a
+ trailing NUL, we could use strpbrk(quote, unsafe) rather than
+ strchr(unsafe, *quote) and avoid the special case; on the other
+ hand, many strpbrk implementations are not as efficient as
+ strchr, and we save memory by avoiding the trailing NUL. */
#define Letters "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
static const char unsafe[] = Letters "_0123456789(,) \t\n\r\f\v";
#undef Letters
if (curr_quote.len1 == 1 && curr_quote.len2 == 1
- && strpbrk (curr_quote.str1, unsafe) == NULL
- && strpbrk (curr_quote.str2, unsafe) == NULL
+ && (!*curr_quote.str1 || strchr (unsafe, *curr_quote.str1) == NULL)
+ && (!*curr_quote.str2 || strchr (unsafe, *curr_quote.str2) == NULL)
&& default_word_regexp && *curr_quote.str1 != *curr_quote.str2
- && *curr_comm.str1 != '(' && *curr_comm.str1 != ','
- && *curr_comm.str1 != ')' && *curr_comm.str1 != *curr_quote.str1)
+ && (!curr_comm.len1
+ || (*curr_comm.str1 != '(' && *curr_comm.str1 != ','
+ && *curr_comm.str1 != ')'
+ && *curr_comm.str1 != *curr_quote.str1)))
current_quote_age = (((*curr_quote.str1 & 0xff) << 8)
| (*curr_quote.str2 & 0xff));
else
@@ -1627,7 +1654,7 @@ next_token (token_data *td, int *line, struct obstack *obs, bool allow_argv,
return TOKEN_ARGV;
}
- if (MATCH (ch, curr_comm.str1, true))
+ if (MATCH (ch, curr_comm.str1, curr_comm.len1, true))
{
if (obs)
obs_td = obs;
@@ -1652,7 +1679,7 @@ next_token (token_data *td, int *line, struct obstack *obs, bool allow_argv,
init_macro_token (obs, obs ? td : NULL);
continue;
}
- if (MATCH (ch, curr_comm.str2, true))
+ if (MATCH (ch, curr_comm.str2, curr_comm.len2, true))
{
obstack_grow (obs_td, curr_comm.str2, curr_comm.len2);
break;
@@ -1711,7 +1738,7 @@ next_token (token_data *td, int *line, struct obstack *obs, bool allow_argv,
#endif /* ENABLE_CHANGEWORD */
- else if (!MATCH (ch, curr_quote.str1, true))
+ else if (!MATCH (ch, curr_quote.str1, curr_quote.len1, true))
{
assert (ch < CHAR_EOF);
switch (ch)
@@ -1756,13 +1783,13 @@ next_token (token_data *td, int *line, struct obstack *obs, bool allow_argv,
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))
+ else if (MATCH (ch, curr_quote.str2, curr_quote.len2, true))
{
if (--quote_level == 0)
break;
obstack_grow (obs_td, curr_quote.str2, curr_quote.len2);
}
- else if (MATCH (ch, curr_quote.str1, true))
+ else if (MATCH (ch, curr_quote.str1, curr_quote.len1, true))
{
quote_level++;
obstack_grow (obs_td, curr_quote.str1, curr_quote.len1);
@@ -1858,7 +1885,7 @@ peek_token (void)
{
result = TOKEN_MACDEF;
}
- else if (MATCH (ch, curr_comm.str1, false))
+ else if (MATCH (ch, curr_comm.str1, curr_comm.len1, false))
{
result = TOKEN_STRING;
}
@@ -1870,7 +1897,7 @@ peek_token (void)
{
result = TOKEN_WORD;
}
- else if (MATCH (ch, curr_quote.str1, false))
+ else if (MATCH (ch, curr_quote.str1, curr_quote.len1, false))
{
result = TOKEN_STRING;
}
diff --git a/src/m4.h b/src/m4.h
index 8fa3c450..c79a5618 100644
--- a/src/m4.h
+++ b/src/m4.h
@@ -198,63 +198,11 @@ extern FILE *debug;
/* default flags -- equiv: aeq */
#define DEBUG_TRACE_DEFAULT 0x007
-#define DEBUG_PRINT1(Fmt, Arg1) \
- do \
- { \
- if (debug != NULL) \
- xfprintf (debug, Fmt, Arg1); \
- } \
- while (0)
-
-#define DEBUG_PRINT3(Fmt, Arg1, Arg2, Arg3) \
- do \
- { \
- if (debug != NULL) \
- xfprintf (debug, Fmt, Arg1, Arg2, Arg3); \
- } \
- while (0)
-
-#define DEBUG_MESSAGE(Fmt) \
- do \
- { \
- if (debug != NULL) \
- { \
- debug_message_prefix (); \
- xfprintf (debug, Fmt); \
- putc ('\n', debug); \
- } \
- } \
- while (0)
-
-#define DEBUG_MESSAGE1(Fmt, Arg1) \
- do \
- { \
- if (debug != NULL) \
- { \
- debug_message_prefix (); \
- xfprintf (debug, Fmt, Arg1); \
- putc ('\n', debug); \
- } \
- } \
- while (0)
-
-#define DEBUG_MESSAGE2(Fmt, Arg1, Arg2) \
- do \
- { \
- if (debug != NULL) \
- { \
- debug_message_prefix (); \
- xfprintf (debug, Fmt, Arg1, Arg2); \
- putc ('\n', debug); \
- } \
- } \
- while (0)
-
void debug_init (void);
int debug_decode (const char *);
void debug_flush_files (void);
bool debug_set_output (const call_info *, const char *);
-void debug_message_prefix (void);
+void debug_message (const char *, ...) M4_GNUC_PRINTF (1, 2);
void trace_prepre (const call_info *);
unsigned int trace_pre (macro_arguments *);
@@ -429,8 +377,8 @@ extern string_pair curr_quote;
#define DEF_BCOMM "#"
#define DEF_ECOMM "\n"
-void set_quotes (const char *, const char *);
-void set_comment (const char *, const char *);
+void set_quotes (const char *, size_t, const char *, size_t);
+void set_comment (const char *, size_t, const char *, size_t);
#ifdef ENABLE_CHANGEWORD
void set_word_regexp (const call_info *, const char *);
#endif
@@ -583,7 +531,6 @@ void undivert_all (void);
void expand_user_macro (struct obstack *, symbol *, int, macro_arguments *);
void m4_placeholder (struct obstack *, int, macro_arguments *);
void init_pattern_buffer (struct re_pattern_buffer *, struct re_registers *);
-const char *ntoa (int32_t, int);
const builtin *find_builtin_by_addr (builtin_func *);
const builtin *find_builtin_by_name (const char *);
diff --git a/src/output.c b/src/output.c
index ee1907b2..6d74ecd0 100644
--- a/src/output.c
+++ b/src/output.c
@@ -191,12 +191,7 @@ m4_tmpname (int divnum)
static size_t offset;
if (buffer == NULL)
{
- obstack_grow (&diversion_storage, output_temp_dir->dir_name,
- strlen (output_temp_dir->dir_name));
- obstack_1grow (&diversion_storage, '/');
- obstack_1grow (&diversion_storage, 'm');
- obstack_1grow (&diversion_storage, '4');
- obstack_1grow (&diversion_storage, '-');
+ obstack_printf (&diversion_storage, "%s/m4-", output_temp_dir->dir_name);
offset = obstack_object_size (&diversion_storage);
buffer = (char *) obstack_alloc (&diversion_storage,
INT_BUFSIZE_BOUND (divnum));
@@ -473,7 +468,6 @@ void
divert_text (struct obstack *obs, const char *text, int length, int line)
{
static bool start_of_output_line = true;
- const char *cursor;
/* If output goes to an obstack, merely add TEXT to it. */
@@ -533,20 +527,15 @@ divert_text (struct obstack *obs, const char *text, int length, int line)
if (output_current_line != line)
{
- OUTPUT_CHARACTER ('#');
- OUTPUT_CHARACTER ('l');
- OUTPUT_CHARACTER ('i');
- OUTPUT_CHARACTER ('n');
- OUTPUT_CHARACTER ('e');
- OUTPUT_CHARACTER (' ');
- for (cursor = ntoa (line, 10); *cursor; cursor++)
- OUTPUT_CHARACTER (*cursor);
+ static char line_buf[sizeof "#line " + INT_BUFSIZE_BOUND (line)];
+ sprintf (line_buf, "#line %d", line);
+ output_text (line_buf, strlen (line_buf));
+ assert (strlen (line_buf) < sizeof line_buf);
if (output_current_line < 1 && current_file[0] != '\0')
{
OUTPUT_CHARACTER (' ');
OUTPUT_CHARACTER ('"');
- for (cursor = current_file; *cursor; cursor++)
- OUTPUT_CHARACTER (*cursor);
+ output_text (current_file, strlen (current_file));
OUTPUT_CHARACTER ('"');
}
OUTPUT_CHARACTER ('\n');
diff --git a/src/path.c b/src/path.c
index 98d45671..998c0ed9 100644
--- a/src/path.c
+++ b/src/path.c
@@ -1,7 +1,7 @@
/* GNU m4 -- A simple macro processor
- Copyright (C) 1989, 1990, 1991, 1992, 1993, 2004, 2006, 2007 Free
- Software Foundation, Inc.
+ Copyright (C) 1989, 1990, 1991, 1992, 1993, 2004, 2006, 2007, 2008
+ Free Software Foundation, Inc.
This file is part of GNU M4.
@@ -160,7 +160,7 @@ m4_path_search (const char *file, char **result)
if (fp != NULL)
{
if (debug_level & DEBUG_TRACE_PATH)
- DEBUG_MESSAGE2 ("path search for `%s' found `%s'", file, name);
+ debug_message ("path search for `%s' found `%s'", file, name);
if (set_cloexec_flag (fileno (fp), true) != 0)
m4_warn (errno, NULL, _("cannot protect input file across forks"));
if (result)