[PATCH] lib: use shorter way to test if variable is set

Eric Blake <[email protected]>
Newsgroups gmane.comp.sysutils.autoconf.patches
Message-ID <[email protected]>
Based on an idea by Bernhard Reutner-Fischer.

We frequently used the idiom of 'test "${var+set}" = set' to
test if $var was set to a non-empty string, but this can portably
be trimmed to a more compact 'test ${var+y}' for a smaller
configure file.  Testing that a variable is not set can be done
with '${var+false} :' (although the value of $? is not reliably
1 when the variable is set).

The code for AS_VAR_TEST_SET already used the form '${var+:} false',
but it is slightly longer, and does not guarantee $? of 1.

Tested on coreutils, where the resulting configure file is about
1k smaller.

* doc/autoconf.texi (Shell Substitutions): Prefer shorter sequence
for testing if a variable is set.
(Limitations of Builtins) <test (strings)>: Document it.
* configure.ac: Use it.
* lib/autoconf/c.m4 (_AC_PROG_CC_G, _AC_PROG_CXX_G)
(_AC_PROG_OBJC_G, _AC_PROG_OBJCXX_G): Likewise.
* lib/autoconf/fortran.m4 (_AC_PROG_FC_G): Likewise.
* lib/autoconf/general.m4 (_AC_ENABLE_IF_ACTION, AC_CACHE_SAVE):
Likewise.
* lib/autoconf/lang.m4 (_AC_COMPILER_EXEEXT_DEFAULT): Likewise.
* lib/autoconf/programs.m4 (AC_PROG_INSTALL, AC_PROG_MKDIR_P)
(_AC_PROG_LEX_YYTEXT_DECL): Likewise.
* lib/autoconf/status.m4 (_AC_OUTPUT_MAIN_LOOP): Likewise.
* lib/autotest/general.m4 (AT_INIT): Likewise.
* tests/base.at (AC_CACHE_CHECK): Likewise.
* tests/m4sh.at (LINENO): Likewise.
* lib/m4sugar/m4sh.m4 (_AS_BOURNE_COMPATIBLE)
(_AS_DETECT_BETTER_SHELL, _AS_SHELL_SANITIZE)
(_AS_PATH_SEPARATOR_PREPARE): Likewise.
(AS_VAR_TEST_SET): Use shorter sequence.

Signed-off-by: Eric Blake <[email protected]>
---

Finally finding time to revisit this; here's what I will probably
push, if no negative review comments are raised in a couple days.

I'll probably also work on a second patch that scrubs obvious
uses of 'test -n "$var"' and 'test -z "$var"'; this patch just
touched ${var+set} instances, plus AS_VAR_TEST_SET.

 configure.ac             |  6 +++---
 doc/autoconf.texi        | 13 ++++++++-----
 lib/autoconf/c.m4        | 16 ++++++++--------
 lib/autoconf/fortran.m4  |  4 ++--
 lib/autoconf/general.m4  |  4 ++--
 lib/autoconf/lang.m4     |  2 +-
 lib/autoconf/programs.m4 |  6 +++---
 lib/autoconf/status.m4   |  8 ++++----
 lib/autotest/general.m4  |  4 ++--
 lib/m4sugar/m4sh.m4      | 14 +++++++-------
 tests/base.at            |  2 +-
 tests/m4sh.at            |  4 ++--
 12 files changed, 43 insertions(+), 40 deletions(-)

diff --git a/configure.ac b/configure.ac
index 2709a0d..e7029eb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -61,9 +61,9 @@ AC_CACHE_CHECK([whether /bin/sh -n is known to work], [ac_cv_sh_n_works],
 [if (
     unset BASH_VERSION ZSH_VERSION
     /bin/sh -c '
-      test -n "${BASH_VERSION+set}" || # Bash
-      test -n "${KSH_VERSION+set}" || # pdksh
-      test -n "${ZSH_VERSION+set}" || # zsh
+      test ${BASH_VERSION+y} || # Bash
+      test ${KSH_VERSION+y} || # pdksh
+      test ${ZSH_VERSION+y} || # zsh
       test -n "${.sh.version}" # ksh93; put this last since its syntax is dodgy
     '
   ) 2>/dev/null
diff --git a/doc/autoconf.texi b/doc/autoconf.texi
index d9e833d..bab87ad 100644
--- a/doc/autoconf.texi
+++ b/doc/autoconf.texi
@@ -15977,7 +15977,7 @@ Shell Substitutions
 @samp{$@{1+"$@@"@}} into @samp{"$@@"} by itself:

 @example
-test "$@{ZSH_VERSION+set@}" = set && alias -g '$@{1+"$@@"@}'='"$@@"'
+test $@{ZSH_VERSION+y@} && alias -g '$@{1+"$@@"@}'='"$@@"'
 @end example

 Zsh only recognizes this alias when a shell word matches it exactly;
@@ -16297,7 +16297,7 @@ Shell Substitutions
 use:

 @example
-test "$@{var+set@}" = set || var=@var{@{value@}}
+test $@{var+y@} || var=@var{@{value@}}
 @end example

 @item $@{#@var{var}@}
@@ -16547,7 +16547,7 @@ Assignments
 If the default value contains a closing brace, then use:

 @example
-test "$@{var+set@}" = set || var="has a '@}'"
+test $@{var+y@} || var="has a '@}'"
 @end example
 @end enumerate

@@ -18076,7 +18076,7 @@ Limitations of Builtins
 @command{/bin/sh} takes extremely long to parse large scripts.  Autoconf
 itself uses @command{sh -n} within its testsuite to check that correct
 scripts were generated, but only after first probing for other shell
-features (such as @code{test -n "$@{BASH_VERSION+set@}"}) that indicate
+features (such as @code{test $@{BASH_VERSION+y@}}) that indicate
 a reasonably fast and working implementation.

 @item @command{shift}
@@ -18172,7 +18172,10 @@ Limitations of Builtins
 Posix says that @samp{test "@var{string}"} succeeds if @var{string} is
 not null, but this usage is not portable to traditional platforms like
 Solaris 10 @command{/bin/sh}, which mishandle strings like @samp{!} and
-@samp{-n}.
+@samp{-n}.  However, it @emph{is} portable to test if a variable is set
+to a non-empty value, by using @samp{test $@{var+y@}}, since all known
+implementations properly distinguish between no arguments and a
+known-safe string of @samp{y}.

 Posix also says that @samp{test ! "@var{string}"},
 @samp{test -n "@var{string}"} and
diff --git a/lib/autoconf/c.m4 b/lib/autoconf/c.m4
index 4c87d21..0d1918f 100644
--- a/lib/autoconf/c.m4
+++ b/lib/autoconf/c.m4
@@ -502,7 +502,7 @@ AC_LANG_POP(C)dnl
 # versions of a library), tasteless as that idea is.
 # Don't consider -g to work if it generates warnings when plain compiles don't.
 m4_define([_AC_PROG_CC_G],
-[ac_test_CFLAGS=${CFLAGS+set}
+[ac_test_CFLAGS=${CFLAGS+y}
 ac_save_CFLAGS=$CFLAGS
 AC_CACHE_CHECK(whether $CC accepts -g, ac_cv_prog_cc_g,
   [ac_save_c_werror_flag=$ac_c_werror_flag
@@ -519,7 +519,7 @@ AC_CACHE_CHECK(whether $CC accepts -g, ac_cv_prog_cc_g,
 	 _AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
 	   [ac_cv_prog_cc_g=yes])])])
    ac_c_werror_flag=$ac_save_c_werror_flag])
-if test "$ac_test_CFLAGS" = set; then
+if test $ac_test_CFLAGS; then
   CFLAGS=$ac_save_CFLAGS
 elif test $ac_cv_prog_cc_g = yes; then
   if test "$GCC" = yes; then
@@ -743,7 +743,7 @@ AC_LANG_POP(C++)dnl
 # normal versions of a library), tasteless as that idea is.
 # Don't consider -g to work if it generates warnings when plain compiles don't.
 m4_define([_AC_PROG_CXX_G],
-[ac_test_CXXFLAGS=${CXXFLAGS+set}
+[ac_test_CXXFLAGS=${CXXFLAGS+y}
 ac_save_CXXFLAGS=$CXXFLAGS
 AC_CACHE_CHECK(whether $CXX accepts -g, ac_cv_prog_cxx_g,
   [ac_save_cxx_werror_flag=$ac_cxx_werror_flag
@@ -760,7 +760,7 @@ AC_CACHE_CHECK(whether $CXX accepts -g, ac_cv_prog_cxx_g,
 	 _AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
 	   [ac_cv_prog_cxx_g=yes])])])
    ac_cxx_werror_flag=$ac_save_cxx_werror_flag])
-if test "$ac_test_CXXFLAGS" = set; then
+if test $ac_test_CXXFLAGS; then
   CXXFLAGS=$ac_save_CXXFLAGS
 elif test $ac_cv_prog_cxx_g = yes; then
   if test "$GXX" = yes; then
@@ -913,7 +913,7 @@ AC_LANG_POP(Objective C)dnl
 # normal versions of a library), tasteless as that idea is.
 # Don't consider -g to work if it generates warnings when plain compiles don't.
 m4_define([_AC_PROG_OBJC_G],
-[ac_test_OBJCFLAGS=${OBJCFLAGS+set}
+[ac_test_OBJCFLAGS=${OBJCFLAGS+y}
 ac_save_OBJCFLAGS=$OBJCFLAGS
 AC_CACHE_CHECK(whether $OBJC accepts -g, ac_cv_prog_objc_g,
   [ac_save_objc_werror_flag=$ac_objc_werror_flag
@@ -930,7 +930,7 @@ AC_CACHE_CHECK(whether $OBJC accepts -g, ac_cv_prog_objc_g,
 	 _AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
 	   [ac_cv_prog_objc_g=yes])])])
    ac_objc_werror_flag=$ac_save_objc_werror_flag])
-if test "$ac_test_OBJCFLAGS" = set; then
+if test $ac_test_OBJCFLAGS; then
   OBJCFLAGS=$ac_save_OBJCFLAGS
 elif test $ac_cv_prog_objc_g = yes; then
   if test "$GOBJC" = yes; then
@@ -1052,7 +1052,7 @@ AC_LANG_POP(Objective C++)dnl
 # normal versions of a library), tasteless as that idea is.
 # Don't consider -g to work if it generates warnings when plain compiles don't.
 m4_define([_AC_PROG_OBJCXX_G],
-[ac_test_OBJCXXFLAGS=${OBJCXXFLAGS+set}
+[ac_test_OBJCXXFLAGS=${OBJCXXFLAGS+y}
 ac_save_OBJCXXFLAGS=$OBJCXXFLAGS
 AC_CACHE_CHECK(whether $OBJCXX accepts -g, ac_cv_prog_objcxx_g,
   [ac_save_objcxx_werror_flag=$ac_objcxx_werror_flag
@@ -1069,7 +1069,7 @@ AC_CACHE_CHECK(whether $OBJCXX accepts -g, ac_cv_prog_objcxx_g,
 	 _AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
 	   [ac_cv_prog_objcxx_g=yes])])])
    ac_objcxx_werror_flag=$ac_save_objcx_werror_flag])
-if test "$ac_test_OBJCXXFLAGS" = set; then
+if test $ac_test_OBJCXXFLAGS; then
   OBJCXXFLAGS=$ac_save_OBJCXXFLAGS
 elif test $ac_cv_prog_objcxx_g = yes; then
   if test "$GOBJCXX" = yes; then
diff --git a/lib/autoconf/fortran.m4 b/lib/autoconf/fortran.m4
index 7fd9191..fd3d5b1 100644
--- a/lib/autoconf/fortran.m4
+++ b/lib/autoconf/fortran.m4
@@ -398,7 +398,7 @@ AC_LANG_POP(Fortran)dnl
 # versions of a library), tasteless as that idea is.
 m4_define([_AC_PROG_FC_G],
 [_AC_FORTRAN_ASSERT()dnl
-ac_test_[]_AC_LANG_PREFIX[]FLAGS=${[]_AC_LANG_PREFIX[]FLAGS+set}
+ac_test_[]_AC_LANG_PREFIX[]FLAGS=${[]_AC_LANG_PREFIX[]FLAGS+y}
 ac_save_[]_AC_LANG_PREFIX[]FLAGS=$[]_AC_LANG_PREFIX[]FLAGS
 _AC_LANG_PREFIX[]FLAGS=
 AC_CACHE_CHECK(whether $[]_AC_FC[] accepts -g, ac_cv_prog_[]_AC_LANG_ABBREV[]_g,
@@ -407,7 +407,7 @@ _AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
 [ac_cv_prog_[]_AC_LANG_ABBREV[]_g=yes],
 [ac_cv_prog_[]_AC_LANG_ABBREV[]_g=no])
 ])
-if test "$ac_test_[]_AC_LANG_PREFIX[]FLAGS" = set; then
+if test $ac_test_[]_AC_LANG_PREFIX[]FLAGS; then
   _AC_LANG_PREFIX[]FLAGS=$ac_save_[]_AC_LANG_PREFIX[]FLAGS
 elif test $ac_cv_prog_[]_AC_LANG_ABBREV[]_g = yes; then
   if test "x$ac_cv_[]_AC_LANG_ABBREV[]_compiler_gnu" = xyes; then
diff --git a/lib/autoconf/general.m4 b/lib/autoconf/general.m4
index 2d1a291..49df536 100644
--- a/lib/autoconf/general.m4
+++ b/lib/autoconf/general.m4
@@ -1467,7 +1467,7 @@ _AC_ENABLE_IF_ACTION([$1], m4_translit([$2], [-+.], [___]), [$3], [$4])
 m4_define([_AC_ENABLE_IF_ACTION],
 [m4_append_uniq([_AC_USER_OPTS], [$1_$2], [
 ])dnl
-AS_IF([test "${$1_$2+set}" = set], [$1val=$$1_$2; $3], [$4])dnl
+AS_IF([test ${$1_$2+y}], [$1val=$$1_$2; $3], [$4])dnl
 ])

 # AC_ARG_ENABLE(FEATURE, HELP-STRING, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
@@ -2044,7 +2044,7 @@ _AC_CACHE_DUMP() |
      /^ac_cv_env_/b end
      t clear
      :clear
-     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
      t end
      s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
      :end'] >>confcache
diff --git a/lib/autoconf/lang.m4 b/lib/autoconf/lang.m4
index 2e30f50..80c395d 100644
--- a/lib/autoconf/lang.m4
+++ b/lib/autoconf/lang.m4
@@ -553,7 +553,7 @@ do
 	# certainly right.
 	break;;
     *.* )
-	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
 	then :; else
 	   ac_cv_exeext=`expr "$ac_file" : ['[^.]*\(\..*\)']`
 	fi
diff --git a/lib/autoconf/programs.m4 b/lib/autoconf/programs.m4
index ef35a79..1ed16cd 100644
--- a/lib/autoconf/programs.m4
+++ b/lib/autoconf/programs.m4
@@ -586,7 +586,7 @@ esac
 ])
 rm -rf conftest.one conftest.two conftest.dir
 ])dnl
-  if test "${ac_cv_path_install+set}" = set; then
+  if test ${ac_cv_path_install+y}; then
     INSTALL=$ac_cv_path_install
   else
     # As a last resort, use the slow shell script.  Don't cache a
@@ -680,7 +680,7 @@ if test -z "$MKDIR_P"; then
 	 done
        done])])
   test -d ./--version && rmdir ./--version
-  if test "${ac_cv_path_mkdir+set}" = set; then
+  if test ${ac_cv_path_mkdir+y}; then
     MKDIR_P="$ac_cv_path_mkdir -p"
   else
     # As a last resort, use the slow shell script.  Don't cache a
@@ -750,7 +750,7 @@ else
 fi])
 AC_SUBST([LEX_OUTPUT_ROOT], [$ac_cv_prog_lex_root])dnl

-if test -z "${LEXLIB+set}"; then
+if ${LEXLIB+false} :; then
   AC_CACHE_CHECK([lex library], [ac_cv_lib_lex], [
     ac_save_LIBS=$LIBS
     ac_cv_lib_lex='none needed'
diff --git a/lib/autoconf/status.m4 b/lib/autoconf/status.m4
index ef9d521..7bda371 100644
--- a/lib/autoconf/status.m4
+++ b/lib/autoconf/status.m4
@@ -1604,16 +1604,16 @@ AC_DEFUN([_AC_OUTPUT_MAIN_LOOP],
 # bizarre bug on SunOS 4.1.3.
 if $ac_need_defaults; then
 m4_ifdef([_AC_SEEN_CONFIG(FILES)],
-[  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+[  test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
 ])dnl
 m4_ifdef([_AC_SEEN_CONFIG(HEADERS)],
-[  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+[  test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers
 ])dnl
 m4_ifdef([_AC_SEEN_CONFIG(LINKS)],
-[  test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links
+[  test ${CONFIG_LINKS+y} || CONFIG_LINKS=$config_links
 ])dnl
 m4_ifdef([_AC_SEEN_CONFIG(COMMANDS)],
-[  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+[  test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands
 ])dnl
 fi

diff --git a/lib/autotest/general.m4 b/lib/autotest/general.m4
index e70e326..c809409 100644
--- a/lib/autotest/general.m4
+++ b/lib/autotest/general.m4
@@ -363,7 +363,7 @@ at_fn_create_debugging_script ()
 {
   {
     echo "#! /bin/sh" &&
-    echo 'test "${ZSH_VERSION+set}" = set dnl
+    echo 'test ${ZSH_VERSION+y} dnl
 && alias -g '\''${1+"$[@]"}'\''='\''"$[@]"'\''' &&
     AS_ECHO(["cd '$at_dir'"]) &&
     AS_ECHO(["exec \${CONFIG_SHELL-$SHELL} \"$at_myself\" -v -d ]dnl
@@ -1367,7 +1367,7 @@ dnl Unfortunately, ksh93 fork-bombs when we send TSTP, so send STOP
 dnl if this might be ksh (STOP prevents possible TSTP handlers inside
 dnl AT_CHECKs from running).  Then stop ourselves.
 	  at_sig=TSTP
-	  test "${TMOUT+set}" = set && at_sig=STOP
+	  test ${TMOUT+y} && at_sig=STOP
 	  kill -$at_sig $at_pids 2>/dev/null
 	fi
 	kill -STOP $$
diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index 603466f..5949e0a 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -100,7 +100,7 @@ _$0
 # This is the part of AS_BOURNE_COMPATIBLE which has to be repeated inside
 # each instance.
 m4_define([_AS_BOURNE_COMPATIBLE],
-[AS_IF([test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1],
+[AS_IF([test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1],
  [emulate sh
   NULLCMD=:
   [#] Pre-4.2 versions of Zsh do word splitting on ${1+"$[@]"}, which
@@ -252,7 +252,7 @@ dnl Unfortunately, $as_me isn't available here.
     AS_IF([test x$as_have_required = xno],
       [AS_ECHO(["$[]0: This script requires a shell more modern than all"])
   AS_ECHO(["$[]0: the shells that I found on your system."])
-  if test x${ZSH_VERSION+set} = xset ; then
+  if test ${ZSH_VERSION+y} ; then
     AS_ECHO(["$[]0: In particular, zsh $ZSH_VERSION has bugs and should"])
     AS_ECHO(["$[]0: be upgraded to zsh 4.3.4 or later."])
   else
@@ -488,7 +488,7 @@ fi
 # suppresses any "Segmentation fault" message there.  '((' could
 # trigger a bug in pdksh 5.2.14.
 for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
+do eval test \${$as_var+y} \
   && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
 done
 PS1='$ '
@@ -1272,7 +1272,7 @@ fi
 # Compute the path separator.
 m4_defun([_AS_PATH_SEPARATOR_PREPARE],
 [# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
   PATH_SEPARATOR=:
   (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
     (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
@@ -2062,9 +2062,9 @@ m4_define([AS_VAR_SET_IF],
 # is set.  Polymorphic.
 m4_define([AS_VAR_TEST_SET],
 [AS_LITERAL_WORD_IF([$1],
-  [${$1+:} false],
-  [{ as_var=$1; eval \${$as_var+:} false; }],
-  [eval \${$1+:} false])])
+  [test ${$1+y}],
+  [{ as_var=$1; eval test \${$as_var+y}; }],
+  [eval test \${$1+y}])])


 ## -------------------- ##
diff --git a/tests/base.at b/tests/base.at
index 63bd36e..cbc5a59 100644
--- a/tests/base.at
+++ b/tests/base.at
@@ -342,7 +342,7 @@ my_cv_variable=true
 AC_MSG_RESULT([$my_cv_variable])

 # Ensure that the result is available at this point.
-if test ${my_cv_variable+set} != set; then
+if ${my_cv_variable+false} :; then
   AC_MSG_ERROR([AC@&@&t@t@_CACHE_VAL did not ensure that the cache variable was set])
 fi

diff --git a/tests/m4sh.at b/tests/m4sh.at
index df39ae7..32de374 100644
--- a/tests/m4sh.at
+++ b/tests/m4sh.at
@@ -214,7 +214,7 @@ AT_KEYWORDS([m4sh])
 # unsetting LINENO to compare its result when (i) LINENO is supported
 # and when (ii) it is not.
 # So just skip if the shell is ZSH.
-AT_CHECK([test -n "${ZSH_VERSION+set}" && exit 77], ignore)
+AT_CHECK([test ${ZSH_VERSION+y} && exit 77], ignore)

 # AT_DATA_LINENO(FILE-NAME,
 #                UNSET-LINENO = true | false, COUNTER, COUNTER-RE)
@@ -297,7 +297,7 @@ test $as_lineno = 9999 || AS_ERROR([bad as_lineno at depth 2])
 AS_LINENO_POP
 test $as_lineno = 9999 || AS_ERROR([bad as_lineno at depth 1])
 AS_LINENO_POP
-test x${as_lineno+set} = xset && AS_ERROR([as_lineno set at depth 0])
+test ${as_lineno+y} && AS_ERROR([as_lineno set at depth 0])

 AS_EXIT([0])
 ]])
-- 
2.1.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.