]> git.ipfire.org Git - thirdparty/autoconf.git/commitdiff
Add AS_SET_STATUS, make AS_EXIT more efficient.
authorEric Blake <ebb9@byu.net>
Mon, 17 Nov 2008 22:49:30 +0000 (15:49 -0700)
committerEric Blake <ebb9@byu.net>
Tue, 18 Nov 2008 16:57:19 +0000 (09:57 -0700)
* lib/m4sugar/m4sh.m4 (_AS_EXIT_PREPARE, AS_SET_STATUS): New
macros.
(AS_EXIT): Rewrite to avoid forks.
(_AS_SHELL_SANITIZE): Avoid AS_EXIT prior to shell functions.
(AS_PREPARE, _AS_PREPARE): Add new preparation.
* doc/autoconf.texi (Common Shell Constructs) <AS_SET_STATUS>:
Document.
* NEWS: Mention new macro.
* tests/m4sh.at (AS@&t@_EXIT): New test.
(BASENAME_TEST): Sort.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
NEWS
doc/autoconf.texi
lib/m4sugar/m4sh.m4
tests/m4sh.at

index 543ce5d96fba4a8aff19c44a66bd7207b57978c3..1e56b6e9354484bb409cb0317e2066e937173acb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2008-11-18  Eric Blake  <ebb9@byu.net>
 
+       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_SHELL_SANITIZE): Avoid AS_EXIT prior to shell functions.
+       (AS_PREPARE, _AS_PREPARE): Add new preparation.
+       * doc/autoconf.texi (Common Shell Constructs) <AS_SET_STATUS>:
+       Document.
+       * NEWS: Mention new macro.
+       * tests/m4sh.at (AS@&t@_EXIT): New test.
+       (BASENAME_TEST): Sort.
+
        Document Tru64 bug with 'set -e'.
        * doc/autoconf.texi (Limitations of Builtins) <trap>: Mention a
        bug in mixing 'set -e' with 'trap .. 0'.
diff --git a/NEWS b/NEWS
index f5f3d6e3abfb4adf95d8b9a033a78184a81ce7f0..b67d82ce607a808b1ba870438f7ff0cf6f102f7f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -30,8 +30,8 @@ GNU Autoconf NEWS - User visible changes.
    m4_copy  m4_dumpdefs  m4_rename
 
 ** The following documented m4sh macros are new:
-   AS_LINENO_PREPARE  AS_ME_PREPARE  AS_VAR_APPEND  AS_VAR_ARITH
-   AS_VAR_COPY
+   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:
    AS_ECHO  AS_ECHO_N  AS_EXIT  AS_LITERAL_IF  AS_UNSET  AS_VAR_IF
index 37becc5f1bbcc93b7d40f888fb3c2ad09fe39a97..71d72f4e75ec95dad34f86434285ee4de7075488 100644 (file)
@@ -12052,6 +12052,14 @@ script.
 Also see the @code{AC_PROG_MKDIR_P} macro (@pxref{Particular Programs}).
 @end defmac
 
+@defmac AS_SET_STATUS (@var{status})
+@asindex{SET_STATUS}
+Emit shell code to set the value of @samp{$?} to @var{status} without
+forking.  However, this is not guaranteed to abort a shell running with
+@code{set -e} (@pxref{Limitations of Builtins, , Limitations of Shell
+Builtins}).
+@end defmac
+
 @defmac AS_TR_CPP (@var{expression})
 @asindex{TR_CPP}
 Transform @var{expression} into a valid right-hand side for a C @code{#define}.
index 4da8f37810d68d5268fa8fc63d4b0597387b8b6c..f056ee315ccf80d73a6b4d1fe0306c75ac2e4dae 100644 (file)
@@ -299,7 +299,8 @@ m4_defun([_AS_PREPARE],
 [m4_pushdef([AS_REQUIRE])]dnl
 [m4_pushdef([AS_REQUIRE_SHELL_FN], _m4_defn([_AS_REQUIRE_SHELL_FN])
 )]dnl
-[_AS_UNSET_PREPARE
+[_AS_EXIT_PREPARE
+_AS_UNSET_PREPARE
 _AS_VAR_APPEND_PREPARE
 _AS_VAR_ARITH_PREPARE
 
@@ -331,6 +332,7 @@ AS_REQUIRE([_AS_ME_PREPARE])
 AS_REQUIRE([_AS_CR_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])
@@ -418,8 +420,11 @@ 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.
+# This is the prolog that is emitted by AS_INIT and AS_INIT_GENERATED;
+# it is executed prior to shell function definitions, hence the
+# temporary redefinition of AS_EXIT.
 m4_defun([_AS_SHELL_SANITIZE],
+[m4_pushdef([AS_EXIT], [exit m4_default([$1], 1)])]dnl
 [m4_text_box([M4sh Initialization.])
 
 AS_BOURNE_COMPATIBLE
@@ -470,7 +475,7 @@ export LANGUAGE
 
 # CDPATH.
 (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-])# _AS_SHELL_SANITIZE
+_m4_popdef([AS_EXIT])])# _AS_SHELL_SANITIZE
 
 
 # AS_SHELL_SANITIZE
@@ -519,18 +524,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, with status set to EXIT-CODE in the way that it's seen
+# within "trap 0", and without interference from "set -e".
+m4_defun([AS_EXIT],
+[AS_REQUIRE([_AS_EXIT_PREPARE])[]as_func_exit m4_default([$1], 1)])
 
 
 # AS_FOR(MACRO, SHELL-VAR, [LIST = "$@"], [BODY = :])
@@ -589,6 +610,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
index 96e0452db37d5554228a5f5558fa3e652372488b..85ad5d8b1cbfd997357fd79bdd097f317bcb229c 100644 (file)
@@ -126,6 +126,63 @@ AT_CHECK([./script])
 AT_CLEANUP
 
 
+## ------------- ##
+## AS_BASENAME.  ##
+## ------------- ##
+
+# Strip path from file.
+AT_SETUP([AS@&t@_BASENAME])
+AT_KEYWORDS([m4sh])
+
+AT_DATA_M4SH([script.as],
+[[AS_INIT
+
+m4_define([BASENAME_TEST],
+[base=`AS_BASENAME([$1])`
+test "$base" = "$2" ||
+  echo "basename($1) = $base instead of $2" >&2
+
+base=`_AS_BASENAME_SED([$1])`
+test "$base" = "$2" ||
+  echo "basename_sed($1) = $base instead of $2" >&2])
+
+BASENAME_TEST([//1],             [1])
+BASENAME_TEST([/1],              [1])
+BASENAME_TEST([./1],             [1])
+BASENAME_TEST([../../2],         [2])
+BASENAME_TEST([//1/],            [1])
+BASENAME_TEST([/1/],             [1])
+BASENAME_TEST([./1/],            [1])
+BASENAME_TEST([../../2],         [2])
+BASENAME_TEST([//1/3],           [3])
+BASENAME_TEST([/1/3],            [3])
+BASENAME_TEST([./1/3],           [3])
+BASENAME_TEST([../../2/3],       [3])
+BASENAME_TEST([//1/3///],        [3])
+BASENAME_TEST([/1/3///],         [3])
+BASENAME_TEST([./1/3///],        [3])
+BASENAME_TEST([../../2/3///],    [3])
+BASENAME_TEST([//1//3/],         [3])
+BASENAME_TEST([/1//3/],          [3])
+BASENAME_TEST([./1//3/],         [3])
+BASENAME_TEST([a.c],             [a.c])
+BASENAME_TEST([a.c/],            [a.c])
+BASENAME_TEST([/a.c/],           [a.c])
+BASENAME_TEST([/1/a.c],          [a.c])
+BASENAME_TEST([/1/a.c/],         [a.c])
+BASENAME_TEST([/1/../a.c],       [a.c])
+BASENAME_TEST([/1/../a.c/],      [a.c])
+BASENAME_TEST([./1/a.c],         [a.c])
+BASENAME_TEST([./1/a.c/],        [a.c])
+AS_EXIT(0)
+]])
+
+AT_CHECK_M4SH
+AT_CHECK([./script])
+
+AT_CLEANUP
+
+
 ## ------------ ##
 ## AS_DIRNAME.  ##
 ## ------------ ##
@@ -236,59 +293,43 @@ AT_CLEANUP
 
 
 
-## ------------- ##
-## AS_BASENAME.  ##
-## ------------- ##
+## --------- ##
+## AS_EXIT.  ##
+## --------- ##
 
-# Strip path from file.
-AT_SETUP([AS@&t@_BASENAME])
-AT_KEYWORDS([m4sh])
+# Exit scripts with given status.
+AT_SETUP([AS@&t@_EXIT])
+AT_KEYWORDS([m4sh AS@&t@_SET_STATUS])
 
 AT_DATA_M4SH([script.as],
 [[AS_INIT
-
-m4_define([BASENAME_TEST],
-[base=`AS_BASENAME([$1])`
-test "$base" = "$2" ||
-  echo "basename($1) = $base instead of $2" >&2
-
-base=`_AS_BASENAME_SED([$1])`
-test "$base" = "$2" ||
-  echo "basename_sed($1) = $base instead of $2" >&2])
-
-BASENAME_TEST([//1],             [1])
-BASENAME_TEST([/1],              [1])
-BASENAME_TEST([./1],             [1])
-BASENAME_TEST([../../2],         [2])
-BASENAME_TEST([//1/],            [1])
-BASENAME_TEST([/1/],             [1])
-BASENAME_TEST([./1/],            [1])
-BASENAME_TEST([../../2],         [2])
-BASENAME_TEST([//1/3],           [3])
-BASENAME_TEST([/1/3],            [3])
-BASENAME_TEST([./1/3],           [3])
-BASENAME_TEST([../../2/3],       [3])
-BASENAME_TEST([//1/3///],        [3])
-BASENAME_TEST([/1/3///],         [3])
-BASENAME_TEST([./1/3///],        [3])
-BASENAME_TEST([../../2/3///],    [3])
-BASENAME_TEST([//1//3/],         [3])
-BASENAME_TEST([/1//3/],          [3])
-BASENAME_TEST([./1//3/],         [3])
-BASENAME_TEST([a.c],             [a.c])
-BASENAME_TEST([a.c/],            [a.c])
-BASENAME_TEST([/a.c/],           [a.c])
-BASENAME_TEST([/1/a.c],          [a.c])
-BASENAME_TEST([/1/a.c/],         [a.c])
-BASENAME_TEST([/1/../a.c],       [a.c])
-BASENAME_TEST([/1/../a.c/],      [a.c])
-BASENAME_TEST([./1/a.c],         [a.c])
-BASENAME_TEST([./1/a.c/],        [a.c])
-AS_EXIT(0)
+test x${1} = xa && AS_EXIT
+test x${1} = xb && AS_EXIT([${2}])
+test x${1} = xc && trap 's=$?; echo $s; AS_EXIT([$s])' 0
+test x${2} = xd && set -e
+AS_SET_STATUS([3])
+dnl Solaris /bin/sh 'set -e' doesn't react to failed function calls
+test x${2} = xd \
+  && { echo 'skipping rest of test: set -e support is lousy'; exit 77; }
+AS_SET_STATUS([4])
 ]])
 
 AT_CHECK_M4SH
-AT_CHECK([./script])
+AT_CHECK([./script], [4])
+AT_CHECK([./script a], [1])
+AT_CHECK([./script b], [0])
+AT_CHECK([./script b 2], [2])
+AT_CHECK([./script c], [4], [[4
+]])
+dnl If we got to this point without a FAIL, then AS_EXIT at least works.
+dnl The rest of this test relies on semi-decent 'set -e' support, even
+dnl though m4sh in general should not try to rely on it because of
+dnl portability nightmares on what constructs are considered errors across
+dnl various shells; therefore, an overall SKIP result is desirable on
+dnl broken shells like Solaris /bin/sh.
+AT_CHECK([./script '' d], [3])
+AT_CHECK([./script c d], [3], [[3
+]])
 
 AT_CLEANUP