Bash crashes if you try to mapfile into an associative array

2009-10-16 Thread Nick Hobson
From: Nick Hobson
To: bug-bash@gnu.org
Subject: Bash crashes if you try to mapfile into an associative array

Configuration Information [Automatically generated, do not change]:
Machine: i686
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i686' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i686-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib   -march=i686 -mtune=generic -O2 
-pipe
uname output: Linux localhost 2.6.31-ARCH #1 SMP PREEMPT Tue Oct 13 13:36:23 
CEST 2009 i686 Intel(R) Celeron(R) CPU 550 @ 2.00GHz GenuineIntel GNU/Linux
Machine Type: i686-pc-linux-gnu

Bash Version: 4.0
Patch Level: 33
Release Status: release

Description:
If you declare an array to be associative and then try to mapfile (or 
readarray) into it, Bash crashes.

Repeat-By:
declare -A x
mapfile x 

IFS=: breaks literal patterns with character classes

2009-10-16 Thread Enrique Perez-Terron
Configuration Information [Automatically generated, do not change]:
Machine: i386
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i386' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i386-redhat-linux-gnu' 
-DCONF_VENDOR='redhat' -DLOCALE
DIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H   -I.  -I. 
-I./include -I./lib  -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 
-O2 
-g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector 
--param=ssp-buffer-size=4 -m32 -march=i586 -mtune=generic 
-fasynchronous-unwind-tables
uname output: Linux apeiron.home.lan 2.6.29.4-167.fc11.i586 #1 SMP Wed May 27 
17:14:37 EDT 2009 i686 i686 i386 GNU/Linux
Machine Type: i386-redhat-linux-gnu

Bash Version: 4.0
Patch Level: 23
Release Status: release

Description:
See the Repeat-by section. Character class [:graph:] appears not to 
match as it
should, if IFS=':'.  Why, or at what stage, is IFS used here? 

Repeat-By:
$ # Correct:
$ (IFS=' '; case A in ([[:graph:]]) echo graph;; (*) echo non-graph;; 
esac)
graph

$ # Not correct:
$ (IFS=':'; case A in ([[:graph:]]) echo graph;; (*) echo non-graph;; 
esac)
non-graph

$ # Contrast with
$ (IFS=:; echo a:b)
a:b

$ # The error also happens with the == operator:
$ # Correct:
$ (IFS=' '; [[ A == [[:graph:]] ]] && echo yes || echo no)
yes

$ # Not correct
$ (IFS=':'; [[ A == [[:graph:]] ]] && echo yes || echo no)
no







PS1 prompt problem

2009-10-16 Thread Nils
I'm using bash 3.2 and I'd like to set my prompt to the following
(inspired by the Opensolaris prompt for ksh93):

PS1='$(
spwd="${PWD/#${HOME}/~}"
[[ ${#spwd} -gt 10 ]] && spwd="...${spwd: -10}"
printf "%...@%s:%s%s " "\u" "\h" "${spwd}" "\$"
termtitle="\...@\h:${spwd}"


printf "%s" "\["
case "${TERM}" in
(xterm*)
printf "\033]0;%s\a" "${termtitle}"
;;
(screen*)
printf "\033_%s\033\\" "${termtitle}"
;;
esac
printf "%s" "\]"

)'

Basically this is supposed to shorten PWD to the last 10 characters
and set the terminal title as well. Unfortunately it causes bash to
hang, the problem seems to lie in the escape codes for entering and
leaving the terminal title and the surrounding "\[" "\]" because
commenting out the case statement and the surrounding printfs makes it
at least set the prompt correctly. I have the strong suspicion it
might be some quoting issue.

Using printf "\033]0;%s\a" "${PWD}" on the command line will set the
xterm title to $PWD.
Setting PROMPT_COMMAND='printf "\033]0;%s\a" "${PWD}"' works as well,
however I do not want to use $PROMPT_COMMAND for efficiency reasons as
I would have to calculate $spwd (and possibly other things later)
twice.
Following a suggestion in comp.unix.shell putting the above code
contained in $() inside a separate function f and setting PS1='$( f )'
displays the $spwd correctly in both the prompt and xterm title, but
bash escapes like "\u", "\h" etc are not expanded any more

What's wrong here?


Re: Bash crashes if you try to mapfile into an associative array

2009-10-16 Thread Chet Ramey
Nick Hobson wrote:
> From: Nick Hobson
> To: bug-bash@gnu.org
> Subject: Bash crashes if you try to mapfile into an associative array
> 
> Configuration Information [Automatically generated, do not change]:
> Machine: i686
> OS: linux-gnu
> Compiler: gcc
> Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i686' 
> -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i686-pc-linux-gnu' 
> -DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
> -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib   -march=i686 -mtune=generic 
> -O2 -pipe
> uname output: Linux localhost 2.6.31-ARCH #1 SMP PREEMPT Tue Oct 13 13:36:23 
> CEST 2009 i686 Intel(R) Celeron(R) CPU 550 @ 2.00GHz GenuineIntel GNU/Linux
> Machine Type: i686-pc-linux-gnu
> 
> Bash Version: 4.0
> Patch Level: 33
> Release Status: release
> 
> Description:
> If you declare an array to be associative and then try to mapfile (or 
> readarray) into it, Bash crashes.
> 

That's an incorrect use of `mapfile' -- mapfile takes an indexed array --
but the shell still shouldn't crash by assuming the variable is an
indexed array.  I'll fix that for bash-4.1.

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/




Re: PS1 prompt problem

2009-10-16 Thread Andreas Schwab
Nils  writes:

> Following a suggestion in comp.unix.shell putting the above code
> contained in $() inside a separate function f and setting PS1='$( f )'
> displays the $spwd correctly in both the prompt and xterm title, but
> bash escapes like "\u", "\h" etc are not expanded any more

You could pass them as arguments to the function.

> What's wrong here?

You are faced with multi-level expansion and need to protect the special
characters that you want to be preserved for the later levels.  Before
the command substitution is expanded all backslash sequences are
expanded, so for example "\033_%s\033\\" becomes "^[_%s^[\" (where ^[
denotes the literal escape character).  The trailing backslash is now
quoting the quote character, which results in an unmatched quote.  Thus
you should write "\\033_%s\\033" instead.

PS1='$(
spwd="${PWD/#${HOME}/~}"
[[ ${#spwd} -gt 10 ]] && spwd="...${spwd: -10}"
printf "%...@%s:%s%s " "\u" "\h" "${spwd}" "\$"
termtitle="\...@\h:${spwd}"


printf "%s" "\["
case "${TERM}" in
(xterm*)
printf "\\033]0;%s\\a" "${termtitle}"
;;
(screen*)
printf "\\033_%s\\033" "${termtitle}"
;;
esac
printf "%s" "\]"

)'

Andreas.

-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."




Re: PS1 prompt problem

2009-10-16 Thread Chet Ramey
Nils wrote:
> I'm using bash 3.2 and I'd like to set my prompt to the following
> (inspired by the Opensolaris prompt for ksh93):
> 
> PS1='$(
> spwd="${PWD/#${HOME}/~}"
> [[ ${#spwd} -gt 10 ]] && spwd="...${spwd: -10}"
> printf "%...@%s:%s%s " "\u" "\h" "${spwd}" "\$"
> termtitle="\...@\h:${spwd}"
> 
> 
> printf "%s" "\["
> case "${TERM}" in
> (xterm*)
> printf "\033]0;%s\a" "${termtitle}"
> ;;
> (screen*)
> printf "\033_%s\033\\" "${termtitle}"
> ;;
> esac
> printf "%s" "\]"
> 
> )'
> 
> Basically this is supposed to shorten PWD to the last 10 characters
> and set the terminal title as well. Unfortunately it causes bash to
> hang, the problem seems to lie in the escape codes for entering and
> leaving the terminal title and the surrounding "\[" "\]" because
> commenting out the case statement and the surrounding printfs makes it
> at least set the prompt correctly. I have the strong suspicion it
> might be some quoting issue.

Sort of.  I think you're overlooking the various expansion (and backslash
escaping) that's taking place with your prompt.

Since you set the value of PS1 to literal string containing a command
substitution, the value will be expanded twice before being sent to
readline.  The first expansion is the normal set of backslash escapes
performed by prompt string decoding; the second is the set of shell word
expansions, including command substitution.

This is the problem line: printf "\033_%s\033\\" "${termtitle}".  I
assume the intent is to wind up with a string ending with a single
backslash written to the terminal.  The string as written results in
a parsing error.

One of the prompt string decoding expansions turns \\ into \, so the
form of the above string when passed to the parser by the command
substitution is

printf "ESC_%sESC\" "${termtitle}"

(the ESC stands for a literal escape character).  The escaped double quote
is probably not what's intended.

For printf to see what you want it to, you need to double the backslashes
in that string:

printf "\033_%s\033" "${termtitle}"

Try that and see what you get.

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/




Re: PS1 prompt problem

2009-10-16 Thread Nils
On 16 Okt., 21:18, Chet Ramey  wrote:
> Sort of.  I think you're overlooking the various expansion (and backslash
> escaping) that's taking place with your prompt.
>
> Since you set the value of PS1 to literal string containing a command
> substitution, the value will be expanded twice before being sent to
> readline.  The first expansion is the normal set of backslash escapes
> performed by prompt string decoding; the second is the set of shell word
> expansions, including command substitution.
>
> This is the problem line: printf "\033_%s\033\\" "${termtitle}".  I
> assume the intent is to wind up with a string ending with a single
> backslash written to the terminal.  The string as written results in
> a parsing error.
>
> One of the prompt string decoding expansions turns \\ into \, so the
> form of the above string when passed to the parser by the command
> substitution is
>
>         printf "ESC_%sESC\" "${termtitle}"
>
> (the ESC stands for a literal escape character).  The escaped double quote
> is probably not what's intended.
>
> For printf to see what you want it to, you need to double the backslashes
> in that string:
>
>         printf "\033_%s\033" "${termtitle}"
>
> Try that and see what you get.

Yes, that was the problem, I did not take into account that bash
expands $PS1 twice. This is easy to reproduce by setting PS1='$
( printf "\\" )' which works with ash, ksh93, ksh88 but fails with
bash which needs PS1='$( printf "" )'. Is this double expansion
even POSIX compliant? The spec says that "[e]ach time an interactive
shell is ready to read a command, the value of this variable shall be
subjected to parameter expansion..." (http://www.opengroup.org/
onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_05_03)


Re: PS1 prompt problem

2009-10-16 Thread Chet Ramey
Nils wrote:
> 
> Yes, that was the problem, I did not take into account that bash
> expands $PS1 twice.

No, it doesn't.  It performs additional expansions besides those
specified by Posix.

> Is this double expansion even POSIX compliant? 

Yes.
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/




Re: IFS=: breaks literal patterns with character classes

2009-10-16 Thread Chet Ramey
Enrique Perez-Terron wrote:

> Bash Version: 4.0
> Patch Level: 23
> Release Status: release
> 
> Description:
>   See the Repeat-by section. Character class [:graph:] appears not to 
> match as it
>   should, if IFS=':'.  Why, or at what stage, is IFS used here? 

Thanks for the report.  This will be fixed in bash-4.1.

Chet


-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/




Re: Oddities when tab-completing filenames containing backticks

2009-10-16 Thread Chet Ramey
bash-b...@atu.cjb.net wrote:

> Bash Version: 4.0
> Patch Level: 39
> Release Status: release
> 
> Description:
>
>Also affects Bash 4.0.33.
>
>When a filename begins with a backtick ` then tab-completion works
>as expected if you go \`, however if you try to tab-complete
>the filename inside single quotes, several strange behaviours appear.

You need to remember that readline understands the characters in
rl_completer_quote_characters as those which, in pairs, delimit quoted
substrings in the line.  It performs completion (allowing the application
to take first crack, of course) on the substring, using the text after
the open quote.

The other thing to keep in mind is that readline doesn't look past point
when performing completion -- it only considers characters from the
beginning of the line or a quote character up to point.

My answers below are for the built-in bash completion, not any programmable
completions you might have defined.

> Repeat-By:
> 
>1) '`  This causes all commands available on the system to be
>listed such as `awk `bash etc., even though it's inside
>single quotes.

Readline does completion on substrings; it passes ` to the bash completion
code, which performs command completion.

> 
>2) '`text  This completes the filename, but it does not insert a
>trailing single quote as tab-completion would usually do.

Bash receives "`text", does command completion on `text' and suppresses
the append of the close quote, since it's usually wrong in this case.

>3) '`dir   This completes the directory name and adds the trailing
>forward slash, but not the trailing single quote.

Again, appending the trailing single quote without the trailing ` is
generally going to be wrong.

>4) 'text`  This completes the filename and closes the single quote
>as expected.

Interesting.  I don't get this behavior.

>5) '`text' When using tab-completion inside single quotes on a
>filename beginning with a backtick, then it completes
>the filename and adds an additional closing single quote,
>e.g. '`filename.txt''

Also interesting.  I get normal command completion without any closing
quote appended.

>6) '`dir'  When using tab-completion inside single quotes on a
>directory name beginning with a backtick, then it
>completes the directory name and adds an additional
>closing single quote after the directory name and before
>the forward slash, e.g. '`directory'/'

I don't see this behavior either.

Chet

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/