autoconf-patches
[Top][All Lists]
Advanced

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

Re: fewer forks during shell detection


From: Eric Blake
Subject: Re: fewer forks during shell detection
Date: Wed, 29 Oct 2008 16:58:15 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

Paolo Bonzini <bonzini <at> gnu.org> writes:

> > Also, we have a regression in _AS_LINENO_PREPARE.  The recent change to
> > put the shell detection code into the shell variables
> > as_suggested/as_required means hat we are now passing uses of $LINENO
> > through eval in order to check whether $LINENO works.
> 
> Actually the previous code was also using eval, but not through a variable:

Here's my proposed patch.  I've tested that $as_suggested has the desired 
value, and that both bash and pdksh now pass the LINENO test, while ash fails 
and proceeds to re-exec with bash.  I used TESTSUITEFLAGS='-d -k LINENO' then 
tweaked the reference file to add some strategic echos to make it easier to 
test multiple shells on a simple m4sh script.  On cygwin, pdksh was 
surprisingly faster than bash at running the remainder of the script once the 
better shell selection test concluded (1.0 vs. 1.5 seconds); likewise, zsh and 
posh were on par with pdksh.  I wonder what is making bash so much slower on 
cygwin, although that is independent of this issue.

> $ cat > foo <<\EOF
> eval "echo \$LINENO
> echo \$LINENO"
> f="echo \$LINENO
> echo \$LINENO"
> eval "$f"
> EOF
> $ bash foo
> 2
> 3
> 5
> 6
> 
> (Note that bash is wrong too!)

For that matter, I noticed this anomaly, present in all shells with LINENO 
support:

$ cat > foo <<\EOF
f1="$LINENO"
f2="$LINENO
"
echo $f1 $f2
EOF
$ bash foo
1 3

I would have expected "1 2" for the output, but the mere presence of a newline 
within the "" changes which line the $LINENO expands to.  POSIX certainly 
doesn't mention that!

Any comments before I apply this patch?


From: Eric Blake <address@hidden>
Date: Wed, 29 Oct 2008 10:39:53 -0600
Subject: [PATCH] Fix LINENO detection to work around bash and pdksh limitations.

* lib/m4sugar/m4sh.m4 (_AS_LINENO_WORKS): Enhance the test, so
that we can choose which of two tests to trust.
(_AS_RUN): Set flag when alternate shell is running.
(_AS_DETECT_EXPAND): New macro.
(_AS_DETECT_BETTER_SHELL): Use it to massage LINENO tests.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog           |    9 +++++++++
 lib/m4sugar/m4sh.m4 |   45 +++++++++++++++++++++++++++++++++++----------
 2 files changed, 44 insertions(+), 10 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index c59bb94..1833c14 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2008-10-29  Eric Blake  <address@hidden>
 
+       Fix LINENO detection to work around bash and pdksh limitations.
+       * lib/m4sugar/m4sh.m4 (_AS_LINENO_WORKS): Enhance the test, so
+       that we can choose which of two tests to trust.
+       (_AS_RUN): Set flag when alternate shell is running.
+       (_AS_DETECT_EXPAND): New macro.
+       (_AS_DETECT_BETTER_SHELL): Use it to massage LINENO tests.
+
+2008-10-29  Eric Blake  <address@hidden>
+
        Document current beta-quality status.
        * configure.ac: Reflect fact that change to git-version-gen
        produces -, but not always a letter, on non-release builds.
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index a9b6aec..2750982 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -153,6 +153,22 @@ m4_define([AS_COPYRIGHT],
 $1], [^], address@hidden:@ ])])])
 
 
+# _AS_DETECT_EXPAND(VAR, SET)
+# ---------------------------
+# Assign the contents of VAR from the contents of SET, expanded in such
+# a manner that VAR can be passed to _AS_RUN.  In order to make
+# _AS_LINENO_WORKS operate correctly, we must specially handle the
+# first instance of $LINENO within any line being expanded (the first
+# instance is important to tests using the current shell, leaving
+# remaining instances for tests using a candidate shell).  Bash loses
+# track of line numbers if a double quote contains a newline, hence,
+# we must piece-meal the assignment of VAR such that $LINENO expansion
+# occurs in a single line.
+m4_define([_AS_DETECT_EXPAND],
+[$1="m4_bpatsubst(m4_dquote(AS_ESCAPE(m4_expand(m4_set_contents([$2], [
+])))), [\\\$LINENO\(.*\)$], [";$1="$$1$LINENO";$1="$$1""\1])"])
+
+
 # _AS_DETECT_REQUIRED(TEST)
 # -------------------------
 # Refuse to execute under a shell that does not pass the given TEST.
@@ -198,10 +214,8 @@ dnl Remove any tests from suggested that are also required
 [m4_pushdef([AS_EXIT], [exit m4_default([$1], 1)])]dnl
 [if test "x$CONFIG_SHELL" = x; then
   as_bourne_compatible="AS_ESCAPE(m4_expand([_AS_BOURNE_COMPATIBLE]))"
-  as_required="AS_ESCAPE(m4_expand(m4_set_contents([_AS_DETECT_REQUIRED_BODY],
-    m4_newline)))"
-  as_suggested="AS_ESCAPE(m4_expand(m4_set_contents
([_AS_DETECT_SUGGESTED_BODY],
-    m4_newline)))"
+  _AS_DETECT_EXPAND([as_required], [_AS_DETECT_REQUIRED_BODY])
+  _AS_DETECT_EXPAND([as_suggested], [_AS_DETECT_SUGGESTED_BODY])
   AS_IF([_AS_RUN(["$as_required"])],
        [as_have_required=yes],
        [as_have_required=no])
@@ -358,8 +372,9 @@ m4_default_quoted([$4], [M4SH-INIT-FN]))])])
 # ----------------------
 # Run TEST under the current shell (if one parameter is used)
 # or under the given SHELL, protecting it from syntax errors.
+# Set as_run in order to assist _AS_LINENO_WORKS.
 m4_define([_AS_RUN],
-[m4_ifval([$2], [{ $as_echo "$as_bourne_compatible"$1 | ($2); }],
+[m4_ifval([$2], [{ $as_echo "$as_bourne_compatible"$1 | (as_run=a $2); }],
                [(eval $1)]) 2>/dev/null])
 
 
@@ -951,12 +966,22 @@ m4_defun([_AS_ME_PREPARE],
 # cause "bash -c '_ASLINENO_WORKS'" to fail (with Bash 2.05, anyway),
 # but that bug is irrelevant to our use of LINENO.  We can't use
 # AS_VAR_ARITH, as this is expanded prior to shell functions.
+#
+# Testing for LINENO support is hard; we use _AS_LINENO_WORKS inside
+# _AS_RUN, which sometimes eval's its argument (pdksh gives false
+# negatives if $LINENO is expanded by eval), and sometimes passes the
+# argument to another shell (if the current shell supports LINENO,
+# then expanding $LINENO prior to the string leads to false
+# positives).  Hence, we perform two tests, and coordinate with
+# _AS_DETECT_EXPAND (which ensures that only the first of two LINENO
+# is expanded in advance) and _AS_RUN (which sets $as_run to 'a' when
+# handing the test to another shell), so that we know which test to
+# trust.
 m4_define([_AS_LINENO_WORKS],
-[
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2"])
+[  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"'])
 
 
 # _AS_LINENO_PREPARE
-- 
1.6.0.2








reply via email to

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