autoconf
[Top][All Lists]
Advanced

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

bash 2.05 'set' incompatibility with POSIX is breaking Autoconf


From: Paul Eggert
Subject: bash 2.05 'set' incompatibility with POSIX is breaking Autoconf
Date: Sun, 21 Oct 2001 13:49:07 -0700 (PDT)

Configuration Information [Automatically generated, do not change]:
Machine: sparc
OS: solaris2.8
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='sparc' 
-DCONF_OSTYPE='solaris2.8' -DCONF_MACHTYPE='sparc-sun-solaris2.8' 
-DCONF_VENDOR='sun' -DSHELL  -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib -g 
-O2
uname output: SunOS sic.twinsun.com 5.8 Generic_108528-10 sun4u sparc 
SUNW,UltraSPARC-IIi-Engine
Machine Type: sparc-sun-solaris2.8

Bash Version: 2.05a
Patch Level: 0
Release Status: beta1

Description:
        Autoconf users have reported an incompatibility of Bash 2.05
        with other shells (including Bash 2.04 and earlier).  This
        incompatibility occasionally causes problems when people run
        'configure' and related programs.

        Here's the problem.  'configure' uses the builtin 'set'
        command to output variable values, and stores them away into
        'config.cache'.  E.g.:

           ac_cv_prog_CPP=${ac_cv_prog_CPP='gcc -E'}

        But when 'configure' is invoked with Bash 2.05 (e.g. with
        'bash configure'), it uses the ANSI C quoting rules, so it puts
        the following into config.cache instead:

           ac_cv_prog_CPP=${ac_cv_prog_CPP=$'gcc -E'}

        Now, it's common to execute config.cache with /bin/sh or with
        some other shell that is not Bash 2.05 or later.  When this
        happens, it mishandles the $'gcc -E' and screws up the build,
        sometimes in subtle ways.

        An example bug report (for an attempt to build GCC 2.95.2)
        with followup discussion can be found at:
        <http://sources.redhat.com/ml/autoconf/2001-09/msg00002.html>
        <http://sources.redhat.com/ml/autoconf/2001-09/msg00064.html>
        <http://sources.redhat.com/ml/autoconf/2001-09/msg00066.html>

        I see three problems here with the Bash 2.05 'set' command.

          1.  It unnecessarily quotes its output with $'...'.  There's
              no reason to include the '$' before the quoted string
              unless the string contains nonprinting chars.  This is
              not merely a question of making the output look nice: it
              is an interoperability issue, as shown by the above bug
              report.

          2.  Conversely, it does not always quote characters to make
              them printable, even when they are not printable.  For
              example:

                 $ foox=$'\f'
                 $ set | grep foox
                 foox=^L

              (Here I have used "^L" to denote an actual formfeed in
              the output.)  The output should be "foox='\$f'"; it
              should not contain a hard formfeed.

          3.  It does not conform to POSIX 1003.1-200x draft 7, which
              requires the output of 'set' to be quoted using the
              shell quoting rules described by the standard.  Hence
              'set' should not output $'...' in POSIX mode.

Repeat-By:
        Example of unnecessary and sometimes-harmful '$' in output:
        $ foobar='gcc -E'
        $ set | grep foobar
        foobar=$'gcc -E'

        Example of missing '$' in output; here '^L' denotes a formfeed.
        $ foox=$'\f'
        $ set | grep foox
        foox=^L

Fix:

The simplest fix is to revert back to the Bash 2.04 behavior.

However, I like the idea of having 'set' output $'...' when necessary,
so I propose the following patch instead.  It is relative to
bash-2.05a-beta1 and assumes the previous Bash patches that I've
submitted.

Autoconf generates "configure" scripts that run Bash in POSIX mode,
so this patch should fix the Autoconf problem.

2001-10-21  Paul Eggert  <address@hidden>

        Change 'set' so that it uses the $'...' style quoting only for
        strings that contain nonprinting characters, and only when not
        operating in POSIX mode.  This is for better compatibility
        with other shells, and for POSIX conformance.  For example,
        Autoconf uses 'set' to generate assignment statements that are
        sometimes interpreted by shells other than Bash, or by older
        versions of Bash.

        * doc/bashref.texi (Bash POSIX Mode):
        'set' does not use ANSI C quoting in POSIX mode.

        * externs.h (ansic_contains_nonprinting_chars): New function.
        * lib/sh/strtrans.c (ansic_contains_nonprinting_chars): Likewise.

        * variables.c (print_var_value): When quoting, use ansic_quote
        only if the string contains nonprinting chars and only when
        not operating in POSIX mode; otherwise, use the quoting
        algorithm of Bash 2.04 and earlier.

===================================================================
RCS file: doc/bashref.texi,v
retrieving revision 2.5.1.2.0.1
retrieving revision 2.5.1.2.0.3
diff -pu -r2.5.1.2.0.1 -r2.5.1.2.0.3
--- doc/bashref.texi    2001/10/15 00:44:05     2.5.1.2.0.1
+++ doc/bashref.texi    2001/10/21 20:15:38     2.5.1.2.0.3
@@ -5503,6 +5503,10 @@ The @code{export} and @code{readonly} bu
 output in the format required by @sc{posix} 1003.2.
 
 @item
+When used with no arguments, the @code{set} builtin displays the
+standard syntax, even if the result contains nonprinting characters.
+
address@hidden
 The @code{trap} builtin displays signal names without the leading
 @code{SIG}.
 
===================================================================
RCS file: externs.h,v
retrieving revision 2.5.1.2.0.2
retrieving revision 2.5.1.2.0.3
diff -pu -r2.5.1.2.0.2 -r2.5.1.2.0.3
--- externs.h   2001/10/15 00:44:05     2.5.1.2.0.2
+++ externs.h   2001/10/21 19:25:03     2.5.1.2.0.3
@@ -238,6 +238,7 @@ extern unsigned long strtoul __P((const 
 /* declarations for functions defined in lib/sh/strtrans.c */
 extern char *ansicstr __P((char *, int, int, int *, int *));
 extern char *ansic_quote __P((char *, int, int *));
+extern int ansic_contains_nonprinting_chars __P((char const *));
 
 /* declarations for functions defined in lib/sh/timeval.c.  No prototypes
    so we don't have to count on having a definition of struct timeval in
===================================================================
RCS file: lib/sh/strtrans.c,v
retrieving revision 2.5.1.2.0.1
retrieving revision 2.5.1.2.0.2
diff -pu -r2.5.1.2.0.1 -r2.5.1.2.0.2
--- lib/sh/strtrans.c   2001/10/13 00:41:40     2.5.1.2.0.1
+++ lib/sh/strtrans.c   2001/10/21 19:25:03     2.5.1.2.0.2
@@ -191,3 +191,20 @@ ansic_quote (str, flags, rlen)
     *rlen = r - ret;
   return ret;
 }
+
+/* Return nonzero if STRING contains nonprinting characters that
+   ansic_quote will convert to printing characters.  */
+int
+ansic_contains_nonprinting_chars (string)
+     char const *string;
+{
+  char const *s;
+  unsigned char c;
+
+  if (string)
+    for (s = string; (c = *s); s++)
+      if (ISPRINT (c) == 0)
+       return 1;
+
+  return 0;
+}
===================================================================
RCS file: variables.c,v
retrieving revision 2.5.1.2.0.3
retrieving revision 2.5.1.2.0.5
diff -pu -r2.5.1.2.0.3 -r2.5.1.2.0.5
--- variables.c 2001/10/15 00:44:05     2.5.1.2.0.3
+++ variables.c 2001/10/21 19:47:11     2.5.1.2.0.5
@@ -902,13 +902,16 @@ print_var_value (var, quote)
 
   if (var->value)
     {
-      if (quote && sh_contains_shell_metas (var->value))
+      if (quote && !posixly_correct
+         && ansic_contains_nonprinting_chars (var->value))
        {
-#if 0
-         t = sh_single_quote (var->value);
-#else
          t = ansic_quote (var->value, 0, (int *)0);
-#endif
+         printf ("%s", t);
+         free (t);
+       }
+      else if (quote && sh_contains_shell_metas (var->value))
+       {
+         t = sh_single_quote (var->value);
          printf ("%s", t);
          free (t);
        }



reply via email to

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