gbranden pushed a commit to branch master
in repository groff.
commit 2b86c9332c7599db2371d19a49b173593f19799d
Author: G. Branden Robinson <[email protected]>
AuthorDate: Wed Feb 4 05:30:17 2026 -0600
Stop using `${1+"$@"}` in shell scripts.
...to kludge around old broken shells.
The (forthcoming) Autoconf 2.73 manual explains.
---snip---
You may see usages like ‘${1+"$@"}’ in older shell scripts designed to
work around a portability problem in ancient shells. Unfortunately this
runs afoul of bugs in more-recent shells, and nowadays it is better to
use plain ‘"$@"’ instead.
The portability problem with ancient shells was significant. When there
are no positional arguments ‘"$@"’ should be discarded, but the original
Unix version 7 Bourne shell mistakenly treated it as equivalent to ‘""’
instead, and many ancient shells followed its lead.
For many years shell scripts worked around this portability problem by
using ‘${1+"$@"}’ instead of ‘"$@"’, and you may see this usage in older
scripts. Unfortunately, ‘${1+"$@"}’ does not work with ‘ksh93’ M 93t+
(2009) as shipped in AIX 7.2 (2015), as this shell drops a trailing
empty argument:
$ set a b c ""
$ set ${1+"$@"}
$ echo $#
3
Also, ‘${1+"$@"}’ does not work with Zsh 4.2.6 (2005) and earlier, as
shipped in Mac OS X releases before 10.5, as this old Zsh incorrectly
word splits the result:
zsh $ emulate sh
zsh $ for i in "$@"; do echo $i; done
Hello World
!
zsh $ for i in ${1+"$@"}; do echo $i; done
Hello
World
!
---end snip---
In light of all this winning by elite shell developers, use plain,
idiomatic `"$@"` instead, relying on downstream distributors to patch
the handful of occurrences in groff should their deployments be boxed in
by a buggy /bin/sh.
* src/preproc/eqn/neqn.sh:
* src/roff/nroff/nroff.sh:
* test-groff.in: Do it.
---
ChangeLog | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
src/preproc/eqn/neqn.sh | 5 +----
src/roff/nroff/nroff.sh | 9 ++-------
test-groff.in | 2 +-
4 files changed, 56 insertions(+), 12 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 33536ce32..ca157d341 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,55 @@
+2026-02-04 G. Branden Robinson <[email protected]>
+
+ Stop using `${1+"$@"}` to kludge around old broken shells.
+
+ The (forthcoming) Autoconf 2.73 manual explains.
+
+ ---snip---
+ You may see usages like ‘${1+"$@"}’ in older shell scripts
+ designed to work around a portability problem in ancient shells.
+ Unfortunately this runs afoul of bugs in more-recent shells, and
+ nowadays it is better to use plain ‘"$@"’ instead.
+
+ The portability problem with ancient shells was significant.
+ When there are no positional arguments ‘"$@"’ should be
+ discarded, but the original Unix version 7 Bourne shell
+ mistakenly treated it as equivalent to ‘""’ instead, and many
+ ancient shells followed its lead.
+
+ For many years shell scripts worked around this portability
+ problem by using ‘${1+"$@"}’ instead of ‘"$@"’, and you may see
+ this usage in older scripts. Unfortunately, ‘${1+"$@"}’ does
+ not work with ‘ksh93’ M 93t+ (2009) as shipped in AIX 7.2
+ {2015}, as this shell drops a trailing empty argument:
+
+ $ set a b c ""
+ $ set ${1+"$@"}
+ $ echo $#
+ 3
+
+ Also, ‘${1+"$@"}’ does not work with Zsh 4.2.6 (2005) and
+ earlier, as shipped in Mac OS X releases before 10.5, as this
+ old Zsh incorrectly word splits the result:
+
+ zsh $ emulate sh
+ zsh $ for i in "$@"; do echo $i; done
+ Hello World
+ !
+ zsh $ for i in ${1+"$@"}; do echo $i; done
+ Hello
+ World
+ !
+ ---end snip---
+
+ In light of all this winning by elite shell developers,
+ use plain, idiomatic `"$@"` instead, relying on downstream
+ distributors to patch the handful of occurrences in groff should
+ their deployments be boxed in by a buggy /bin/sh.
+
+ * src/preproc/eqn/neqn.sh:
+ * src/roff/nroff/nroff.sh:
+ * test-groff.in: Do it.
+
2026-02-03 G. Branden Robinson <[email protected]>
* m4/groff.m4 (GROFF_URW_FONTS_CHECK): Stop blanking
diff --git a/src/preproc/eqn/neqn.sh b/src/preproc/eqn/neqn.sh
index 0846a03f7..12864a6eb 100644
--- a/src/preproc/eqn/neqn.sh
+++ b/src/preproc/eqn/neqn.sh
@@ -56,10 +56,7 @@ EOF
esac
done
-# Note: The construction '${1+"@$"}' preserves the absence of arguments
-# in old shells; see "Shell Substitutions" in the GNU Autoconf manual.
-# We don't want 'neqn' to become 'neqn ... ""' if $# equals zero.
-exec @g@eqn -T ascii ${1+"$@"}
+exec @g@eqn -T ascii "$@"
# Local Variables:
# fill-column: 72
diff --git a/src/roff/nroff/nroff.sh b/src/roff/nroff/nroff.sh
index c465cb39e..05c293632 100644
--- a/src/roff/nroff/nroff.sh
+++ b/src/roff/nroff/nroff.sh
@@ -251,16 +251,11 @@ groff=${GROFF_TEST_GROFF-groff}
#
# If POSIX adopts Bash's ${var@Q} or an equivalent, this issue can be
# revisited.
-#
-# Note 2: The construction '${1+"$@"}' preserves the absence of
-# arguments in old shells; see "Shell Substitutions" in the GNU Autoconf
-# manual. We don't want 'nroff' to become 'groff ... ""' if $# equals
-# zero.
if [ -n "$dry_run" ]
then
- echo PATH="$GROFF_RUNTIME$PATH" $groff $T $opts ${1+"$@"}
+ echo PATH="$GROFF_RUNTIME$PATH" $groff $T $opts "$@"
else
- PATH="$GROFF_RUNTIME$PATH" $groff $T $opts ${1+"$@"}
+ PATH="$GROFF_RUNTIME$PATH" $groff $T $opts "$@"
fi
# Local Variables:
diff --git a/test-groff.in b/test-groff.in
index aa5da5071..a65898a77 100644
--- a/test-groff.in
+++ b/test-groff.in
@@ -52,4 +52,4 @@ $SEP$builddir/contrib/sboxes\
export GROFF_COMMAND_PREFIX
export GROFF_BIN_PATH GROFF_FONT_PATH GROFF_TMAC_PATH
-exec $builddir/groff ${1+"$@"}
+exec $builddir/groff "$@"
_______________________________________________
groff-commit mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit