[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);
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- bash 2.05 'set' incompatibility with POSIX is breaking Autoconf,
Paul Eggert <=