autoconf-patches
[Top][All Lists]
Advanced

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

[PATCH 4/7] Add optional argument to AS_LITERAL_IF.


From: Eric Blake
Subject: [PATCH 4/7] Add optional argument to AS_LITERAL_IF.
Date: Fri, 2 Jul 2010 13:37:49 -0600

* lib/m4sugar/m4sh.m4 (_AS_LITERAL_IF): Rewrite to generate macro
name, without using m4_cond.
(_AS_LITERAL_IF_, _AS_LITERAL_IF_YES, _AS_LITERAL_IF_NO): New
helpers.
(AS_LITERAL_IF, AS_LITERAL_WORD_IF, _AS_TR_SH, _AS_TR_CPP)
(_AS_VAR_PUSHDEF): Adjust callers.
* lib/autoconf/types.m4 (AC_CHECK_ALIGNOF): Relax restrictions on
invalid bytes, since this allows inline struct layouts.
(_AC_CHECK_ALIGNOF): New helper macro.
* tests/m4sh.at (AS@&address@hidden): Update test.
* doc/autoconf.texi (Polymorphic Variables) <AS_LITERAL_IF>:
Update documentation.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog             |   14 ++++++++++
 doc/autoconf.texi     |   18 +++++++++----
 lib/autoconf/types.m4 |   22 +++++++++++-----
 lib/m4sugar/m4sh.m4   |   67 ++++++++++++++++++++++++++++++++-----------------
 tests/m4sh.at         |    6 ++--
 5 files changed, 88 insertions(+), 39 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index dc2fa00..d835b3f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2010-07-02  Eric Blake  <address@hidden>

+       Add optional argument to AS_LITERAL_IF.
+       * lib/m4sugar/m4sh.m4 (_AS_LITERAL_IF): Rewrite to generate macro
+       name, without using m4_cond.
+       (_AS_LITERAL_IF_, _AS_LITERAL_IF_YES, _AS_LITERAL_IF_NO): New
+       helpers.
+       (AS_LITERAL_IF, AS_LITERAL_WORD_IF, _AS_TR_SH, _AS_TR_CPP)
+       (_AS_VAR_PUSHDEF): Adjust callers.
+       * lib/autoconf/types.m4 (AC_CHECK_ALIGNOF): Relax restrictions on
+       invalid bytes, since this allows inline struct layouts.
+       (_AC_CHECK_ALIGNOF): New helper macro.
+       * tests/m4sh.at (AS@&address@hidden): Update test.
+       * doc/autoconf.texi (Polymorphic Variables) <AS_LITERAL_IF>:
+       Update documentation.
+
        Use AS_LITERAL_WORD_IF as appropriate.
        * lib/autoconf/autoheader.m4 (AH_VERBATIM): Use new macro.
        * lib/autoconf/general.m4 (AC_REQUIRE_AUX_FILE, AC_CACHE_VAL)
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index ab7ed93..e6d4751 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -13298,15 +13298,20 @@ Polymorphic Variables
 undefined if expansion of an indirect variable does not result in a
 literal variable name.

address@hidden AS_LITERAL_IF (@var{expression}, @ovar{if-literal}, 
@ovar{if-not})
address@hidden AS_LITERAL_WORD_IF (@var{expression}, @ovar{if-literal})
address@hidden AS_LITERAL_IF (@var{expression}, @ovar{if-literal}, 
@ovar{if-not}, @
+  @dvar{if-simple-ref, @var{if-not}})
address@hidden AS_LITERAL_WORD_IF (@var{expression}, @ovar{if-literal}, @
+  @ovar{if-not}, @dvar{if-simple-ref, @var{if-not}})
 @asindex{LITERAL_IF}
 @asindex{LITERAL_WORD_IF}
 If the expansion of @var{expression} is definitely a shell literal,
 expand @var{if-literal}.  If the expansion of @var{expression} looks
 like it might contain shell indirections (such as @code{$var} or
address@hidden), then @var{if-not} is expanded.
address@hidden only expands
address@hidden), then @var{if-not} is expanded.  Sometimes, it is
+possible to output optimized code if @var{expression} consists only of
+shell variable expansions (such as @address@hidden@}}), in which case
address@hidden can be provided; but defaulting to @var{if-not}
+should always be safe.  @code{AS_LITERAL_WORD_IF} only expands
 @var{if-literal} if @var{expression} looks like a single shell word,
 containing no whitespace; while @code{AS_LITERAL_IF} allows whitespace
 in @var{expression}.
@@ -13327,7 +13332,7 @@ Polymorphic Variables
 @samp{_}).

 This example shows how to read the contents of the shell variable
address@hidden, exercising both arguments to @code{AS_LITERAL_IF}.  It
address@hidden, exercising all three arguments to @code{AS_LITERAL_IF}.  It
 results in a script that will output the line @samp{hello} three times.

 @example
@@ -13335,7 +13340,8 @@ Polymorphic Variables
 [AS_LITERAL_IF([$1],
   [echo "$$1"],
   [AS_VAR_COPY([tmp], [$1])
-   echo "$tmp"])])
+   echo "$tmp"],
+  [eval 'echo "$'"$1"\"])])
 foo=bar bar=hello
 MY_ACTION([bar])
 MY_ACTION([`echo bar`])
diff --git a/lib/autoconf/types.m4 b/lib/autoconf/types.m4
index 646b1dc..ee07148 100644
--- a/lib/autoconf/types.m4
+++ b/lib/autoconf/types.m4
@@ -785,25 +785,32 @@ AC_DEFINE_UNQUOTED(AS_TR_CPP(sizeof_$1), 
$AS_TR_SH([ac_cv_sizeof_$1]),

 # AC_CHECK_ALIGNOF(TYPE, [INCLUDES = DEFAULT-INCLUDES])
 # -----------------------------------------------------
+# TYPE can include braces and semicolon, which AS_TR_CPP and AS_TR_SH
+# (correctly) recognize as potential shell metacharacters.  So we
+# have to flatten problematic characters ourselves to guarantee that
+# AC_DEFINE_UNQUOTED will see a literal.
 AC_DEFUN([AC_CHECK_ALIGNOF],
-[AS_LITERAL_IF([$1], [],
-              [m4_fatal([$0: requires literal arguments])])]dnl
+[m4_if(m4_index(m4_translit([[$1]], [`\"], [$]), [$]), [-1], [],
+       [m4_fatal([$0: requires literal arguments])])]dnl
+[_$0([$1], [$2], m4_translit([[$1]], [{;}], [___]))])
+
+m4_define([_AC_CHECK_ALIGNOF],
 [# The cast to long int works around a bug in the HP C Compiler,
 # see AC_CHECK_SIZEOF for more information.
-_AC_CACHE_CHECK_INT([alignment of $1], [AS_TR_SH([ac_cv_alignof_$1])],
+_AC_CACHE_CHECK_INT([alignment of $1], [AS_TR_SH([ac_cv_alignof_$3])],
   [(long int) offsetof (ac__type_alignof_, y)],
   [AC_INCLUDES_DEFAULT([$2])
 #ifndef offsetof
 # define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0)
 #endif
 typedef struct { char x; $1 y; } ac__type_alignof_;],
-  [if test "$AS_TR_SH([ac_cv_type_$1])" = yes; then
+  [if test "$AS_TR_SH([ac_cv_type_$3])" = yes; then
      AC_MSG_FAILURE([cannot compute alignment of $1], 77)
    else
-     AS_TR_SH([ac_cv_alignof_$1])=0
+     AS_TR_SH([ac_cv_alignof_$3])=0
    fi])

-AC_DEFINE_UNQUOTED(AS_TR_CPP(alignof_$1), $AS_TR_SH([ac_cv_alignof_$1]),
+AC_DEFINE_UNQUOTED(AS_TR_CPP(alignof_$3), $AS_TR_SH([ac_cv_alignof_$3]),
                   [The normal alignment of `$1', in bytes.])
 ])# AC_CHECK_ALIGNOF

@@ -878,7 +885,8 @@ AC_DEFUN([AC_CHECK_MEMBER],
      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
+[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 b3c6006..d218eb2 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -1517,10 +1517,14 @@ 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 no shell indirections ($var or `expr`), expand
-# IF-LITERAL, else IF-NOT-LITERAL.
+# 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
@@ -1528,8 +1532,9 @@ m4_dquote(m4_dquote(m4_defn([m4_cr_symbols1])))[[))], 
[0], [-])])
 # assumption that it will be flattened to _).  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
+# literal, because it has different globbing.  Note, however, that
+# while `${a+b}' is neither a literal nor a simple ref, `a+b' is a
+# literal.  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.
 #
@@ -1548,30 +1553,44 @@ m4_dquote(m4_dquote(m4_defn([m4_cr_symbols1])))[[))], 
[0], [-])])
 # anything that might be in a macro name, as well as comments, commas,
 # or unbalanced parentheses.  Valid shell variable characters and
 # unambiguous literal characters are deleted (`a.b'), and remaining
-# characters are normalized into `$' if they are special to the
-# shell or to m4 parsing, and left alone otherwise.
+# characters are normalized into `$' if they can form simple refs
+# (${a}), `+' if they can potentially form literals (a+b), ``' if they
+# can interfere with m4 parsing, or left alone otherwise.  If both `$'
+# and `+' are left, it is treated as a complex reference (${a+b}),
+# even though it could technically be a simple reference (${a}+b).
 # _AS_LITERAL_IF_ only has to check for an empty string after removing
-# the normalized characters.
+# one of the two normalized characters.
 #
 # 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], address@hidden|@]) == -1)], [0], [],
-  [m4_index(m4_translit([$1], [[]`'\"$4,#()]]]dnl
-m4_dquote(m4_dquote(m4_defn([m4_cr_symbols2])))[[, [$$$$$$$5]), [$])],
-  [-1], [-]), [-], [$2], [$3])])
+[m4_if(m4_index([$1], address@hidden|@]), [-1], [$0_(m4_translit([$1],
+  [-:%/@{}[]#(),.$2]]]m4_dquote(m4_dquote(m4_defn([m4_cr_symbols2])))[[,
+  [+++++$$`````]))], [$0_NO])])

-# AS_LITERAL_WORD_IF(EXPRESSION, IF-LITERAL, IF-NOT-LITERAL)
+m4_define([_AS_LITERAL_IF_],
+[m4_if(m4_translit([$1], [+]), [], [$0YES],
+       m4_translit([$1], [$]), [], [m4_default], [$0NO])])
+
+m4_define([_AS_LITERAL_IF_YES], [$3])
+m4_define([_AS_LITERAL_IF_NO], [$2])
+
+# AS_LITERAL_WORD_IF(EXPRESSION, IF-LITERAL, IF-NOT-LITERAL,
+#                    [IF-SIMPLE-REF = IF-NOT-LITERAL])
 # ----------------------------------------------------------
 # Like AS_LITERAL_IF, except that spaces and tabs in EXPRESSION
 # are treated as non-literal.
 m4_define([AS_LITERAL_WORD_IF],
-[_AS_LITERAL_IF(m4_expand([$1]), [$2], [$3], [  ][
-], [$$$])])
-
+[_AS_LITERAL_IF(m4_expand([$1]))([$4], [$3], [$2])])


 # AS_TMPDIR(PREFIX, [DIRECTORY = $TMPDIR [= /tmp]])
@@ -1760,7 +1779,8 @@ 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]],
@@ -1792,7 +1812,8 @@ 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],
@@ -1994,10 +2015,10 @@ 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 5b3a55d..1e6eb59 100644
--- a/tests/m4sh.at
+++ b/tests/m4sh.at
@@ -1085,8 +1085,8 @@ echo AS_LITERAL_IF([lit], [ok], [ERR]) 1
 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], [ok], [fixme]) 5
-echo AS_LITERAL_IF([l${it}], [ERR1], [ok], [fixme]) 6
+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])
@@ -1094,7 +1094,7 @@ 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]) 11
-echo AS_LITERAL_IF([mac], [ERR1], [ok], [fixme]) 12
+echo AS_LITERAL_IF([mac], [ERR1], [ERR2], [ok]) 12
 m4_define([mac], [l``it])
 echo AS_LITERAL_IF([mac], [ERR], [ok]) 13
 echo AS_LITERAL_IF([mac], [ERR1], [ok], [ERR2]) 14
-- 
1.7.1




reply via email to

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