According to Bruno Haible on 2/23/2010 4:43 PM:
> Hi Eric,
> 
>>> The first use of as_gl_Symbol is now like this:
>>>
>>>   if { as_var=$as_gl_Symbol; eval "test \"\${$as_var+set}\" = set"; }; then
>>>
>>> Autoconf could have optimized this to
>>>
>>>   if eval "test \"\${$as_gl_Symbol+set}\" = set"; then
>>>
>>> Neither autoconf 2.60 not 2.65 do this optimization.
>>
>> That's because it is too complex at m4 time to tell whether the
>> indirection is simple enough to simplify like that.  The whole point of
>> AS_LITERAL_IF and AS_VAR_* is that you can have things more complex than
>> '$as_gl_Symbol' as the indirect variable name, such as '`program that
>> outputs valid shell name`', and in that case, you cannot simplify things
>> by bypassing the intermediate variable without running into "`""`" shell
>> bugs.
> 
> It is not that complicated:
> 
> m4_define([AS_VAR_TEST_SET],
> [AS_LITERAL_IF([$1],
>                [test "${$1+set}" = set],
>                [AS_VAR_REF_IF([$1],
>                               [eval "test \"\${][$1][+set}\" = set"],
>                               [{ as_var=$1; eval "test \"\${$as_var+set}\" = 
> set"; }])])])
> 
> # Tests whether the first argument is a shell variable reference, like $foo
> # AS_VAR_REF_IF(EXPRESSION, IF_BRANCH, ELSE_BRANCH)
> m4_define([AS_VAR_REF_IF],
> [_AS_VAR_REF_IF(m4_expand([$1]), [$2], [$3])])
> 
> m4_define([_AS_VAR_REF_IF],
> [m4_if(m4_substr([$1],[0],[1]),[$],
>   [AS_LITERAL_IF([m4_substr([$1],[1])], [$2], [$3])],
>   [$3])])
> 
> Should I submit a patch to autoconf-patches?

I'm game.  But I think this patch series is a little more robust.  It
shaves more than 1k size off of coreutils' configure.  The number of
reduced processes is in the noise.

-- 
Don't work too hard, make some time for fun as well!

Eric Blake             [email protected]
From 22d46ebe6ddaeb128e2b4119add59dccecc28526 Mon Sep 17 00:00:00 2001
From: Eric Blake <[email protected]>
Date: Mon, 1 Mar 2010 17:17:40 -0700
Subject: [PATCH 1/3] Optimize AS_BOX.

* lib/m4sugar/m4sh.m4 (AS_BOX): Use less m4 time.
(_AS_BOX_LITERAL): Use fewer forks in the common case.
* doc/autoconf.texi (Common Shell Constructs) <AS_BOX>: Document
the macro.
* NEWS: Mention it.

Signed-off-by: Eric Blake <[email protected]>
---
 ChangeLog           |    7 +++++++
 NEWS                |    3 +++
 doc/autoconf.texi   |   11 +++++++++++
 lib/m4sugar/m4sh.m4 |    9 +++------
 4 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 523628e..ce31a7e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2010-03-01  Eric Blake  <[email protected]>

+       Optimize AS_BOX.
+       * lib/m4sugar/m4sh.m4 (AS_BOX): Use less m4 time.
+       (_AS_BOX_LITERAL): Use fewer forks in the common case.
+       * doc/autoconf.texi (Common Shell Constructs) <AS_BOX>: Document
+       the macro.
+       * NEWS: Mention it.
+
        Update file flow diagram to mention Automake.
        * doc/autoconf.texi (Making configure Scripts): Avoid confusion
        with listing Makefile.in twice on one line.  Add a diagram showing
diff --git a/NEWS b/NEWS
index 207325e..c11d3a1 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,9 @@ GNU Autoconf NEWS - User visible changes.
 ** AC_PROG_INSTALL correctly uses `shtool' again.  Regression introduced
    in 2.64.

+** The following macros are now documented:
+   AS_BOX
+
 * Major changes in Autoconf 2.65 (2009-11-21) [stable]
   Released by Eric Blake, based on git versions 2.64.*.

diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index 191a397..0c7c981 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -13047,6 +13047,17 @@ Common Shell Constructs
 @end defmac
 @end ignore

+...@defmac AS_BOX (@var{text}, @var{char, -})
+...@asindex{box}
+Expand into shell code that will output @var{text} surrounded by a box
+with @var{char} in the top and bottom border.  @var{text} should not
+contain a newline, but may contain shell expansions valid for unquoted
+here-documents.  @var{char} defaults to @samp{-}, but can be any
+character except @samp{/}, @samp{'}, @samp{"}, @samp{\}, @samp{$},
+...@samp{&}, or @samp{`}.  This is useful for outputting a comment box into
+log files to separate distinct phases of script operation.
+...@end defmac
+
 @defmac AS_CASE (@var{word}, @ovar{pattern1}, @ovar{if-matched1}, @
   @dots{}, @ovar{default})
 @asindex{CASE}
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index 8160b3d..6a43f21 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -1378,17 +1378,14 @@ as_executable_p=$as_test_x
 # Output MESSAGE, a single line text, framed with FRAME-CHARACTER (which
 # must not be `/').
 m4_define([AS_BOX],
-[AS_LITERAL_IF([$1],
-              [_AS_BOX_LITERAL($@)],
-              [_AS_BOX_INDIR($@)])])
+[m4_if(m4_index(m4_translit([[$1]], [`\"], [$$$]), [$]),
+  [-1], [_$0_LITERAL], [_$0_INDIR])($@)])


 # _AS_BOX_LITERAL(MESSAGE, [FRAME-CHARACTER = `-'])
 # -------------------------------------------------
 m4_define([_AS_BOX_LITERAL],
-[cat <<\_ASBOX
-m4_text_box($@)
-_ASBOX])
+[AS_ECHO("m4_text_box($@)")])


 # _AS_BOX_INDIR(MESSAGE, [FRAME-CHARACTER = `-'])
-- 
1.6.6.1


From d679979e5f79926de13f1abf0bfecf5bb990e56f Mon Sep 17 00:00:00 2001
From: Eric Blake <[email protected]>
Date: Sat, 27 Feb 2010 10:39:31 -0700
Subject: [PATCH 2/3] Add optional argument to AS_LITERAL_IF.

* lib/m4sugar/m4sh.m4 (_AS_LITERAL_IF): Rewrite to generate macro
name, without using m4_cond.  Allow more control over whitespace.
(_AS_LITERAL_IF_, _AS_LITERAL_IF_YES, _AS_LITERAL_IF_NO): New
helpers.
(AS_LITERAL_IF, _AS_TR_SH, _AS_TR_CPP, _AS_VAR_PUSHDEF): Adjust
callers.
* lib/autoconf/types.m4 (AC_CHECK_MEMBER): Don't hand space to
AS_LITERAL_IF.
* lib/autoconf/general.m4 (_AC_INIT_PACKAGE): Likewise.
* tests/m4sh.at (AS@&t...@_literal_if): Update test.

Signed-off-by: Eric Blake <[email protected]>
---
 ChangeLog               |   12 ++++++++++
 lib/autoconf/general.m4 |    3 +-
 lib/autoconf/types.m4   |    6 +++-
 lib/m4sugar/m4sh.m4     |   55 ++++++++++++++++++++++++++++++++--------------
 tests/m4sh.at           |   28 ++++++++++++++++++------
 5 files changed, 77 insertions(+), 27 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index ce31a7e..230d20e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2010-03-01  Eric Blake  <[email protected]>

+       Add optional argument to AS_LITERAL_IF.
+       * lib/m4sugar/m4sh.m4 (_AS_LITERAL_IF): Rewrite to generate macro
+       name, without using m4_cond.  Allow more control over whitespace.
+       (_AS_LITERAL_IF_, _AS_LITERAL_IF_YES, _AS_LITERAL_IF_NO): New
+       helpers.
+       (AS_LITERAL_IF, _AS_TR_SH, _AS_TR_CPP, _AS_VAR_PUSHDEF): Adjust
+       callers.
+       * lib/autoconf/types.m4 (AC_CHECK_MEMBER): Don't hand space to
+       AS_LITERAL_IF.
+       * lib/autoconf/general.m4 (_AC_INIT_PACKAGE): Likewise.
+       * tests/m4sh.at (AS@&t...@_literal_if): Update test.
+
        Optimize AS_BOX.
        * lib/m4sugar/m4sh.m4 (AS_BOX): Use less m4 time.
        (_AS_BOX_LITERAL): Use fewer forks in the common case.
diff --git a/lib/autoconf/general.m4 b/lib/autoconf/general.m4
index 15640c8..396ec3d 100644
--- a/lib/autoconf/general.m4
+++ b/lib/autoconf/general.m4
@@ -229,7 +229,8 @@ AU_ALIAS([AC_HELP_STRING], [AS_HELP_STRING])
 # _AC_INIT_PACKAGE(PACKAGE-NAME, VERSION, BUG-REPORT, [TARNAME], [URL])
 # ---------------------------------------------------------------------
 m4_define([_AC_INIT_PACKAGE],
-[AS_LITERAL_IF([$1], [], [m4_warn([syntax], [AC_INIT: not a literal: $1])])
+[AS_LITERAL_IF(m4_translit([[$1]], [    ], [__]), [],
+  [m4_warn([syntax], [AC_INIT: not a literal: $1])])
 AS_LITERAL_IF([$2], [],  [m4_warn([syntax], [AC_INIT: not a literal: $2])])
 AS_LITERAL_IF([$3], [],  [m4_warn([syntax], [AC_INIT: not a literal: $3])])
 m4_ifndef([AC_PACKAGE_NAME],
diff --git a/lib/autoconf/types.m4 b/lib/autoconf/types.m4
index 0e0e3f3..0774582 100644
--- a/lib/autoconf/types.m4
+++ b/lib/autoconf/types.m4
@@ -877,8 +877,10 @@ AC_DEFUN([AC_CHECK_MEMBER],
     [Tries to find if the field MEMBER exists in type AGGR, after including
      INCLUDES, setting cache variable VAR accordingly.])],
     [_$0_BODY])]dnl
-[AS_LITERAL_IF([$1], [], [m4_fatal([$0: requires literal arguments])])]dnl
-[m4_if(m4_index([$1], [.]), -1, [m4_fatal([$0: Did not see any dot in 
`$1'])])]dnl
+[AS_LITERAL_IF(m4_translit([[$1]], [    ], [__]), [],
+  [m4_fatal([$0: requires literal arguments])])]dnl
+[m4_if(m4_index([$1], [.]), [-1],
+  [m4_fatal([$0: Did not see any dot in `$1'])])]dnl
 [AS_VAR_PUSHDEF([ac_Member], [ac_cv_member_$1])]dnl
 [ac_fn_[]_AC_LANG_ABBREV[]_check_member "$LINENO" ]dnl
 [m4_bpatsubst([$1], [^\([^.]*\)\.\(.*\)], ["\1" "\2"]) "ac_Member" ]dnl
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index 6a43f21..52edba8 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -1515,17 +1515,28 @@ m4_dquote(m4_dquote(m4_defn([m4_cr_symbols2])))[[)) > 
0)], [1], [],
 m4_dquote(m4_dquote(m4_defn([m4_cr_symbols1])))[[))], [0], [-])])


-# AS_LITERAL_IF(EXPRESSION, IF-LITERAL, IF-NOT-LITERAL)
+# AS_LITERAL_IF(EXPRESSION, IF-LITERAL, IF-NOT-LITERAL,
+#               [IF-SIMPLE-REF = IF-NOT-LITERAL])
 # -----------------------------------------------------
 # If EXPRESSION has shell indirections ($var or `expr`), expand
-# IF-LITERAL, else IF-NOT-LITERAL.
-# This is an *approximation*: for instance EXPRESSION = `\$' is
-# definitely a literal, but will not be recognized as such.
+# IF-LITERAL, else IF-NOT-LITERAL.  In some cases, IF-NOT-LITERAL
+# must be complex to safely deal with ``, while a simpler
+# expression IF-SIMPLE-REF can be used if the indirection
+# involves only shell variable expansion (as in ${varname}).
+#
+# EXPRESSION is treated as a literal if it results in the same
+# interpretation whether it is unquoted or contained within double
+# quotes.  Therefore, neither `\$' nor `a''b' is a literal, since both
+# backslash and single quotes have different quoting behavior in the
+# two contexts; and `a*' is not a literal, because it has different
+# globbing.  This macro is an *approximation*: it is possible that
+# there are some EXPRESSIONs which the shell would treat as literals,
+# but which this macro does not recognize.
 #
 # Why do we reject EXPRESSION expanding with `[' or `]' as a literal?
 # Because AS_TR_SH is MUCH faster if it can use m4_translit on literals
 # instead of m4_bpatsubst; but m4_translit is much tougher to do safely
-# if `[' is translated.
+# if `[' is translated.  That, and file globbing matters.
 #
 # Note that the quadrigraph @S|@ can result in non-literals, but outright
 # rejecting all @ would make AC_INIT complain on its bug report address.
@@ -1539,15 +1550,26 @@ m4_dquote(m4_dquote(m4_defn([m4_cr_symbols1])))[[))], 
[0], [-])])
 # m4_index can scan the result.
 #
 # Rather than expand m4_defn every time AS_LITERAL_IF is expanded, we
-# inline its expansion up front.
+# inline its expansion up front.  _AS_LITERAL_IF expands to the name
+# of a macro that takes three arguments: IF-SIMPLE-REF,
+# IF-NOT-LITERAL, IF-LITERAL.  It also takes an optional argument of
+# any additional characters to allow as literals (useful for AS_TR_SH
+# and AS_TR_CPP to perform inline conversion of whitespace to _).  The
+# order of the arguments allows reuse of m4_default.
 m4_define([AS_LITERAL_IF],
-[_$0(m4_expand([$1]), [$2], [$3])])
+[_$0(m4_expand([$1]))([$4], [$3], [$2])])

 m4_define([_AS_LITERAL_IF],
-[m4_if(m4_cond([m4_eval(m4_index([$1], [...@s|@]) == -1)], [0], [],
-  [m4_index(m4_translit([$1], [[]`,#()]]]dnl
-m4_dquote(m4_dquote(m4_defn([m4_cr_symbols2])))[[, [$$$]), [$])],
-  [-1], [-]), [-], [$2], [$3])])
+[m4_if(m4_index([$1], [...@s|@]), [-1], [$0_(m4_translit([$1], [{}[]#()]]]dnl
+m4_dquote(m4_dquote(m4_defn([m4_cr_symbols2])))[[[,....@%+/$2-],
+[$$``:::]))], [$0_NO])])
+
+m4_define([_AS_LITERAL_IF_],
+[m4_if([$1], [], [$0YES],
+       m4_translit([$1], [$]), [], [m4_default], [$0NO])])
+
+m4_define([_AS_LITERAL_IF_YES], [$3])
+m4_define([_AS_LITERAL_IF_NO], [$2])


 # AS_TMPDIR(PREFIX, [DIRECTORY = $TMPDIR [= /tmp]])
@@ -1736,7 +1758,7 @@ m4_defun_init([AS_TR_SH],
 [_$0(m4_expand([$1]))])

 m4_define([_AS_TR_SH],
-[_AS_LITERAL_IF([$1], [$0_LITERAL], [$0_INDIR])([$1])])
+[_AS_LITERAL_IF([$1], [         ])([], [$0_INDIR], [$0_LITERAL])([$1])])

 m4_define([_AS_TR_SH_LITERAL],
 [m4_translit([[$1]],
@@ -1768,7 +1790,7 @@ m4_defun_init([AS_TR_CPP],
 [_$0(m4_expand([$1]))])

 m4_define([_AS_TR_CPP],
-[_AS_LITERAL_IF([$1], [$0_LITERAL], [$0_INDIR])([$1])])
+[_AS_LITERAL_IF([$1], [         ])([], [$0_INDIR], [$0_LITERAL])([$1])])

 m4_define([_AS_TR_CPP_LITERAL],
 [m4_translit([$1],
@@ -1970,10 +1992,9 @@ m4_defun_init([AS_VAR_PUSHDEF],
 [_$0([$1], m4_expand([$2]))])

 m4_define([_AS_VAR_PUSHDEF],
-[_AS_LITERAL_IF([$2],
-               [m4_pushdef([$1], [_AS_TR_SH_LITERAL([$2])])],
-               [as_$1=_AS_TR_SH_INDIR([$2])
-m4_pushdef([$1], [$as_[$1]])])])
+[_AS_LITERAL_IF([$2], [         ])([], [as_$1=_AS_TR_SH_INDIR([$2])
+m4_pushdef([$1], [$as_[$1]])],
+[m4_pushdef([$1], [_AS_TR_SH_LITERAL([$2])])])])


 # AS_VAR_SET(VARIABLE, VALUE)
diff --git a/tests/m4sh.at b/tests/m4sh.at
index f34e6ba..6e3f8b3 100644
--- a/tests/m4sh.at
+++ b/tests/m4sh.at
@@ -1040,15 +1040,22 @@ AT_KEYWORDS([m4sh])
 AT_DATA_M4SH([script.as], [[dnl
 AS_INIT
 echo AS_LITERAL_IF([lit], [ok], [ERR]) 1
-echo AS_LITERAL_IF([l$it], [ERR], [ok]) 2
-echo AS_LITERAL_IF([l`case a in b) ;; esac`it], [ERR], [ok]) 3
-m4_define([mac], [lit])
-echo AS_LITERAL_IF([mac], [ok], [ERR]) 4
-echo AS_LITERAL_IF([mac($, ``)], [ok], [ERR]) 5
+echo AS_LITERAL_IF([l-/.it], [ok], [ERR]) 2
+echo AS_LITERAL_IF([l''it], [ERR], [ok]) 3
+echo AS_LITERAL_IF([l$it], [ERR], [ok]) 4
+echo AS_LITERAL_IF([l$it], [ERR1], [ERR2], [ok]) 5
+echo AS_LITERAL_IF([l${it}], [ERR1], [ERR2], [ok]) 6
+echo AS_LITERAL_IF([l`case a in b) ;; esac`it], [ERR], [ok]) 7
+echo AS_LITERAL_IF([l`case a in b) ;; esac`it], [ERR1], [ok], [ERR2]) 8
+m4_define([mac], [l-/.it])
+echo AS_LITERAL_IF([mac], [ok], [ERR]) 9
+echo AS_LITERAL_IF([mac($, ``)], [ok], [ERR]) 10
 m4_define([mac], [l$it])
-echo AS_LITERAL_IF([mac], [ERR], [ok]) 6
+echo AS_LITERAL_IF([mac], [ERR], [ok]) 11
+echo AS_LITERAL_IF([mac], [ERR1], [ERR2], [ok]) 12
 m4_define([mac], [l``it])
-echo AS_LITERAL_IF([mac], [ERR], [ok]) 7
+echo AS_LITERAL_IF([mac], [ERR], [ok]) 13
+echo AS_LITERAL_IF([mac], [ERR1], [ok], [ERR2]) 14
 ]])

 AT_CHECK_M4SH
@@ -1060,6 +1067,13 @@ ok 4
 ok 5
 ok 6
 ok 7
+ok 8
+ok 9
+ok 10
+ok 11
+ok 12
+ok 13
+ok 14
 ]])

 AT_CLEANUP
-- 
1.6.6.1


From e8402265cfad0a2992a7c97a7fb7f5190e6c054d Mon Sep 17 00:00:00 2001
From: Eric Blake <[email protected]>
Date: Sat, 27 Feb 2010 11:43:21 -0700
Subject: [PATCH 3/3] Use new AS_LITERAL_IF argument when appropriate.

* lib/m4sugar/m4sh.m4 (AS_VAR_SET): Reduce m4 overhead.
(AS_VAR_IF, AS_VAR_TEST_SET): Provide shorter variant for simple
references.
Suggested by Bruno Haible.

Signed-off-by: Eric Blake <[email protected]>
---
 ChangeLog           |    8 ++++++++
 lib/m4sugar/m4sh.m4 |    9 ++++++---
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 230d20e..7b082c5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2010-03-01  Eric Blake  <[email protected]>

+       Use new AS_LITERAL_IF argument when appropriate.
+       * lib/m4sugar/m4sh.m4 (AS_VAR_SET): Reduce m4 overhead.
+       (AS_VAR_IF, AS_VAR_TEST_SET): Provide shorter variant for simple
+       references.
+       Suggested by Bruno Haible.
+
+2010-03-01  Eric Blake  <[email protected]>
+
        Add optional argument to AS_LITERAL_IF.
        * lib/m4sugar/m4sh.m4 (_AS_LITERAL_IF): Rewrite to generate macro
        name, without using m4_cond.  Allow more control over whitespace.
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index 52edba8..7552046 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -1941,7 +1941,9 @@ m4_define([AS_VAR_IF],
 [AS_LITERAL_IF([$1],
   [AS_IF([test "x$$1" = x""$2]],
   [AS_VAR_COPY([as_val], [$1])
-   AS_IF([test "x$as_val" = x""$2]]), [$3], [$4])])
+   AS_IF([test "x$as_val" = x""$2]],
+  [AS_IF([eval test \"x\$"$1"\" = x"_AS_ESCAPE([$2], [`], [\"$])"]]),
+[$3], [$4])])


 # AS_VAR_PUSHDEF and AS_VAR_POPDEF
@@ -2005,7 +2007,7 @@ m4_pushdef([$1], [$as_[$1]])],
 m4_define([AS_VAR_SET],
 [AS_LITERAL_IF([$1],
               [$1=$2],
-              [eval "$1=AS_ESCAPE([$2])"])])
+              [eval "$1=_AS_ESCAPE([$2], [`], [\"$])"])])


 # AS_VAR_SET_IF(VARIABLE, IF-TRUE, IF-FALSE)
@@ -2023,7 +2025,8 @@ m4_define([AS_VAR_SET_IF],
 m4_define([AS_VAR_TEST_SET],
 [AS_LITERAL_IF([$1],
               [test "${$1+set}" = set],
-              [{ as_var=$1; eval "test \"\${$as_var+set}\" = set"; }])])
+              [{ as_var=$1; eval "test \"\${$as_var+set}\" = set"; }],
+              [eval "test \"\${$1+set}\"" = set])])


 ## -------------------- ##
-- 
1.6.6.1

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to