2010-08-25 Eric Blake <eblake@redhat.com>
+ docs: mention cost of globbing during variable expansion
+ * doc/autoconf.texi (Shell Substitutions) <${var=literal}>:
+ Recommend quoting substitutions that might trigger globbing.
+ (Limitations of Builtins) <:>: Likewise.
+ * bin/autoconf.as: Follow our own advice.
+ * lib/autoconf/functions.m4 (AC_FUNC_SELECT_ARGTYPES): Likewise.
+ * lib/autoconf/general.m4 (_AC_INIT_PARSE_ARGS): Likewise.
+ * lib/autoconf/status.m4 (AC_OUTPUT): Likewise.
+ * lib/autotest/general.m4 (_AT_FINISH): Likewise.
+ * lib/m4sugar/m4sh.m4 (AS_TMPDIR): Likewise.
+ * tests/autotest.at (parallel autotest and signal handling):
+ Likewise.
+ * tests/c.at (AC_OPENMP and C, AC_OPENMP and C++): Likewise.
+ * tests/foreign.at (shtool): Likewise.
+ * tests/fortran.at: Likewise.
+ * tests/tools.at (autom4te preselections): Likewise.
+ * tests/torture.at (VPATH): Likewise.
+
m4sh: fix some namespace safety issues
* lib/m4sugar/m4sh.m4 (_AS_SHELL_SANITIZE): Avoid problems if
as_myself is inherited from environment.
# restore font-lock: '
# Variables.
-: ${AUTOM4TE='@bindir@/@autom4te-name@'}
+: "${AUTOM4TE='@bindir@/@autom4te-name@'}"
autom4te_options=
outfile=
verbose=false
@item $@{@var{var}=@var{literal}@}
@cindex $@{@var{var}=@var{literal}@}
-Be sure to quote:
+When using @samp{$@{@var{var}=@var{value}@}} to assign a default value
+to @var{var}, remember that even though the assignment to @var{var} does
+not undergo file name expansion, the result of the variable expansion
+does. In particular, when using @command{:} followed by unquoted
+variable expansion for the side effect of setting a default value, if
+either @samp{value} or the prior contents of @samp{$var} contains
+globbing characters, the shell has to spend time performing file name
+expansion and field splitting even though those results will not be
+used. Therefore, it is a good idea to use double quotes when performing
+default initialization.
@example
-: $@{var='Some words'@}
+$ time bash -c ': "$@{a=/usr/bin/*@}"; echo "$a"'
+/usr/bin/*
+
+real 0m0.005s
+user 0m0.002s
+sys 0m0.003s
+$ time bash -c ': $@{a=/usr/bin/*@}; echo "$a"'
+/usr/bin/*
+
+real 0m0.039s
+user 0m0.026s
+sys 0m0.009s
+@end example
+
+Use quotes if @var{literal} contains more than one shell word:
+
+@example
+: "$@{var='Some words'@}"
@end example
@noindent
@example
default="yu,yaa"
-: $@{var="$default"@}
+: "$@{var="$default"@}"
@end example
@noindent
@example
default="a b c"
-: $@{list="$default"@}
+: "$@{list="$default"@}"
for c in $list; do
echo $c
done
brace, use:
@example
-: $@{var='my literal'@}
+: "$@{var='my literal'@}"
@end example
@item
(i.e., it's not a list), then use:
@example
-: $@{var="$default"@}
+: "$@{var="$default"@}"
@end example
@item
for @command{true}.
@end quotation
+Remember that even though @samp{:} ignores its arguments, it still takes
+time to compute those arguments. It is a good idea to use double quotes
+around any arguments to @samp{:} to avoid time spent in field splitting
+and file name expansion.
+
@anchor{unset}
@item @command{unset}
# Create a temporary directory $tmp in $TMPDIR (default /tmp).
# Use mktemp if possible; otherwise fall back on mkdir,
# with $RANDOM to make collisions less likely.
-: $@{TMPDIR=/tmp@}
+: "$@{TMPDIR=/tmp@}"
@{
tmp=`
(umask 077 && mktemp -d "$TMPDIR/fooXXXXXX") 2>/dev/null
done
done
# Provide a safe default value.
-: ${ac_cv_func_select_args='int,int *,struct timeval *'}
+: "${ac_cv_func_select_args='int,int *,struct timeval *'}"
])
ac_save_IFS=$IFS; IFS=','
set dummy `echo "$ac_cv_func_select_args" | sed 's/\*/\*/g'`
AC_MSG_WARN([you should use --build, --host, --target])
expr "x$ac_option" : "[.*[^-._$as_cr_alnum]]" >/dev/null &&
AC_MSG_WARN([invalid host type: $ac_option])
- : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
esac
dnl Commands to run before creating config.status.
AC_OUTPUT_COMMANDS_PRE()dnl
-: ${CONFIG_STATUS=./config.status}
+: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
done
# Autoconf <=2.59b set at_top_builddir instead of at_top_build_prefix:
-: ${at_top_build_prefix=$at_top_builddir}
+: "${at_top_build_prefix=$at_top_builddir}"
# Perform any assignments requested during argument parsing.
eval "$at_debug_args"
# which name is inspired by PREFIX (should be 2-4 chars max).
m4_define([AS_TMPDIR],
[# Create a (secure) tmp directory for tmp files.
-m4_if([$2], [], [: ${TMPDIR=/tmp}])
+m4_if([$2], [], [: "${TMPDIR=/tmp}"])
{
as_tmp=`(umask 077 && mktemp -d "m4_default([$2],
[$TMPDIR])/$1XXXXXX") 2>/dev/null` &&
# AT_CHECK([[grep '[iI]nterrupt[ ]' stderr]], [1])
# Ditto with `make' in the loop.
- : ${MAKE=make}
+ : "${MAKE=make}"
unset MAKEFLAGS
# Need to eliminate outer TESTSUITEFLAGS here.
# Need to normalize exit status here: some make implementations
}
]])
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([env ACLOCAL=true autoreconf -vi], [], [ignore], [ignore])
AT_CHECK([./configure $configure_options], [], [ignore], [ignore])
AT_CHECK([$MAKE], [], [ignore], [ignore])
}
]])
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([env ACLOCAL=true autoreconf -vi], [], [ignore], [ignore])
AT_CHECK([./configure $configure_options], [], [ignore], [ignore])
AT_CHECK([$MAKE], [], [ignore], [ignore])
: >file1
: >file2
chmod +x file1
-: ${MAKE=make}
+: "${MAKE=make}"
mkdir build-aux inst
instdir=`pwd`/inst
AT_CHECK_AUTOCONF
end
]])
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([env ACLOCAL=true autoreconf -vi], [], [ignore], [ignore])
AT_CHECK_CONFIGURE
AT_CHECK([$MAKE], [], [ignore], [ignore])
end
]])
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([env ACLOCAL=true autoreconf -vi], [], [ignore], [ignore])
AT_CHECK_CONFIGURE
AT_CHECK([$MAKE], [], [ignore], [ignore])
AT_CHECK_AUTOCONF
AT_CHECK_AUTOHEADER
AT_CHECK_CONFIGURE
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([$MAKE], [], [ignore], [ignore])
dnl AT_CHECK([./cprogram])
AT_CHECK_AUTOCONF
AT_CHECK_AUTOHEADER
AT_CHECK_CONFIGURE
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([$MAKE], [], [ignore], [ignore])
dnl AT_CHECK([./cprogram])
AT_CHECK_AUTOCONF
AT_CHECK_AUTOHEADER
AT_CHECK_CONFIGURE
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([$MAKE], [], [ignore], [ignore])
dnl AT_CHECK([./cprogram], [], [output from C main
dnl some output from Fortran sources
AT_CHECK_AUTOCONF
AT_CHECK_AUTOHEADER
AT_CHECK_CONFIGURE
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([$MAKE], [], [ignore], [ignore])
dnl AT_CHECK([./cprogram], [], [output from C main
dnl some output from Fortran sources
AT_CHECK_AUTOCONF
AT_CHECK_CONFIGURE
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([$MAKE], [], [ignore], [ignore])
dnl AT_CHECK([./cprogram])
AT_CHECK_AUTOCONF
AT_CHECK_CONFIGURE
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([$MAKE], [], [ignore], [ignore])
dnl AT_CHECK([./cprogram])
AT_CLEANUP
AT_CHECK_AUTOCONF
AT_CHECK_CONFIGURE
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([$MAKE], [], [ignore], [ignore])
AT_CLEANUP
AT_CHECK_AUTOCONF
AT_CHECK_CONFIGURE
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([$MAKE], [], [ignore], [ignore])
dnl AT_CHECK([./prog])
AT_CHECK_AUTOCONF
AT_CHECK_CONFIGURE
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([$MAKE], [], [ignore], [ignore])
dnl AT_CHECK([./prog])
AT_CHECK_AUTOCONF
AT_CHECK_CONFIGURE
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([$MAKE], [], [ignore], [ignore])
dnl AT_CHECK([./prog])
AT_CHECK_AUTOCONF
AT_CHECK_CONFIGURE
-: ${MAKE=make}
+: "${MAKE=make}"
AT_CHECK([$MAKE], [], [ignore], [ignore])
dnl AT_CHECK([./prog])
AT_CHECK_AUTOCONF
AT_CHECK_CONFIGURE
- : ${MAKE=make}
+ : "${MAKE=make}"
AT_CHECK([$MAKE], [], [ignore], [ignore])
dnl AT_CHECK([./prog])
AT_CHECK([$MAKE clean], [], [ignore], [ignore])
# -----------------------------
AT_SETUP([autom4te preselections])
-: ${sleep='sleep 1'} # Command to force different time stamps.
+: "${sleep='sleep 1'}" # Command to force different time stamps.
# If this test should run on FAT file systems and older w32,
# then setting $sleep correctly needs to be revisited.
AT_CHECK_AUTOCONF
-: ${MAKE=make}
+: "${MAKE=make}"
# In place.
AT_CHECK([./configure $configure_options], [], [ignore])