autoconf-patches
[Top][All Lists]
Advanced

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

more efficient AS_EXIT


From: Eric Blake
Subject: more efficient AS_EXIT
Date: Thu, 23 Oct 2008 20:04:56 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

So, based on the recent discussion, does this patch look sane?  I also tried to 
clean up _AS_PREPARE, so that it doesn't require a duplicate listing of 
as_func_mkdir_p just to work around AS_REQUIRE* issues.

From: Eric Blake <address@hidden>
Date: Thu, 23 Oct 2008 11:27:11 -0600
Subject: [PATCH] Add AS_SET_STATUS, make AS_EXIT more efficient.

* lib/m4sugar/m4sh.m4 (_AS_EXIT_PREPARE, AS_SET_STATUS): New
macros.
(AS_EXIT): Rewrite to avoid forks.
(_AS_DETECT_REQUIRED, _AS_DETECT_SUGGESTED)
(_AS_DETECT_BETTER_SHELL, _AS_SHELL_SANITIZE): Avoid AS_EXIT in
contexts prior to shell functions.
(AS_REQUIRE_SHELL_FN): Factor...
(_AS_REQUIRE_SHELL_FN): ...into new helper macro.
(AS_PREPARE): Prepare the functions.
(_AS_PREPARE): Likewise.  Temporarily redefine AS_REQUIRE_SHELL_FN
to make this task easier.
(_AS_LINENO_PREPARE): Make more efficient.
(_AS_MKDIR_P_PREPARE): Simplify use in _AS_PREPARE.
* doc/autoconf.texi (Common Shell Constructs) <AS_EXIT>,
<AS_SET_STATUS>: Document.
(Limitations of Builtins): Mention AS_EXIT.
* NEWS: Mention new macro.
* bin/autoconf.as: Use AS_EXIT consistently.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog           |   22 +++++++++++
 NEWS                |    9 +++--
 bin/autoconf.as     |    8 ++--
 doc/autoconf.texi   |   17 ++++++++-
 lib/m4sugar/m4sh.m4 |  100 +++++++++++++++++++++++++++++++++------------------
 5 files changed, 112 insertions(+), 44 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index da1654e..94e0118 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2008-10-23  Eric Blake  <address@hidden>
+
+       Add AS_SET_STATUS, make AS_EXIT more efficient.
+       * lib/m4sugar/m4sh.m4 (_AS_EXIT_PREPARE, AS_SET_STATUS): New
+       macros.
+       (AS_EXIT): Rewrite to avoid forks.
+       (_AS_DETECT_REQUIRED, _AS_DETECT_SUGGESTED)
+       (_AS_DETECT_BETTER_SHELL, _AS_SHELL_SANITIZE): Avoid AS_EXIT in
+       contexts prior to shell functions.
+       (AS_REQUIRE_SHELL_FN): Factor...
+       (_AS_REQUIRE_SHELL_FN): ...into new helper macro.
+       (AS_PREPARE): Prepare the functions.
+       (_AS_PREPARE): Likewise.  Temporarily redefine AS_REQUIRE_SHELL_FN
+       to make this task easier.
+       (_AS_LINENO_PREPARE): Make more efficient.
+       (_AS_MKDIR_P_PREPARE): Simplify use in _AS_PREPARE.
+       * doc/autoconf.texi (Common Shell Constructs) <AS_EXIT>,
+       <AS_SET_STATUS>: Document.
+       (Limitations of Builtins): Mention AS_EXIT.
+       * NEWS: Mention new macro.
+       * bin/autoconf.as: Use AS_EXIT consistently.
+
 2008-10-23  Paolo Bonzini  <address@hidden>
 
        Eliminate empty lines after AC_*_IFELSE.
diff --git a/NEWS b/NEWS
index 8b682b8..f8f4482 100644
--- a/NEWS
+++ b/NEWS
@@ -17,12 +17,13 @@ GNU Autoconf NEWS - User visible changes.
    m4_set_map
 
 ** The following documented m4sh macros are new:
-   AS_LINENO_PREPARE  AS_ME_PREPARE  AS_VAR_APPEND  AS_VAR_COPY
+   AS_LINENO_PREPARE  AS_ME_PREPARE  AS_SET_STATUS  AS_VAR_APPEND
+   AS_VAR_COPY
 
 ** The following m4sh macros are documented now:
-   AS_ECHO  AS_ECHO_N  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
+   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_VAR_TEST_SET  AS_VERSION_COMPARE
 
 ** The m4sh macros AS_IF and AS_CASE can now be used in shell lists.
    The responsibility for supplying a trailing newline now belongs to
diff --git a/bin/autoconf.as b/bin/autoconf.as
index 6eab32a..c678e55 100644
--- a/bin/autoconf.as
+++ b/bin/autoconf.as
@@ -81,7 +81,7 @@ Try \`$as_me --help' for more information."
 exit_missing_arg='
   AS_ECHO(["$as_me: option \`$[1]'\'' requires an argument"]) >&2
   AS_ECHO(["$help"]) >&2
-  exit 1
+  AS_EXIT([1])
 ' # restore font-lock: "
 
 # Variables.
@@ -156,7 +156,7 @@ while test $# -gt 0 ; do
        exec >&2
        AS_ECHO(["$as_me: invalid option $[1]"])
        AS_ECHO(["$help"])
-       exit 1 ;;
+       AS_EXIT([1]) ;;
     * )
        break ;;
   esac
@@ -175,7 +175,7 @@ case $# in
       infile=configure.in
     else
       AS_ECHO(["$as_me: no input file"]) >&2
-      exit 1
+      AS_EXIT([1])
     fi
     test -z "$traces" && test -z "$outfile" && outfile=configure;;
   1)
@@ -183,7 +183,7 @@ case $# in
   *) exec >&2
      AS_ECHO(["$as_me: invalid number of arguments."])
      AS_ECHO(["$help"])
-     (exit 1); exit 1 ;;
+     AS_EXIT([1]) ;;
 esac
 
 # Unless specified, the output is stdout.
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index 71f507f..01d7302 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -11947,6 +11947,14 @@ Common Shell Constructs
 Redirections can be placed outside the macro invocation.
 @end defmac
 
address@hidden AS_EXIT (@dvar{status, 1})
address@hidden
+Emit code to exit the shell with @var{status}.  This works around shells
+that see the exit status of the command prior to @code{exit} inside a
address@hidden 0} handler (@pxref{Limitations of Builtins, , Limitations of
+Shell Builtins}).
address@hidden defmac
+
 @defmac AS_IF (@var{test1}, @ovar{run-if-true1}, @dots{}, @ovar{run-if-false})
 @asindex{IF}
 Run shell code @var{test1}.  If @var{test1} exits with a zero status then
@@ -11981,6 +11989,12 @@ Common Shell Constructs
 Also see the @code{AC_PROG_MKDIR_P} macro (@pxref{Particular Programs}).
 @end defmac
 
address@hidden AS_SET_STATUS (@var{status})
address@hidden
+Emit shell code to set the value of @samp{$?} to @var{status} without
+forking.
address@hidden defmac
+
 @defmac AS_TR_CPP (@var{expression})
 @asindex{TR_CPP}
 Transform @var{expression} into a valid right-hand side for a C @code{#define}.
@@ -15414,7 +15428,8 @@ Limitations of Builtins
 The portable solution is then simple: when you want to @samp{exit 42},
 run @samp{(exit 42); exit 42}, the first @command{exit} being used to
 set the exit status to 42 for Zsh, and the second to trigger the trap
-and pass 42 as exit status for Bash.
+and pass 42 as exit status for Bash.  In m4sh, this is covered by using
address@hidden
 
 The shell in address@hidden 4.0 has the following bug: @samp{$?} is
 reset to 0 by empty lines if the code is inside @command{trap}.
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index b96ec09..74c814c 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -157,9 +157,10 @@ $1], [^], address@hidden:@ ])])])
 # -------------------------
 # Refuse to execute under a shell that does not pass the given TEST.
 # Does not do AS_REQUIRE for the better-shell detection code.
+# This code is not run in a trap context, so plain exit suffices.
 m4_defun([_AS_DETECT_REQUIRED],
 [m4_set_add([_AS_DETECT_REQUIRED_BODY],
-          [($1) || AS_EXIT(1)
+           [($1) || exit 1
 ])])
 
 
@@ -167,9 +168,10 @@ m4_defun([_AS_DETECT_REQUIRED],
 # --------------------------
 # Prefer to execute under a shell that passes the given TEST.
 # Does not do AS_REQUIRE for the better-shell detection code.
+# This code is not run in a trap context, so plain exit suffices.
 m4_defun([_AS_DETECT_SUGGESTED],
 [m4_set_add([_AS_DETECT_SUGGESTED_BODY],
-          [($1) || AS_EXIT(1)
+           [($1) || exit 1
 ])])
 
 
@@ -241,7 +243,7 @@ dnl Remove any tests from suggested that are also required
       echo shells that I found on your system.  Please install a
       echo modern shell, or manually run the script under such a
       echo shell if you do have one.
-      AS_EXIT(1)])])
+      exit 1])])
 fi
 ])# _AS_DETECT_BETTER_SHELL
 
@@ -255,17 +257,17 @@ fi
 # and config.status.  Relying on AS_REQUIRE is of course fine for
 # configure, but fails for config.status (which is created by
 # configure).  So we need a means to force the inclusion of the
-# various _AS_PREPARE_* on top of config.status.  That's basically why
-# there are so many _AS_PREPARE_* below, and that's also why it is
+# various _AS_*_PREPARE on top of config.status.  That's basically why
+# there are so many _AS_*_PREPARE below, and that's also why it is
 # important not to forget some: config.status needs them.
+# List any preparations that create shell functions first, then
+# topologically sort the others by their dependencies.
 m4_defun([_AS_PREPARE],
-[m4_pushdef([AS_REQUIRE], [])]dnl
-[AS_FUNCTION_DESCRIBE([as_func_mkdir_p], [],
-[Create "$as_dir" as a directory, including parents if necessary.])
-as_func_mkdir_p ()
-{
-  _AS_MKDIR_P
-}
+[m4_pushdef([AS_REQUIRE])]dnl
+[m4_pushdef([AS_REQUIRE_SHELL_FN], _m4_defn([_AS_REQUIRE_SHELL_FN]))]dnl
+[_AS_EXIT_PREPARE
+_AS_UNSET_PREPARE
+_AS_VAR_APPEND_PREPARE
 
 _AS_EXPR_PREPARE
 _AS_BASENAME_PREPARE
@@ -278,9 +280,7 @@ _AS_MKDIR_P_PREPARE
 _AS_TEST_PREPARE
 _AS_TR_CPP_PREPARE
 _AS_TR_SH_PREPARE
-_AS_UNSET_PREPARE
-_AS_VAR_APPEND_PREPARE
-m4_popdef([AS_REQUIRE])])
+_m4_popdef([AS_REQUIRE], [AS_REQUIRE_SHELL_FN])])
 
 # AS_PREPARE
 # ----------
@@ -296,6 +296,7 @@ AS_REQUIRE([_AS_DIRNAME_PREPARE])
 AS_REQUIRE([_AS_ME_PREPARE])
 AS_REQUIRE([_AS_LINENO_PREPARE])
 AS_REQUIRE([_AS_ECHO_N_PREPARE])
+AS_REQUIRE([_AS_EXIT_PREPARE])
 AS_REQUIRE([_AS_LN_S_PREPARE])
 AS_REQUIRE([_AS_MKDIR_P_PREPARE])
 AS_REQUIRE([_AS_TEST_PREPARE])
@@ -325,6 +326,14 @@ m4_defun([AS_REQUIRE],
        1, [m4_require(],
          [m4_divert_require(_m4_divert(_m4_divert_desired),]) [$1], [$2])])
 
+# _AS_REQUIRE_SHELL_FN(NAME-TO-CHECK, COMMENT, BODY-TO-EXPAND)
+# ------------------------------------------------------------
+# Core of AS_REQUIRE_SHELL_FN, but without diversion support.
+m4_define([_AS_REQUIRE_SHELL_FN], [
+m4_n([$2])$1 ()
+{
+$3
+} @%:@ $1[]])
 
 # AS_REQUIRE_SHELL_FN(NAME-TO-CHECK, COMMENT, BODY-TO-EXPAND,
 #                     [DIVERSION = M4SH-INIT-FN])
@@ -337,12 +346,8 @@ m4_defun([AS_REQUIRE],
 m4_define([AS_REQUIRE_SHELL_FN],
 [m4_provide_if([AS_SHELL_FN_$1], [],
 [AS_REQUIRE([AS_SHELL_FN_$1],
-[m4_provide([AS_SHELL_FN_$1])
-m4_n([$2])$1 ()
-{
-$3
-} [#] $1
-], m4_default_quoted([$4], [M4SH-INIT-FN]))])])
+[m4_provide([AS_SHELL_FN_$1])_$0($@)],
+m4_default_quoted([$4], [M4SH-INIT-FN]))])])
 
 
 # _AS_RUN(TEST, [SHELL])
@@ -402,6 +407,9 @@ test x$exitcode = x0[]])# _AS_SHELL_FN_WORK
 # _AS_SHELL_SANITIZE
 # ------------------
 # This is the prolog that is emitted by AS_INIT and AS_INIT_GENERATED.
+# It is run before shell functions are enabled, so it cannot use
+# things like AS_EXIT; however, it is not in a trap context, so plain
+# exit 1 suffices.
 m4_defun([_AS_SHELL_SANITIZE],
 [m4_text_box([M4sh Initialization.])
 
@@ -433,7 +441,7 @@ if test "x$as_myself" = x; then
 fi
 if test ! -f "$as_myself"; then
   AS_ECHO(["$as_myself: error: cannot find myself; rerun with an absolute file 
name"]) >&2
-  AS_EXIT
+  exit 1
 fi
 
 # Unset variables that we do not need and which cause bugs (e.g. in
@@ -502,18 +510,34 @@ m4_defun([AS_CASE],
 esac])# AS_CASE
 
 
-# AS_EXIT([EXIT-CODE = 1])
-# ------------------------
-# Exit and set exit code to EXIT-CODE in the way that it's seen
-# within "trap 0".
+# _AS_EXIT_PREPARE
+# ----------------
+# Ensure AS_EXIT and AS_SET_STATUS will work.
 #
 # We cannot simply use "exit N" because some shells (zsh and Solaris sh)
 # will not set $? to N while running the code set by "trap 0"
-# So we set $? by executing "exit N" in the subshell and then exit.
+# Some shells fork even for (exit N), so we use a helper function
+# to set $? prior to the exit.
 # Other shells don't use `$?' as default for `exit', hence just repeating
 # the exit value can only help improving portability.
-m4_define([AS_EXIT],
-[{ (exit m4_default([$1], 1)); exit m4_default([$1], 1); }])
+m4_defun([_AS_EXIT_PREPARE],
+[AS_REQUIRE_SHELL_FN([as_func_set_status],
+  [AS_FUNCTION_DESCRIBE([as_func_set_status], [STATUS],
+    [Set $? to STATUS, without forking.])], [  return $[]1])]dnl
+[AS_REQUIRE_SHELL_FN([as_func_exit],
+  [AS_FUNCTION_DESCRIBE([as_func_exit], [STATUS],
+    [Exit the shell with STATUS, even in a "trap 0" or "set -e" context.])],
+[  set +e
+  as_func_set_status $[]1
+  exit $[]1])])#_AS_EXIT_PREPARE
+
+
+# AS_EXIT([EXIT-CODE = 1])
+# ------------------------
+# Exit and set exit code to EXIT-CODE in the way that it's seen
+# within "trap 0", and tolerant of "set -e".
+m4_defun([AS_EXIT],
+[AS_REQUIRE([_AS_EXIT_PREPARE])[]as_func_exit m4_default([$1], 1)])
 
 
 # AS_IF(TEST1, [IF-TRUE1 = :]...[IF-FALSE = :])
@@ -545,6 +569,13 @@ m4_map_args_pair([_$0], [_$0_ELSE], m4_shift2($@))]dnl
 [fi[]])# AS_IF
 
 
+# AS_SET_STATUS(STATUS)
+# ---------------------
+# Set the shell status ($?) to STATUS, without forking.
+m4_defun([AS_SET_STATUS],
+[AS_REQUIRE([_AS_EXIT_PREPARE])[]as_func_set_status $1])
+
+
 # _AS_UNSET_PREPARE
 # -----------------
 # Define $as_unset to execute AS_UNSET, for backwards compatibility
@@ -555,8 +586,7 @@ as_func_unset ()
 {
   AS_UNSET([$[1]])
 }
-as_unset=as_func_unset
-])
+as_unset=as_func_unset])
 
 
 # AS_UNSET(VAR)
@@ -1001,7 +1031,7 @@ dnl Eggert wrote the scripts with optimization help from 
Paolo Bonzini).
   # Exit status is that of the last command.
   exit
 }
-m4_popdef([AS_MESSAGE_LOG_FD])])# _AS_LINENO_PREPARE
+_m4_popdef([AS_MESSAGE_LOG_FD])])# _AS_LINENO_PREPARE
 
 
 # _AS_LN_S_PREPARE
@@ -1090,8 +1120,8 @@ m4_defun([_AS_MKDIR_P_PREPARE],
     [Create "$as_dir" as a directory, including parents if necessary.])],
 [
   _AS_MKDIR_P
-])
-if mkdir -p . 2>/dev/null; then
+])]dnl
+[if mkdir -p . 2>/dev/null; then
   as_mkdir_p='mkdir -p "$as_dir"'
 else
   test -d ./-p && rmdir ./-p
@@ -1818,5 +1848,5 @@ m4_divert_pop([KILL])[]dnl
 m4_divert_push([BODY])
 m4_text_box([Main body of script.])
 _AS_DETECT_REQUIRED([_AS_SHELL_FN_WORK])dnl
-AS_REQUIRE([_AS_UNSET_PREPARE])dnl For backwards compatibility.
+AS_REQUIRE([_AS_UNSET_PREPARE], [], [M4SH-INIT-FN])dnl
 ])
-- 
1.6.0.2








reply via email to

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