m4-commit
[Top][All Lists]
Advanced

[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-29-


From: Eric Blake
Subject: [SCM] GNU M4 source repository branch, branch-1.6, updated. v1.5.89a-29-g10b0347
Date: Wed, 18 Jun 2008 13:29:13 +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=10b0347d04e2d00fddfce01d0321d3e75aaf6520

The branch, branch-1.6 has been updated
       via  10b0347d04e2d00fddfce01d0321d3e75aaf6520 (commit)
      from  2319d2628b8a6257622caa7d136d88021eaf8883 (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 10b0347d04e2d00fddfce01d0321d3e75aaf6520
Author: Eric Blake <address@hidden>
Date:   Wed Dec 19 17:16:28 2007 -0700

    Stage 25: Handle embedded NUL in changequote and changecom.
    
    * m4/gnulib-cache.m4: Import obstack-printf-posix module.
    * src/m4.h (ntoa): Remove declaration.
    (DEBUG_PRINT1, DEBUG_PRINT3, MESSAGE, DEBUG_MESSAGE1)
    (DEBUG_MESSAGE2): Delete, now that these macros are unused.
    (debug_message_prefix): Rename...
    (debug_message): ...and add parameters.
    (set_quotes, set_comment): Add parameters.
    * src/debug.c (debug_message_prefix): Rename...
    (debug_message): ...and use obstack_printf.
    (trace_format): Delete.
    (trace_header): Adjust caller.
    * src/input.c (init_argv_token, input_init): Handle embedded NUL
    in comments and quotes.
    (match_input, MATCH, set_quotes, set_comment): Add parameter.
    (set_quote_age): Adjust heuristic for safe quote.
    (push_file, pop_input, next_token, peek_token): Adjust callers.
    * src/freeze.c (produce_frozen_state, reload_frozen_state): Handle
    embedded NUL in quotes and comments.
    * src/builtin.h (ntoa): Make static.
    (shipout_int, m4_eval, m4_maketemp): Use obstack_printf.
    (m4_dumpdef): Avoid truncating output on embedded NUL.
    (m4_changequote, m4_changecom): Handle embedded NUL.
    * src/format.c (expand_format): Use obstack_printf.
    * src/output.c (m4_tmpname, divert_text): Likewise.
    * src/path.c (m4_path_search): Adjust caller.
    * doc/m4.texinfo (Using frozen files): Enhance test.
    * examples/null.m4: Likewise.
    * examples/null.out: Update expected output.
    * examples/null.err: Likewise.
    
    (cherry picked from commit 40c640f486bf7a99c6e16d91332f25872f501488)
    
    Signed-off-by: Eric Blake <address@hidden>

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog          |   39 ++++++++++++
 doc/m4.texinfo     |    7 +-
 examples/null.err  |  Bin 505 -> 572 bytes
 examples/null.m4   |  Bin 5891 -> 6189 bytes
 examples/null.out  |  Bin 404 -> 468 bytes
 m4/gnulib-cache.m4 |    4 +-
 src/builtin.c      |   64 +++++++++----------
 src/debug.c        |   88 +++++++-------------------
 src/format.c       |   47 ++++----------
 src/freeze.c       |   29 ++++++---
 src/input.c        |  175 ++++++++++++++++++++++++++++++----------------------
 src/m4.h           |   59 +-----------------
 src/output.c       |   23 ++-----
 src/path.c         |    6 +-
 14 files changed, 246 insertions(+), 295 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index ee7e246..60a5a9e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+2008-06-18  Eric Blake  <address@hidden>
+
+       Stage 25: Handle embedded NUL in changequote and changecom.
+       Track quote and comment delimiters by length, to allow embedded
+       NUL.  Convert macro tracing and other locations to use
+       obstack_printf rather than hand-rolled equivalents.  Ensure that
+       embedded NUL in trace output does not truncate the trace string.
+       Memory impact: none.
+       Speed impact: none noticed.
+       * m4/gnulib-cache.m4: Import obstack-printf-posix module.
+       * src/m4.h (ntoa): Remove declaration.
+       (DEBUG_PRINT1, DEBUG_PRINT3, MESSAGE, DEBUG_MESSAGE1)
+       (DEBUG_MESSAGE2): Delete, now that these macros are unused.
+       (debug_message_prefix): Rename...
+       (debug_message): ...and add parameters.
+       (set_quotes, set_comment): Add parameters.
+       * src/debug.c (debug_message_prefix): Rename...
+       (debug_message): ...and use obstack_printf.
+       (trace_format): Delete.
+       (trace_header): Adjust caller.
+       * src/input.c (init_argv_token, input_init): Handle embedded NUL
+       in comments and quotes.
+       (match_input, MATCH, set_quotes, set_comment): Add parameter.
+       (set_quote_age): Adjust heuristic for safe quote.
+       (push_file, pop_input, next_token, peek_token): Adjust callers.
+       * src/freeze.c (produce_frozen_state, reload_frozen_state): Handle
+       embedded NUL in quotes and comments.
+       * src/builtin.h (ntoa): Make static.
+       (shipout_int, m4_eval, m4_maketemp): Use obstack_printf.
+       (m4_dumpdef): Avoid truncating output on embedded NUL.
+       (m4_changequote, m4_changecom): Handle embedded NUL.
+       * src/format.c (expand_format): Use obstack_printf.
+       * src/output.c (m4_tmpname, divert_text): Likewise.
+       * src/path.c (m4_path_search): Adjust caller.
+       * doc/m4.texinfo (Using frozen files): Enhance test.
+       * examples/null.m4: Likewise.
+       * examples/null.out: Update expected output.
+       * examples/null.err: Likewise.
+
 2008-06-16  Eric Blake  <address@hidden>
 
        Add missing const qualifications.
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index fe429b4..5a645b8 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -7012,12 +7012,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
address@hidden 0
address@hidden #-- hi 0
 @end example
 @end ignore
 
diff --git a/examples/null.err b/examples/null.err
index 05a1ba3..5f989ee 100644
Binary files a/examples/null.err and b/examples/null.err differ
diff --git a/examples/null.m4 b/examples/null.m4
index c928360..de76742 100644
Binary files a/examples/null.m4 and b/examples/null.m4 differ
diff --git a/examples/null.out b/examples/null.out
index 66f41b5..5e90221 100644
Binary files a/examples/null.out and b/examples/null.out differ
diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4
index 5aa4820..e20ee63 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 autobuild avltree-oset 
binary-io clean-temp cloexec close-stream closein config-h error fdl fflush 
flexmember fopen-safer fseeko gendocs getopt git-version-gen gnumakefile 
gnupload gpl-3.0 intprops memchr2 memmem mkstemp obstack progname 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 clean-temp cloexec close-stream closein config-h error fdl fflush 
flexmember fopen-safer 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 autobuild avltree-oset binary-io clean-temp 
cloexec close-stream closein config-h error fdl fflush flexmember fopen-safer 
fseeko gendocs getopt git-version-gen gnumakefile gnupload gpl-3.0 intprops 
memchr2 memmem mkstemp obstack 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_MODULES([announce-gen assert autobuild avltree-oset binary-io clean-temp 
cloexec close-stream closein config-h error fdl fflush flexmember fopen-safer 
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 e68ea8d..6b107ae 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -587,7 +587,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;
@@ -629,10 +629,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);
 }
 
 
@@ -908,11 +905,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:
@@ -922,7 +918,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:
@@ -930,6 +926,7 @@ m4_dumpdef (struct obstack *obs, int argc, macro_arguments 
*argv)
          abort ();
          break;
        }
+      fputc ('\n', debug);
     }
 }
 
@@ -1211,11 +1208,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;
     }
 
@@ -1227,10 +1227,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
@@ -1378,8 +1377,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));
 }
 
 /*--------------------------------------------------------------------.
@@ -1393,8 +1392,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
@@ -1535,23 +1534,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 2b2388f..c3f85bd 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 c783d11..3325853 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 e67bcc8..5e35c81 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.  */
 
@@ -329,7 +340,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':
@@ -361,7 +372,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 acbc370..589fbb1 100644
--- a/src/input.c
+++ b/src/input.c
@@ -252,7 +252,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;
@@ -653,10 +653,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 ();
 }
 
@@ -1459,18 +1478,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
@@ -1625,7 +1652,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;
@@ -1650,7 +1677,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;
@@ -1709,7 +1736,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)
@@ -1754,13 +1781,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);
@@ -1856,7 +1883,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;
     }
@@ -1868,7 +1895,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 d16d87a..3afe476 100644
--- a/src/m4.h
+++ b/src/m4.h
@@ -199,63 +199,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 *);
@@ -430,8 +378,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
@@ -584,7 +532,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 ee1907b..6d74ecd 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 98d4567..998c0ed 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)


hooks/post-receive
--
GNU M4 source repository




reply via email to

[Prev in Thread] Current Thread [Next in Thread]