[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Bug in gnulib-tools prevents bison from bootstrapping
From: |
Bruno Haible |
Subject: |
Re: Bug in gnulib-tools prevents bison from bootstrapping |
Date: |
Sat, 23 Jun 2007 12:13:22 +0200 |
User-agent: |
KMail/1.5.4 |
Eric Blake wrote:
> POSIX requires that echo interpret backslash sequences.
POSIX:2001 Technical Corrigendum 1 [1] mentions that BSD echo is POSIX
compliant.
Eric Blake and Paul Eggert wrote:
> POSIX even admits this, and recommends the use of printf instead.
> ...
> One advantage of using printf is that it won't mishandle a string that
> happens to equal "-n".
But I don't want to use printf %s\n in 500 places because
1) It is less legible.
2) Using a complex primitive for a simple task requires more introspection
for being well optimized (similar to what we see in C: how many
compilers optimize printf("%s",s) to puts(s)?).
3) It is a heavy slowdown for FreeBSD /bin/sh, which has 'echo' built-in
but not 'printf',
4) The argument size is inherently limited to the maximum argument size
that can be passed to programs, and this limit is ridiculously small
on many Linux systems: 256 KB, which is less than 0.1% of main memory.
5) I would not be surprised if some 'printf' implementations had 4 KB limits.
Built-in echo and an echo emulation that uses 'cat' do not have these
problems.
> printf is not yet universally portable, but at least it is a shell builtin
> on many common shells (but notably not a builtin in Solaris' /bin/sh).
Which are these "many common shells"? It is not a builtin in ksh. It is
not a builtin in the various vendors' /bin/sh. The only shell that I found
that has 'printf' built-in is bash >= 2.0.
> Since forking external programs matters most on cygwin and mingw, where
> printf is always available as a builtin, it is one of the lightest-weight
> alternatives to echo when you are worried about the number of processes.
OK, I took this into consideration and optimized the 'echo' emulation in
the case of bash versions >= 2.0, < 2.04.
Bruno
[1] http://www.opengroup.org/austin/docs/austin_155.txt
2007-06-23 Bruno Haible <address@hidden>
* gnulib-tool (echo): Add workarounds also for bash versions < 2.04.
* tests/test-echo.sh: Likewise.
*** gnulib-tool 23 Jun 2007 07:40:58 -0000 1.236
--- gnulib-tool 23 Jun 2007 09:45:35 -0000
***************
*** 415,430 ****
# Test cases:
# echo '\n' | wc -l prints 1 when OK, 2 when KO
# echo '\t' | grep t > /dev/null has return code 0 when OK, 1 when KO
! # This problem is a weird heritage from SVR4. BSD got it right.
# Nowadays the problem occurs in 4 situations:
! # - in bash, when the shell option xpg_echo is set,
# - in zsh, when sh-emulation is not set,
# - in ksh (e.g. AIX /bin/sh and Solaris /usr/xpg4/bin/sh are ksh instances,
# and HP-UX /bin/sh and IRIX /bin/sh behave similarly),
# - in Solaris /bin/sh and OSF/1 /bin/sh.
# We try the following workarounds:
# - for all: respawn using $CONFIG_SHELL if that is set and works.
! # - for bash: unset the shell option xpg_echo.
# - for zsh: turn sh-emulation on.
# - for ksh: alias echo to a function that uses cat of a here document.
# - for Solaris /bin/sh: respawn using /bin/ksh and rely on the ksh
workaround.
--- 415,435 ----
# Test cases:
# echo '\n' | wc -l prints 1 when OK, 2 when KO
# echo '\t' | grep t > /dev/null has return code 0 when OK, 1 when KO
! # This problem is a weird heritage from SVR4. BSD got it right (except that
! # BSD echo interprets '-n' as an option, which is also not desirable).
# Nowadays the problem occurs in 4 situations:
! # - in bash, when the shell option xpg_echo is set (bash >= 2.04)
! # or when it was built with --enable-usg-echo-default (bash >= 2.0)
! # or when it was built with DEFAULT_ECHO_TO_USG (bash < 2.0),
# - in zsh, when sh-emulation is not set,
# - in ksh (e.g. AIX /bin/sh and Solaris /usr/xpg4/bin/sh are ksh instances,
# and HP-UX /bin/sh and IRIX /bin/sh behave similarly),
# - in Solaris /bin/sh and OSF/1 /bin/sh.
# We try the following workarounds:
# - for all: respawn using $CONFIG_SHELL if that is set and works.
! # - for bash >= 2.04: unset the shell option xpg_echo.
! # - for bash >= 2.0: define echo to a function that uses the printf built-in.
! # - for bash < 2.0: define echo to a function that uses cat of a here
document.
# - for zsh: turn sh-emulation on.
# - for ksh: alias echo to a function that uses cat of a here document.
# - for Solaris /bin/sh: respawn using /bin/ksh and rely on the ksh
workaround.
***************
*** 445,457 ****
exec $CONFIG_SHELL "$0" --no-reexec "$@"
exit 127
fi
! # For bash: unset the shell option xpg_echo.
if test -z "$have_echo" \
&& test -n "$BASH_VERSION" \
&& (shopt -o xpg_echo; echo '\t' | grep t > /dev/null) 2>/dev/null; then
shopt -o xpg_echo
have_echo=yes
fi
# For zsh: turn sh-emulation on.
if test -z "$have_echo" \
&& test -n "$ZSH_VERSION" \
--- 450,486 ----
exec $CONFIG_SHELL "$0" --no-reexec "$@"
exit 127
fi
! # For bash >= 2.04: unset the shell option xpg_echo.
if test -z "$have_echo" \
&& test -n "$BASH_VERSION" \
&& (shopt -o xpg_echo; echo '\t' | grep t > /dev/null) 2>/dev/null; then
shopt -o xpg_echo
have_echo=yes
fi
+ # For bash >= 2.0: define echo to a function that uses the printf built-in.
+ # For bash < 2.0: define echo to a function that uses cat of a here document.
+ # (There is no win in using 'printf' over 'cat' if it is not a shell
built-in.)
+ if test -z "$have_echo" \
+ && test -n "$BASH_VERSION"; then \
+ if type printf 2>/dev/null | grep / > /dev/null; then
+ # 'printf' is not a shell built-in.
+ echo ()
+ {
+ cat <<EOF
+ $*
+ EOF
+ }
+ else
+ # 'printf' is a shell built-in.
+ echo ()
+ {
+ printf '%s\n' "$*"
+ }
+ fi
+ if echo '\t' | grep t > /dev/null; then
+ have_echo=yes
+ fi
+ fi
# For zsh: turn sh-emulation on.
if test -z "$have_echo" \
&& test -n "$ZSH_VERSION" \
***************
*** 464,470 ****
# Therefore, for an alias to take effect, the alias definition command has
# to be executed before the command which references the alias is read."
# Because of this, we have to play strange tricks with have_echo, to ensure
! # that the top-level statement containing the test start after the 'alias'
# command.
if test -z "$have_echo"; then
bsd_echo ()
--- 493,499 ----
# Therefore, for an alias to take effect, the alias definition command has
# to be executed before the command which references the alias is read."
# Because of this, we have to play strange tricks with have_echo, to ensure
! # that the top-level statement containing the test starts after the 'alias'
# command.
if test -z "$have_echo"; then
bsd_echo ()
*** tests/test-echo.sh 23 Jun 2007 02:02:04 -0000 1.1
--- tests/test-echo.sh 23 Jun 2007 09:45:35 -0000
***************
*** 20,35 ****
# Test cases:
# echo '\n' | wc -l prints 1 when OK, 2 when KO
# echo '\t' | grep t > /dev/null has return code 0 when OK, 1 when KO
! # This problem is a weird heritage from SVR4. BSD got it right.
# Nowadays the problem occurs in 4 situations:
! # - in bash, when the shell option xpg_echo is set,
# - in zsh, when sh-emulation is not set,
# - in ksh (e.g. AIX /bin/sh and Solaris /usr/xpg4/bin/sh are ksh instances,
# and HP-UX /bin/sh and IRIX /bin/sh behave similarly),
# - in Solaris /bin/sh and OSF/1 /bin/sh.
# We try the following workarounds:
# - for all: respawn using $CONFIG_SHELL if that is set and works.
! # - for bash: unset the shell option xpg_echo.
# - for zsh: turn sh-emulation on.
# - for ksh: alias echo to a function that uses cat of a here document.
# - for Solaris /bin/sh: respawn using /bin/ksh and rely on the ksh
workaround.
--- 20,40 ----
# Test cases:
# echo '\n' | wc -l prints 1 when OK, 2 when KO
# echo '\t' | grep t > /dev/null has return code 0 when OK, 1 when KO
! # This problem is a weird heritage from SVR4. BSD got it right (except that
! # BSD echo interprets '-n' as an option, which is also not desirable).
# Nowadays the problem occurs in 4 situations:
! # - in bash, when the shell option xpg_echo is set (bash >= 2.04)
! # or when it was built with --enable-usg-echo-default (bash >= 2.0)
! # or when it was built with DEFAULT_ECHO_TO_USG (bash < 2.0),
# - in zsh, when sh-emulation is not set,
# - in ksh (e.g. AIX /bin/sh and Solaris /usr/xpg4/bin/sh are ksh instances,
# and HP-UX /bin/sh and IRIX /bin/sh behave similarly),
# - in Solaris /bin/sh and OSF/1 /bin/sh.
# We try the following workarounds:
# - for all: respawn using $CONFIG_SHELL if that is set and works.
! # - for bash >= 2.04: unset the shell option xpg_echo.
! # - for bash >= 2.0: define echo to a function that uses the printf built-in.
! # - for bash < 2.0: define echo to a function that uses cat of a here
document.
# - for zsh: turn sh-emulation on.
# - for ksh: alias echo to a function that uses cat of a here document.
# - for Solaris /bin/sh: respawn using /bin/ksh and rely on the ksh
workaround.
***************
*** 50,62 ****
exec $CONFIG_SHELL "$0" --no-reexec "$@"
exit 127
fi
! # For bash: unset the shell option xpg_echo.
if test -z "$have_echo" \
&& test -n "$BASH_VERSION" \
&& (shopt -o xpg_echo; echo '\t' | grep t > /dev/null) 2>/dev/null; then
shopt -o xpg_echo
have_echo=yes
fi
# For zsh: turn sh-emulation on.
if test -z "$have_echo" \
&& test -n "$ZSH_VERSION" \
--- 55,91 ----
exec $CONFIG_SHELL "$0" --no-reexec "$@"
exit 127
fi
! # For bash >= 2.04: unset the shell option xpg_echo.
if test -z "$have_echo" \
&& test -n "$BASH_VERSION" \
&& (shopt -o xpg_echo; echo '\t' | grep t > /dev/null) 2>/dev/null; then
shopt -o xpg_echo
have_echo=yes
fi
+ # For bash >= 2.0: define echo to a function that uses the printf built-in.
+ # For bash < 2.0: define echo to a function that uses cat of a here document.
+ # (There is no win in using 'printf' over 'cat' if it is not a shell
built-in.)
+ if test -z "$have_echo" \
+ && test -n "$BASH_VERSION"; then \
+ if type printf 2>/dev/null | grep / > /dev/null; then
+ # 'printf' is not a shell built-in.
+ echo ()
+ {
+ cat <<EOF
+ $*
+ EOF
+ }
+ else
+ # 'printf' is a shell built-in.
+ echo ()
+ {
+ printf '%s\n' "$*"
+ }
+ fi
+ if echo '\t' | grep t > /dev/null; then
+ have_echo=yes
+ fi
+ fi
# For zsh: turn sh-emulation on.
if test -z "$have_echo" \
&& test -n "$ZSH_VERSION" \
***************
*** 69,75 ****
# Therefore, for an alias to take effect, the alias definition command has
# to be executed before the command which references the alias is read."
# Because of this, we have to play strange tricks with have_echo, to ensure
! # that the top-level statement containing the test start after the 'alias'
# command.
if test -z "$have_echo"; then
bsd_echo ()
--- 98,104 ----
# Therefore, for an alias to take effect, the alias definition command has
# to be executed before the command which references the alias is read."
# Because of this, we have to play strange tricks with have_echo, to ensure
! # that the top-level statement containing the test starts after the 'alias'
# command.
if test -z "$have_echo"; then
bsd_echo ()
- Re: Bug in gnulib-tools prevents bison from bootstrapping, (continued)
Re: Bug in gnulib-tools prevents bison from bootstrapping, Ralf Wildenhues, 2007/06/22
Re: Bug in gnulib-tools prevents bison from bootstrapping, Bruno Haible, 2007/06/22