bug-gnulib
[Top][All Lists]
Advanced

[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 ()





reply via email to

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