[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: how to do "$@"?
From: |
Paul Eggert |
Subject: |
Re: how to do "$@"? |
Date: |
Fri, 19 Apr 2002 12:18:46 -0700 (PDT) |
> From: Akim Demaille <address@hidden>
> Date: 18 Apr 2002 14:33:03 +0200
>
> This is the kind of obfuscation I'd like to avoid.
OK, I installed the following patch instead. I think it reflects all
your comments. It uses the obfuscated code only in places where the
ZSH_VERSION fixes don't apply.
In this patch I couldn't resist tuning the Zsh workaround slightly,
as follows:
${ZSH_VERSION-:} alias -g '${1+"$@"}'='"$@"'
(The code is total gibberish to the uninitiated anyway, so we might as
well make it short and sweet.)
2002-04-19 Paul Eggert <address@hidden>
Fix some bugs when using "$@" when there might be zero positional
arguments in cases where this matters.
* bin/autoconf.as: Rewrite so that the problem does not come up.
* lib/autoconf/programs.m4 (AC_CHECK_PROG): Likewise.
* lib/autoconf/status.m4 (AC_OUTPUT): Likewise.
* lib/autotest/general.m4 (AT_INIT): Likewise.
* bin/autoheader.in: Use 'case' statement to work around problem.
* bin/auto4mte.in: Likewise.
* bin/autoreconf.in: Likewise.
* bin/autoscan.in: Likewise.
* bin/autoupdate.in: Likewise.
* bin/ifnames.in: Likewise.
* doc/autoconf.texi (Shell Substitutions): Document the problem.
* lib/autotest/general.m4 (AT_INIT):
Use Zsh alias to work around problem.
* tests/atgeneral.m4 (AT_INIT): Likewise.
* tests/c.at: We can't have zero arguments, so remove workaround
that is not portable to Zsh.
Index: bin/autoconf.as
===================================================================
RCS file: /cvsroot/autoconf/autoconf/bin/autoconf.as,v
retrieving revision 1.1
diff -p -u -r1.1 autoconf.as
--- bin/autoconf.as 10 Apr 2002 15:58:19 -0000 1.1
+++ bin/autoconf.as 19 Apr 2002 18:44:36 -0000
@@ -182,10 +182,7 @@ esac
# Unless specified, the output is stdout.
test -z "$outfile" && outfile=-
-# Running autom4te.
-run_autom4te="$AUTOM4TE --language=autoconf --output=$outfile"
-# Autom4te expansion.
-eval set dummy "$traces"
-shift
-$verbose "$me: running $run_autom4te "${1+"$@"}" $infile" >&2
-exec $run_autom4te ${1+"$@"} $infile
+# Run autom4te with expansion.
+eval set \$AUTOM4TE --language=autoconf --output=\$outfile "$traces" \$infile
+$verbose "$me: running $*" >&2
+exec "$@"
Index: bin/autoheader.in
===================================================================
RCS file: /cvsroot/autoconf/autoconf/bin/autoheader.in,v
retrieving revision 1.115
diff -p -u -r1.115 autoheader.in
--- bin/autoheader.in 8 Mar 2002 11:46:31 -0000 1.115
+++ bin/autoheader.in 19 Apr 2002 18:44:36 -0000
@@ -2,11 +2,11 @@
# -*- Perl -*-
# @configure_input@
-eval 'exec @PERL@ -S $0 ${1+"$@"}'
+eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
if 0;
# autoheader -- create `config.h.in' from `configure.ac'
-# Copyright 1992, 1993, 1994, 1996, 1998, 1999, 2000, 2001
+# Copyright (C) 1992, 1993, 1994, 1996, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
Index: bin/autom4te.in
===================================================================
RCS file: /cvsroot/autoconf/autoconf/bin/autom4te.in,v
retrieving revision 1.59
diff -p -u -r1.59 autom4te.in
--- bin/autom4te.in 8 Mar 2002 12:01:23 -0000 1.59
+++ bin/autom4te.in 19 Apr 2002 18:44:36 -0000
@@ -2,11 +2,11 @@
# -*- perl -*-
# @configure_input@
-eval 'exec @PERL@ -S $0 ${1+"$@"}'
+eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
if 0;
# autom4te - Wrapper around M4 libraries.
-# Copyright 2001, 2002 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2002 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Index: bin/autoreconf.in
===================================================================
RCS file: /cvsroot/autoconf/autoconf/bin/autoreconf.in,v
retrieving revision 1.92
diff -p -u -r1.92 autoreconf.in
--- bin/autoreconf.in 5 Apr 2002 09:42:49 -0000 1.92
+++ bin/autoreconf.in 19 Apr 2002 18:44:37 -0000
@@ -2,11 +2,11 @@
# -*- perl -*-
# @configure_input@
-eval 'exec @PERL@ -S $0 ${1+"$@"}'
+eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
if 0;
# autoreconf - install the GNU Build System in a directory tree
-# Copyright 1994, 1999, 2000, 2001 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Index: bin/autoscan.in
===================================================================
RCS file: /cvsroot/autoconf/autoconf/bin/autoscan.in,v
retrieving revision 1.76
diff -p -u -r1.76 autoscan.in
--- bin/autoscan.in 19 Mar 2002 15:25:26 -0000 1.76
+++ bin/autoscan.in 19 Apr 2002 18:44:37 -0000
@@ -1,7 +1,7 @@
#! @PERL@ -w
# -*- perl -*-
# autoscan - Create configure.scan (a preliminary configure.ac) for a package.
-# Copyright 1994, 1999, 2000, 2001 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -20,7 +20,7 @@
# Written by David MacKenzie <address@hidden>.
-eval 'exec @PERL@ -S $0 ${1+"$@"}'
+eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
if 0;
BEGIN
Index: bin/autoupdate.in
===================================================================
RCS file: /cvsroot/autoconf/autoconf/bin/autoupdate.in,v
retrieving revision 1.32
diff -p -u -r1.32 autoupdate.in
--- bin/autoupdate.in 19 Apr 2002 08:30:39 -0000 1.32
+++ bin/autoupdate.in 19 Apr 2002 18:44:37 -0000
@@ -1,7 +1,7 @@
#! @PERL@ -w
# -*- perl -*-
# autoupdate - modernize an Autoconf file.
-# Copyright 1994, 1999, 2000, 2001 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
# Originally written by David MacKenzie <address@hidden>.
# Rewritten by Akim Demaille <address@hidden>.
-eval 'exec @PERL@ -S $0 ${1+"$@"}'
+eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
if 0;
BEGIN
Index: bin/ifnames.in
===================================================================
RCS file: /cvsroot/autoconf/autoconf/bin/ifnames.in,v
retrieving revision 1.25
diff -p -u -r1.25 ifnames.in
--- bin/ifnames.in 8 Mar 2002 11:46:31 -0000 1.25
+++ bin/ifnames.in 19 Apr 2002 18:44:37 -0000
@@ -2,11 +2,13 @@
# -*- perl -*-
# @configure_input@
-eval 'exec @PERL@ -S $0 ${1+"$@"}'
+eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
if 0;
# ifnames - print the identifiers used in C preprocessor conditionals
-# Copyright 1994, 1995, 1999, 2000, 2001 Free Software Foundation, Inc.
+
+# Copyright (C) 1994, 1995, 1999, 2000, 2001, 2002 Free Software
+# Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Index: doc/autoconf.texi
===================================================================
RCS file: /cvsroot/autoconf/autoconf/doc/autoconf.texi,v
retrieving revision 1.612
diff -p -u -r1.612 autoconf.texi
--- doc/autoconf.texi 19 Apr 2002 15:23:25 -0000 1.612
+++ doc/autoconf.texi 19 Apr 2002 18:44:41 -0000
@@ -8457,13 +8457,16 @@ strings inside double-quoted backquoted
@item $@@
@cindex @samp{"$@@"}
One of the most famous shell-portability issues is related to
address@hidden"$@@"}: when there are no positional arguments, it is supposed to
-be equivalent to nothing. But some shells, for instance under Digital
-Unix 4.0 and 5.0, will then replace it with an empty argument. To be
-portable, use @address@hidden"$@@"@}}.
-
-But that's not the end of the story. Zsh (3.x and 4.x), when emulating
-the Bourne shell, does perform word splitting on @address@hidden"$@@"@}}...
address@hidden"$@@"}. When there are no positional arguments, @sc{posix} says
+that @samp{"$@@"} is supposed to be equivalent to nothing, but the
+original Unix Version 7 Bourne shell treated it as equivalent to
address@hidden""} instead, and this behavior survives in later implementations
+like Digital Unix 5.0.
+
+The traditional way to work around this portability problem is to use
address@hidden@{1+"$@@"@}}. Unfortunately this method does not work with
+Zsh (3.x and 4.x), which is used on Mac OS X. When emulating
+the Bourne shell, Zsh performs word splitting on @address@hidden"$@@"@}}:
@example
zsh $ @kbd{emulate sh}
@@ -8477,19 +8480,31 @@ World
@end example
@noindent
-It is not clear whether this is a violation of the Bourne shell
-standard, nevertheless, in this regard Zsh is different from all the
-other shells. Of course Zsh handles @samp{"$@@"} properly, but we can't
-use it portably...
-
-Fortunately, there is a workaround which relies on Zsh's ``global
-aliases'': let it convert @address@hidden"$@@"@}} into @samp{"$@@"} by
-itself:
+Zsh handles plain @samp{"$@@"} properly, but we can't use plain
address@hidden"$@@"} because of the portability problems mentioned above.
+One workaround relies on Zsh's ``global aliases'' to convert
address@hidden@{1+"$@@"@}} into @samp{"$@@"} by itself:
+
address@hidden
address@hidden:@} alias -g 'address@hidden"$@@"@}'='"$@@"'
address@hidden example
+
+A more conservative workaround is to avoid @samp{"$@@"} if it is
+possible that there may be no positional arguments. For example,
+instead of:
@example
-test "address@hidden@}" = set && alias -g 'address@hidden"$@@"@}'='"$@@"'
+cat conftest.c "$@@"
@end example
+you can use this instead:
+
address@hidden
+case $# in
+0) cat conftest.c;;
+*) cat conftest.c "$@@";;
+esac
address@hidden example
@item address@hidden@var{var}:address@hidden@}
@c Info cannot handle `:' in index entries.
Index: lib/autoconf/programs.m4
===================================================================
RCS file: /cvsroot/autoconf/autoconf/lib/autoconf/programs.m4,v
retrieving revision 1.9
diff -p -u -r1.9 programs.m4
--- lib/autoconf/programs.m4 2 Mar 2002 15:19:48 -0000 1.9
+++ lib/autoconf/programs.m4 19 Apr 2002 18:44:41 -0000
@@ -1,6 +1,6 @@
# This file is part of Autoconf. -*- Autoconf -*-
# Checking for programs.
-# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
@@ -92,9 +92,7 @@ m4_ifvaln([$6],
# However, it has the same basename, so the bogon will be chosen
# first if we set $1 to just the basename; use the full file name.
shift
- set dummy "$as_dir/$ac_word" ${1+"address@hidden"}
- shift
- ac_cv_prog_$1="address@hidden"
+ ac_cv_prog_$1="$as_dir/$ac_word${1+' 'address@hidden"
m4_if([$2], [$4],
[ else
# Default is a loser.
Index: lib/autoconf/status.m4
===================================================================
RCS file: /cvsroot/autoconf/autoconf/lib/autoconf/status.m4,v
retrieving revision 1.22
diff -p -u -r1.22 status.m4
--- lib/autoconf/status.m4 10 Apr 2002 15:58:20 -0000 1.22
+++ lib/autoconf/status.m4 19 Apr 2002 18:44:41 -0000
@@ -1382,17 +1382,20 @@ do
--*=*)
ac_option=`expr "x$[1]" : 'x\([[^=]]*\)='`
ac_optarg=`expr "x$[1]" : 'x[[^=]]*=\(.*\)'`
- shift
- set dummy "$ac_option" "$ac_optarg" ${1+"address@hidden"}
- shift
+ ac_shift=:
+ ;;
+ -*)
+ ac_option=$[1]
+ ac_optarg=$[2]
+ ac_shift=shift
;;
- -*);;
*) # This is not an option, so the user has probably given explicit
# arguments.
+ ac_option=$[1]
ac_need_defaults=false;;
esac
- case $[1] in
+ case $ac_option in
# Handling of the options.
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
@@ -1412,12 +1415,12 @@ Try `$[0] --help' for more information.]
--debug | --d* | -d )
debug=: ;;
--file | --fil | --fi | --f )
- shift
- CONFIG_FILES="$CONFIG_FILES $[1]"
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
ac_need_defaults=false;;
--header | --heade | --head | --hea )
- shift
- CONFIG_HEADERS="$CONFIG_HEADERS $[1]"
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
ac_need_defaults=false;;
# This is an error.
Index: lib/autotest/general.m4
===================================================================
RCS file: /cvsroot/autoconf/autoconf/lib/autotest/general.m4,v
retrieving revision 1.130
diff -p -u -r1.130 general.m4
--- lib/autotest/general.m4 10 Apr 2002 15:58:20 -0000 1.130
+++ lib/autotest/general.m4 19 Apr 2002 18:44:42 -0000
@@ -1,6 +1,6 @@
# This file is part of Autoconf. -*- Autoconf -*-
# M4 macros used in building test suites.
-# Copyright 2000, 2001 Free Software Foundation, Inc.
+# Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -101,7 +101,7 @@ AS_PREPARE
SHELL=${CONFIG_SHELL-/bin/sh}
# How were we run?
-at_cli_args=${1+"address@hidden"}
+at_cli_args="address@hidden"
# Load the config file.
for at_file in atconfig atlocal
@@ -569,6 +569,7 @@ _ATEOF
# Create the debugging script.
{
echo "#! /bin/sh"
+ echo '${ZSH_VERSION-:} alias -g '\''${1+"$@"}'\''='\''"$@"'\'''
echo "cd $at_dir"
echo 'exec ${CONFIG_SHELL-'"$SHELL"'}' "$[0]" \
'-v -d' "$at_debug_args" "$at_group" '${1+"address@hidden"}'
Index: tests/atgeneral.m4
===================================================================
RCS file: /cvsroot/autoconf/autoconf/tests/atgeneral.m4,v
retrieving revision 1.70
diff -p -u -r1.70 atgeneral.m4
--- tests/atgeneral.m4 25 Nov 2001 15:13:04 -0000 1.70
+++ tests/atgeneral.m4 19 Apr 2002 18:44:42 -0000
@@ -1,6 +1,6 @@
include(m4sh.m4) -*- Autoconf -*-
# M4 macros used in building test suites.
-# Copyright 2000, 2001 Free Software Foundation, Inc.
+# Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -318,6 +318,7 @@ elif test $at_debug = false; then
for at_group in $at_fail_list; do
echo $at_n " $at_group$at_c"
( echo "#! /bin/sh"
+ echo '${ZSH_VERSION-:} alias -g '\''${1+"$@"}'\''='\''"$@"'\'''
echo 'exec ${CONFIG_SHELL-'"$SHELL"'} '"$[0]"' -v -d '"$at_group"'
${1+"address@hidden"}'
echo 'exit 1'
) >debug-$at_group.sh
Index: tests/c.at
===================================================================
RCS file: /cvsroot/autoconf/autoconf/tests/c.at,v
retrieving revision 1.1
diff -p -u -r1.1 c.at
--- tests/c.at 27 Sep 2001 13:28:15 -0000 1.1
+++ tests/c.at 19 Apr 2002 18:44:42 -0000
@@ -2,7 +2,7 @@
AT_BANNER([C low level compiling/preprocessing macros.])
-# Copyright 2000, 2001 Free Software Foundation, Inc.
+# Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -113,7 +113,7 @@ AT_SETUP([AC_PROG_CPP with warnings])
AT_DATA([mycpp],
[[#! /bin/sh
echo noise >&2
-exec ${1+"$@"}
+exec "$@"
]])
chmod +x mycpp
@@ -146,7 +146,7 @@ AT_CHECK([/lib/cpp </dev/null || exit 77
# A cpp which exit status is meaningless.
AT_DATA([mycpp],
[[#! /bin/sh
-/lib/cpp ${1+"$@"}
+/lib/cpp "$@"
exit 0
]])