autoconf-patches
[Top][All Lists]
Advanced

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

Re: how to do "$@"?


From: Akim Demaille
Subject: Re: how to do "$@"?
Date: 18 Apr 2002 14:33:03 +0200
User-agent: Gnus/5.0808 (Gnus v5.8.8) XEmacs/21.4 (Common Lisp)

| > Date: Wed, 17 Apr 2002 11:41:25 -0600 (MDT)
| > From: "Nelson H. F. Beebe" <address@hidden>
| >
| > The problem seems to arise from manipulations of "$@" that cause
| > quoting of arguments containing blanks to be lost.
| 
| I think the main problem is dealing with the case where there are no
| positional arguments.  In that case, the Unix Version 7 shell treats
| "$@" like "", whereas POSIX requires that it should treat "$@" as if
| it were absent.  

Aah!  So that's finally the bottom line!

| For example:
|   set x
|   shift
|   cat "$@" /dev/null
| 
| In Unix Version 7, this fails and outputs something like this:
| 
|   cat: : No such file or directory
| 
| whereas in a POSIX shell, it outputs nothing.
| 
| > I suspect that most scripts only require the simpler use, and thus,
| > that "$@" should be preferred over the ${1+"$@"} form
| 
| But this won't work on older versions of Digital Unix.
| 
| How about the following (untested) patch instead?  It avoids the
| problem entirely, by removing all instances of "$@" in cases where
| there might be zero positional arguments.

I think it is a good thing to offer the choice to the users: the
documentation should show the two possibilities (using ${1+"$@"} and
having zsh do the right thing), or completely work around using "$@"
when $#=0.  The problem with the latter is that is much less `local'
than a plain ${1+"$@"}.  Although ugly, this solution, at least, had
the pleasant property of being quite discrete (no if/fi wrapping
needed etc.).

| 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   17 Apr 2002 21:47:49 -0000
| @@ -185,7 +185,7 @@ test -z "$outfile" && outfile=-
|  # Running autom4te.
|  run_autom4te="$AUTOM4TE --language=autoconf --output=$outfile"
|  # Autom4te expansion.
| -eval set dummy "$traces"
| +eval set dummy "$traces" \$infile
|  shift
| -$verbose "$me: running $run_autom4te "${1+"$@"}" $infile" >&2
| -exec $run_autom4te ${1+"$@"} $infile
| +$verbose "$me: running $run_autom4te $*" >&2
| +exec $run_autom4te "$@"

Err, this is not correct: infile might be empty, when using autoconf
in a pipe (hm, which seems to be broken now BTW).




| 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 17 Apr 2002 21:47:49 -0000
| @@ -2,7 +2,7 @@
|  # -*- 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'
| 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   17 Apr 2002 21:47:49 -0000
| @@ -2,7 +2,7 @@
|  # -*- 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.
| 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 17 Apr 2002 21:47:50 -0000
| @@ -2,7 +2,7 @@
|  # -*- 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
| 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   17 Apr 2002 21:47:50 -0000
| @@ -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.31
| diff -p -u -r1.31 autoupdate.in
| --- bin/autoupdate.in 8 Mar 2002 11:46:31 -0000       1.31
| +++ bin/autoupdate.in 17 Apr 2002 21:47:50 -0000
| @@ -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    17 Apr 2002 21:47:50 -0000
| @@ -2,7 +2,7 @@
|  # -*- 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

All these seem fine to me.





| Index: config/missing
| ===================================================================
| RCS file: /cvsroot/autoconf/autoconf/config/missing,v
| retrieving revision 1.6
| diff -p -u -r1.6 missing
| --- config/missing    24 Jan 2002 17:42:05 -0000      1.6
| +++ config/missing    17 Apr 2002 21:47:50 -0000
| @@ -293,23 +293,23 @@ WARNING: \`$1' is missing on your system
|      # Look for gnutar/gtar before invocation to avoid ugly error
|      # messages.
|      if (gnutar --version > /dev/null 2>&1); then
| -       gnutar ${1+"$@"} && exit 0
| +       gnutar "$@" && exit 0
|      fi
|      if (gtar --version > /dev/null 2>&1); then
| -       gtar ${1+"$@"} && exit 0
| +       gtar "$@" && exit 0
|      fi
|      firstarg="$1"
|      if shift; then
|       case "$firstarg" in
|       *o*)
|           firstarg=`echo "$firstarg" | sed s/o//`
| -         tar "$firstarg" ${1+"$@"} && exit 0
| +         tar "$firstarg" "$@" && exit 0
|           ;;
|       esac
|       case "$firstarg" in
|       *h*)
|           firstarg=`echo "$firstarg" | sed s/h//`
| -         tar "$firstarg" ${1+"$@"} && exit 0
| +         tar "$firstarg" "$@" && exit 0
|           ;;
|       esac
|      fi

missing belongs to Automake.



| Index: doc/autoconf.texi
| ===================================================================
| RCS file: /cvsroot/autoconf/autoconf/doc/autoconf.texi,v
| retrieving revision 1.610
| diff -p -u -r1.610 autoconf.texi
| --- doc/autoconf.texi 11 Apr 2002 10:24:22 -0000      1.610
| +++ doc/autoconf.texi 17 Apr 2002 21:47:54 -0000
| @@ -8458,13 +8458,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 it is supposed to be equivalent to nothing.  But the original
| +Unix Version 7 Bourne shell treated it as equivalent to @samp{""}
| +instead, and this behavior survives in some more modern
| +implementations, for instance under 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}
| @@ -8478,19 +8481,25 @@ 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.
| +
| +The most portable workaround is to avoid @samp{"$@@"} if it is possible
| +that there may be no positional arguments.  For example, instead of:
|  
|  @example
| -test -n "address@hidden@}" = set && alias -g 'address@hidden"$@@"@}'='"$@@"'
| +# Not portable if there are no positional arguments.
| +cat conftest.c "$@@"
|  @end example
|  
| +you should 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.

I would really prefer that we preserve the choice.  Personally, I much
prefer using ${1+"$@"} for the reasons I gave above.




| 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  17 Apr 2002 21:47:54 -0000
| @@ -92,7 +92,10 @@ 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"}
| +    case address@hidden:@] in
| +    0) set dummy "$as_dir/$ac_word";;
| +    *) set dummy "$as_dir/$ac_word" "address@hidden";;
| +    esac
|      shift
|      ac_cv_prog_$1="address@hidden"
|  m4_if([$2], [$4],

This is the kind of obfuscation I'd like to avoid.


| 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    17 Apr 2002 21:47:55 -0000
| @@ -1383,7 +1383,10 @@ do
|      ac_option=`expr "x$[1]" : 'x\([[^=]]*\)='`
|      ac_optarg=`expr "x$[1]" : 'x[[^=]]*=\(.*\)'`
|      shift
| -    set dummy "$ac_option" "$ac_optarg" ${1+"address@hidden"}
| +    case $[#] in
| +    0) set dummy "$ac_option" "$ac_optarg";;
| +    *) set dummy "$ac_option" "$ac_optarg" "address@hidden";;
| +    esac
|      shift
|      ;;
|    -*);;

Likewise.


| 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   17 Apr 2002 21:47:55 -0000
| @@ -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
| @@ -570,8 +570,12 @@ _ATEOF
|              {
|                echo "#! /bin/sh"
|                echo "cd $at_dir"
| -              echo 'exec ${CONFIG_SHELL-'"$SHELL"'}' "$[0]" \
| -                   '-v -d' "$at_debug_args" "$at_group" 
'${1+"address@hidden"}'
| +              echo 'case $[#] in'
| +              echo '0) exec ${CONFIG_SHELL-'"$SHELL"'}' "$[0]" \
| +                   '-v -d' "$at_debug_args" "$at_group;;"
| +              echo '*) exec ${CONFIG_SHELL-'"$SHELL"'}' "$[0]" \
| +                   '-v -d' "$at_debug_args" "$at_group" '"address@hidden";;'
| +              echo 'esac'
|                echo 'exit 1'
|              } >$at_group_dir/run
|              chmod +x $at_group_dir/run

Ditto.


| Index: lib/m4sugar/m4sh.m4
| ===================================================================
| RCS file: /cvsroot/autoconf/autoconf/lib/m4sugar/m4sh.m4,v
| retrieving revision 1.83
| diff -p -u -r1.83 m4sh.m4
| --- lib/m4sugar/m4sh.m4       10 Apr 2002 17:36:45 -0000      1.83
| +++ lib/m4sugar/m4sh.m4       17 Apr 2002 21:47:55 -0000
| @@ -146,9 +146,6 @@ m4_defun([AS_SHELL_SANITIZE],
|  if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
|    emulate sh
|    NULLCMD=:
| -  [#] Zsh 3.x and 4.x performs word splitting on ${1+"address@hidden"}, which
| -  # is contrary to our usage.  Disable this feature.
| -  alias -g '${1+"address@hidden"}'='"address@hidden"'
|  elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
|    set -o posix
|  fi

I see no point is removing this: it makes M4sh scripts more uniform,
more robust to the usual writing.  Even if you want to promote the
case $#/"$@" approach, I don't understand what motivates the removal
of this.


| @@ -555,7 +552,10 @@ _AS_LINENO_WORKS || {
|            AS_UNSET(ENV)
|            CONFIG_SHELL=$as_dir/$as_base
|            export CONFIG_SHELL
| -          exec "$CONFIG_SHELL" "$[0]" ${1+"address@hidden"}
| +          case $[#] in
| +          0) exec "$CONFIG_SHELL" "$[0]";;
| +          *) exec "$CONFIG_SHELL" "$[0]" "address@hidden";;
| +          esac
|          fi;;
|        esac
|         done]);;

:(


| 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        17 Apr 2002 21:47:55 -0000
| @@ -318,7 +318,10 @@ 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 'exec ${CONFIG_SHELL-'"$SHELL"'} '"$[0]"' -v -d '"$at_group"' 
${1+"address@hidden"}'
| +      echo 'case $[#] in'
| +      echo '0) exec ${CONFIG_SHELL-'"$SHELL"'} '"$[0]"' -v -d 
'"$at_group"';;'
| +      echo '*) exec ${CONFIG_SHELL-'"$SHELL"'} '"$[0]"' -v -d '"$at_group"' 
"address@hidden";;'
| +      echo 'esac'
|        echo 'exit 1'
|      ) >debug-$at_group.sh
|      chmod +x debug-$at_group.sh

:(

Please, install.



| Index: tests/autoreconf.in
| ===================================================================
| RCS file: /cvsroot/autoconf/autoconf/tests/autoreconf.in,v
| retrieving revision 1.2
| diff -p -u -r1.2 autoreconf.in
| --- tests/autoreconf.in       14 Dec 2001 17:57:29 -0000      1.2
| +++ tests/autoreconf.in       17 Apr 2002 21:47:55 -0000
| @@ -3,4 +3,7 @@
|  
|  me=`echo "$0" | sed -e 's,.*[\\/],,'`
|  
| -exec @abs_top_builddir@/bin/$me --autoconf-dir @abs_top_builddir@/lib 
${1+"$@"}
| +case $# in
| +0) exec @abs_top_builddir@/bin/$me --autoconf-dir @abs_top_builddir@/lib;;
| +*) exec @abs_top_builddir@/bin/$me --autoconf-dir @abs_top_builddir@/lib 
"$@";;
| +esac

This guy is generated (and doesn't reflect some of your other changes).


| 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        17 Apr 2002 21:47:55 -0000
| @@ -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
|  ]])
|  

ok.


| Index: tests/wrappl.as
| ===================================================================
| RCS file: /cvsroot/autoconf/autoconf/tests/wrappl.as,v
| retrieving revision 1.3
| diff -p -u -r1.3 wrappl.as
| --- tests/wrappl.as   12 Apr 2002 10:10:10 -0000      1.3
| +++ tests/wrappl.as   17 Apr 2002 21:47:55 -0000
| @@ -9,7 +9,10 @@ export autom4te_perllibdir
|  case $as_me in
|    ifnames)
|       # Does not have lib files.
| -     exec @abs_top_builddir@/bin/$as_me ${1+"$@"}
| +     case $# in
| +     0) exec @abs_top_builddir@/bin/$as_me;;
| +     *) exec @abs_top_builddir@/bin/$as_me "$@";;
| +     esac
|       ;;
|  
|    autom4te)
| @@ -19,6 +22,11 @@ case $as_me in
|  
|  esac
|  # We might need files from build (frozen files), in addition of src files.
| -exec @abs_top_builddir@/bin/$as_me \
| +case $# in
| +0) exec @abs_top_builddir@/bin/$as_me \
|       -I @abs_top_builddir@/lib \
| -     -I @abs_top_srcdir@/lib ${1+"$@"}
| +     -I @abs_top_srcdir@/lib;;
| +*) exec @abs_top_builddir@/bin/$as_me \
| +     -I @abs_top_builddir@/lib \
| +     -I @abs_top_srcdir@/lib "$@";;
| +esac

:(  I really prefer the other approach.


| Index: tests/wrapsh.as
| ===================================================================
| RCS file: /cvsroot/autoconf/autoconf/tests/wrapsh.as,v
| retrieving revision 1.2
| diff -p -u -r1.2 wrapsh.as
| --- tests/wrapsh.as   12 Apr 2002 09:56:11 -0000      1.2
| +++ tests/wrapsh.as   17 Apr 2002 21:47:55 -0000
| @@ -1,4 +1,7 @@
|  AS_INIT[]dnl                                         -*- shell-script -*-
|  # @configure_input@
|  # Running `$0' as if it were installed.
| -exec @abs_top_builddir@/bin/$as_me --include @abs_top_builddir@/lib ${1+"$@"}
| +case $# in
| +0) exec @abs_top_builddir@/bin/$as_me --include @abs_top_builddir@/lib;;
| +*) exec @abs_top_builddir@/bin/$as_me --include @abs_top_builddir@/lib "$@";;
| +esac
| 



reply via email to

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