autoconf-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

improve AS_ESCAPE


From: Eric Blake
Subject: improve AS_ESCAPE
Date: Thu, 19 Feb 2009 22:10:29 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

A while ago, I started a thread about ideas of cleaning up AS_ESCAPE, and it 
even got a favorable review from Paolo.  However, it ran into a snag because 
the optimal semantics (expanding the string before adding escapes) doesn't work 
with the fact that there are existing clients of AS_ESCAPE that call 
AC_REQUIRE, and this does not work inside m4_expand.
http://lists.gnu.org/archive/html/autoconf-patches/2008-11/msg00185.html

However, there are still some simpler cleanups that can be done, whether or not 
I figure out how to make m4_expand and m4_require play nicely.  In particular, 
we can take advantage of my recent patch to m4 to be faster on m4_translit when 
the set of characters to be changed is small:
http://lists.gnu.org/archive/html/m4-patches/2009-02/msg00017.html
In my test runs, I saw about 0.5% improvement in execution time when running 
autoconf on coreutils.

This slightly changes the semantics of AS_ESCAPE, but a google code search 
found most clients of AS_ESCAPE used the default second argument, and of those 
few that didn't, they were still compliant with the additional restrictions 
added by this patch.

When documenting AS_ESCAPE, I also noticed that a few macros recently 
documented in the manual hadn't shown up in the NEWS.


From: Eric Blake <address@hidden>
Date: Thu, 19 Feb 2009 09:53:35 -0700
Subject: [PATCH 1/2] Mention recently documented macros.

* NEWS: Update list of new documentation.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog |    5 +++++
 NEWS      |   13 +++++++------
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index d766102..79b6740 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-02-19  Eric Blake  <address@hidden>
+
+       Mention recently documented macros.
+       * NEWS: Update list of new documentation.
+
 2009-02-14  Ralf Wildenhues  <address@hidden>

        Add index for config.site.
diff --git a/NEWS b/NEWS
index 94b310e..a1f0a60 100644
--- a/NEWS
+++ b/NEWS
@@ -55,10 +55,11 @@ GNU Autoconf NEWS - User visible changes.
    `autoreconf -I dir' option.

 ** The following documented m4sugar macros are new:
-   m4_chomp  m4_curry  m4_default_quoted  m4_esyscmd_s  m4_map_args
-   m4_map_args_pair  m4_map_args_sep  m4_map_args_w  m4_set_map
-   m4_set_map_sep  m4_stack_foreach  m4_stack_foreach_lifo
-   m4_stack_foreach_sep  m4_stack_foreach_sep_lifo
+   m4_chomp  m4_chomp_all  m4_cleardivert  m4_curry  m4_default_quoted
+   m4_esyscmd_s  m4_map_args  m4_map_args_pair  m4_map_args_sep
+   m4_map_args_w  m4_set_map  m4_set_map_sep  m4_stack_foreach
+   m4_stack_foreach_lifo  m4_stack_foreach_sep
+   m4_stack_foreach_sep_lifo

 ** The following m4sugar macros are documented now, but in some cases
    with slightly different semantics than what the previous
@@ -73,8 +74,8 @@ GNU Autoconf NEWS - User visible changes.
    unbalanced `(' where single-quoting used to be sufficient.

 ** The following documented m4sh macros are new:
-   AS_LINENO_PREPARE  AS_ME_PREPARE  AS_SET_STATUS  AS_VAR_APPEND
-   AS_VAR_ARITH  AS_VAR_COPY
+   AS_INIT_GENERATED  AS_LINENO_PREPARE  AS_ME_PREPARE  AS_SET_STATUS
+   AS_VAR_APPEND  AS_VAR_ARITH  AS_VAR_COPY

 ** The following m4sh macros are documented now, but in some cases
    with slightly different semantics than what the previous
-- 
1.6.1.2


>From 4da1abd28bae9bbe54e49159929f33628476fc9a Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Thu, 19 Feb 2009 14:32:36 -0700
Subject: [PATCH 2/2] Use m4_translit more efficiently in AS_ESCAPE.

* lib/m4sugar/m4sh.m4 (_AS_ESCAPE): Alter API to take first byte
of set separately from rest.
(AS_ESCAPE, _AS_QUOTE_MODERN, AS_TR_SH, AS_VAR_GET): Adjust
callers.
* lib/autoconf/autoheader.m4 (AH_VERBATIM): Avoid duplicate
characters in translit request.
* doc/autoconf.texi (Common Shell Constructs) <AS_ESCAPE>:
Document the macro.
* NEWS: Likewise.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog                  |   11 ++++++++++
 NEWS                       |    4 +-
 doc/autoconf.texi          |   45 ++++++++++++++++++++++++++++++++++++++++++++
 lib/autoconf/autoheader.m4 |    4 +-
 lib/m4sugar/m4sh.m4        |   34 ++++++++++++++++++++++++--------
 5 files changed, 85 insertions(+), 13 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 79b6740..c68d1b5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2009-02-19  Eric Blake  <address@hidden>

+       Use m4_translit more efficiently in AS_ESCAPE.
+       * lib/m4sugar/m4sh.m4 (_AS_ESCAPE): Alter API to take first byte
+       of set separately from rest.
+       (AS_ESCAPE, _AS_QUOTE_MODERN, AS_TR_SH, AS_VAR_GET): Adjust
+       callers.
+       * lib/autoconf/autoheader.m4 (AH_VERBATIM): Avoid duplicate
+       characters in translit request.
+       * doc/autoconf.texi (Common Shell Constructs) <AS_ESCAPE>:
+       Document the macro.
+       * NEWS: Likewise.
+
        Mention recently documented macros.
        * NEWS: Update list of new documentation.

diff --git a/NEWS b/NEWS
index a1f0a60..34b4380 100644
--- a/NEWS
+++ b/NEWS
@@ -80,8 +80,8 @@ GNU Autoconf NEWS - User visible changes.
 ** The following m4sh macros are documented now, but in some cases
    with slightly different semantics than what the previous
    undocumented version had:
-   AS_ECHO  AS_ECHO_N  AS_EXIT  AS_LITERAL_IF  AS_UNSET  AS_VAR_IF
-   AS_VAR_POPDEF  AS_VAR_PUSHDEF  AS_VAR_SET  AS_VAR_SET_IF
+   AS_ECHO  AS_ECHO_N  AS_ESCAPE  AS_EXIT  AS_LITERAL_IF  AS_UNSET
+   AS_VAR_IF  AS_VAR_POPDEF  AS_VAR_PUSHDEF  AS_VAR_SET  AS_VAR_SET_IF
    AS_VAR_TEST_SET  AS_VERSION_COMPARE

 ** The m4sh macros AS_IF and AS_CASE can now be used in shell lists.
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index 9588301..dcf591d 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -12338,6 +12338,51 @@ Common Shell Constructs
 Redirections can be placed outside the macro invocation.
 @end defmac

address@hidden AS_ESCAPE (@var{string}, @dvar{chars, `\"$})
address@hidden
+Expands to @var{string}, with any characters in @var{chars} escaped with
+a backslash (@samp{\}).  @var{chars} should be at most four bytes long,
+and only contain characters from the set @samp{`\"$}; however,
+characters may be safely listed more than once in @var{chars} for the
+sake of syntax highlighting editors.  The current implementation expands
address@hidden after adding escapes; if @var{string} contains macro calls
+that have text that needs quoting, you can use
address@hidden(m4_dquote(m4_expand([string])))}.
+
+The default for @var{chars} (@samp{\"$`}) is the set of characters
+needing escapes when @var{string} will be used literally within double
+quotes.  One common variant is the set of characters to protect when
address@hidden will be used literally within back-ticks or an unquoted
+here-doc (@samp{\$`}).  Another common variant is @samp{""}, which can
+be used to form a double-quoted string containing the same expansions
+that would have occurred if @var{string} were expanded in an unquoted
+here-doc; however, when using this variant, care must be taken that
address@hidden does not use double quotes within complex variable
+expansions (such as @address@hidden "hi"address@hidden) that would be broken
+with improper escapes.
+
+This macro is often used with @code{AS_ECHO}.  For example, this snippet
+will produce shell code that outputs the four lines @samp{"$foo" =
+"bar"}, @samp{macro}, @samp{a, b}, and @samp{a, \b}:
+
address@hidden
+foo=bar
+AS_ECHO(["AS_ESCAPE(["$foo" = ])AS_ESCAPE(["$foo"], [""])"])
+m4_define([macro], [a, [\b]])
+AS_ECHO(["AS_ESCAPE([[macro]])"])
+AS_ECHO(["AS_ESCAPE([macro])"])
+AS_ECHO(["AS_ESCAPE(m4_dquote(m4_expand([macro])))"])
address@hidden example
+
address@hidden Should we add AS_ESCAPE_SINGLE? If we do, we can optimize in
address@hidden the case of @var{string} that does not contain '.
+To escape a string that will be placed within single quotes, use:
+
address@hidden
+m4_bpatsubst(address@hidden, ['], ['\\''])
address@hidden example
address@hidden defmac
+
 @defmac AS_EXIT (@dvar{status, $?})
 @asindex{EXIT}
 Emit code to exit the shell with @var{status}, defaulting to @samp{$?}.
diff --git a/lib/autoconf/autoheader.m4 b/lib/autoconf/autoheader.m4
index dfc5f77..8e109cc 100644
--- a/lib/autoconf/autoheader.m4
+++ b/lib/autoconf/autoheader.m4
@@ -2,7 +2,7 @@
 # Interface with autoheader.

 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2008 Free Software Foundation, Inc.
+# 2002, 2008, 2009 Free Software Foundation, Inc.

 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -68,7 +68,7 @@ m4_define([AH_OUTPUT], [])
 # Quote for Perl '' strings, which are those used by Autoheader.
 m4_define([AH_VERBATIM],
 [AS_LITERAL_IF([$1],
-              [AH_OUTPUT([$1], AS_ESCAPE([[$2]], [\\'']))])])
+              [AH_OUTPUT([$1], AS_ESCAPE([[$2]], [\']))])])


 # AH_TEMPLATE(KEY, DESCRIPTION)
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index 2e17a9d..e033063 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -680,18 +680,33 @@ m4_define([AS_MESSAGE_LOG_FD])
 m4_define([AS_ORIGINAL_STDIN_FD], [0])


-# AS_ESCAPE(STRING, [CHARS = $"`\])
+# AS_ESCAPE(STRING, [CHARS = `\"$])
 # ---------------------------------
-# Escape the CHARS in STRING.
+# Add backslash escaping to the CHARS in STRING.  In an effort to
+# optimize use of this macro inside double-quoted shell constructs,
+# the behavior is intentionally undefined if CHARS is longer than 4
+# bytes, or contains bytes outside of the set [`\"$].  However,
+# repeated bytes within the set are permissible (AS_ESCAPE([$1], [""])
+# being a common way to be nice to syntax highlighting).
 #
 # Avoid the m4_bpatsubst if there are no interesting characters to escape.
 # _AS_ESCAPE bypasses argument defaulting.
 m4_define([AS_ESCAPE],
-[_$0([$1], m4_default([$2], [\"$`]))])
+[_$0([$1], m4_if([$2], [], [[`], [\"$]], [m4_substr([$2], [0], [1]), [$2]]))])
+
+# _AS_ESCAPE(STRING, KEY, SET)
+# ----------------------------
+# Backslash-escape all instances of the singly byte KEY or up to four
+# bytes in SET occurring in STRING.  Although a character can occur
+# multiple times, optimum efficiency occurs when KEY and SET are
+# distinct, and when SET does not exceed two bytes.  These particular
+# semantics allow for the fewest number of parses of STRING, as well
+# as taking advantage of newer m4's optimizations when m4_translit is
+# passed SET of size 2 or smaller.
 m4_define([_AS_ESCAPE],
-[m4_if(m4_len([$1]),
-       m4_len(m4_translit([[$1]], [$2])),
-       [$1], [m4_bpatsubst([$1], [[$2]], [\\\&])])])
+[m4_if(m4_index(m4_translit([[$1]], [$3], [$2$2$2$2]), [$2]), [-1],
+       [$0_], [m4_bpatsubst])([$1], [[$2$3]], [\\\&])])
+m4_define([_AS_ESCAPE_], [$1])


 # _AS_QUOTE(STRING)
@@ -722,7 +737,7 @@ m4_define([_AS_QUOTE],
         [_AS_QUOTE_MODERN])([$1])])

 m4_define([_AS_QUOTE_MODERN],
-[_AS_ESCAPE([$1], [`""])])
+[_AS_ESCAPE([$1], [`], [""])])

 m4_define([_AS_QUOTE_OLD],
 [m4_warn([obsolete],
@@ -1725,7 +1740,8 @@ m4_defun_init([AS_TR_SH],
 m4_dquote(m4_dquote(m4_defn([m4_cr_not_symbols2])))[[,
                                 [pp[]]]]dnl
 m4_dquote(m4_dquote(m4_for(,1,255,,[[_]])))[[)],
-  [`AS_ECHO(["_AS_ESCAPE(m4_dquote(m4_expand([$1])), [\`])"]) | $as_tr_sh`])])
+  [`AS_ECHO(["_AS_ESCAPE(m4_dquote(m4_expand([$1])),
+    [`], [\])"]) | $as_tr_sh`])])


 # _AS_TR_CPP_PREPARE
@@ -1883,7 +1899,7 @@ m4_define([AS_VAR_COPY],
 m4_define([AS_VAR_GET],
 [AS_LITERAL_IF([$1],
               [$$1],
-  [`eval 'as_val=${'_AS_ESCAPE([[$1]], [\`])'};AS_ECHO(["$as_val"])'`])])
+  [`eval 'as_val=${'_AS_ESCAPE([[$1]], [`], [\])'};AS_ECHO(["$as_val"])'`])])


 # AS_VAR_IF(VARIABLE, VALUE, IF-TRUE, IF-FALSE)
-- 
1.6.1.2







reply via email to

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