Re: Parsing error when "case" in "for" in $()

2012-09-12 Thread Chet Ramey
On 9/11/12 10:50 AM, Benoit Vaugon wrote:

> Description:
>   Cannot use "case" construction in a "for" loop in a $() sub shell.
>   Should work but produces parsing error.
> 
> Repeat-By:
>   echo $(for x in whatever; do case y in *) echo 42;; esac; done)

Thanks for the report.  This will be fixed in the next bash release.

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: Parsing error when "case" in "for" in $()

2012-09-11 Thread Dan Douglas
On Tuesday, September 11, 2012 05:31:36 PM Steven W. Orr wrote:
> On 09/11/12 17:20, quoth Chris F.A. Johnson:
> > On Tue, 11 Sep 2012, Benoit Vaugon wrote:
> > ...
> >> Description:
> >>  Cannot use "case" construction in a "for" loop in a $() sub shell.
> >>  Should work but produces parsing error.
> >>
> >> Repeat-By:
> >>  echo $(for x in whatever; do case y in *) echo 42;; esac; done)
> >
> >  The closing parentheses in the case statement is being interpreted as the
> > closing for $(
> >
> >> Fix:
> >>  Probably by fixing the bash parser.
> >
> > Balance the parentheses in the case statement:
> >
> > echo $(for x in whatever; do case y in (*) echo 42;; esac; done)
> >
> 
> Thanks. I didn't know that the opening paren was optional and was needed in 
> such a case as a disambiguator. Very nice. And if you really want to match 
> something that starts with an open paren, just backslash it.
> 
> As a style issue, it makes me wonder if I should always use the optional
> open paren as syntactic sugar...

I could only reproduce it with an unquoted command substitution. It may still 
not be correct even though there are workarounds. The existance of an 
enclosing compound command shouldn't affect the parsing of the inner one.

The workaround might be a good idea anyway. ksh fails this in some 
permutations but not others, while most other shells seem to be able to handle 
it (except zsh which usually fails). CC'd ast-devel in case they consider it a 
bug worth fixing.

: $(case . in .) :; esac)
fails: zsh

: $(case . in (.) :; esac)
fails:

: $({ case . in .) :; esac; })
fails: sh bash zsh

: "$({ case . in .) :; esac; })"
fails: zsh

: $(for x in .; do case . in .) :; esac; done)
fails: sh bash zsh ksh

: "$(for x in .; do case . in .) :; esac; done)"
fails: zsh

bash/ksh compatable testcase:
---
#!/usr/bin/env bash

shells=( sh {{b,d}a,z,{,m}k}sh bb )

while IFS= read -r testCase; do
printf '%s\nfails: ' "$testCase"
for sh in "${shells[@]}"; do
"$sh" -c "$testCase" 2>/dev/null || printf '%s ' "$sh"
done
echo $'\n'
done <<"EOF"
: $(case . in .) :; esac)
: $(case . in (.) :; esac)
: $({ case . in .) :; esac; })
: "$({ case . in .) :; esac; })"
: $(for x in .; do case . in .) :; esac; done)
: "$(for x in .; do case . in .) :; esac; done)"
EOF

-- 
Dan Douglas

signature.asc
Description: This is a digitally signed message part.


Re: Parsing error when "case" in "for" in $()

2012-09-11 Thread Eric Blake
On 09/11/2012 03:31 PM, Steven W. Orr wrote:
>>> Fix:
>>>  Probably by fixing the bash parser.
>>
>> Balance the parentheses in the case statement:
>>
>> echo $(for x in whatever; do case y in (*) echo 42;; esac; done)
>>
> 
> Thanks. I didn't know that the opening paren was optional and was needed
> in such a case as a disambiguator. Very nice. And if you really want to
> match something that starts with an open paren, just backslash it.
> 
> As a style issue, it makes me wonder if I should always use the optional
> open paren as syntactic sugar...

POSIX has always required an optional open paren to case patterns,
thanks to ksh; but it hasn't been portable to all shells until recently
(among others, Solaris /bin/sh will fail if you try it, but then again,
that's not a POSIX shell).

-- 
Eric Blake   ebl...@redhat.com+1-919-301-3266
Libvirt virtualization library http://libvirt.org



signature.asc
Description: OpenPGP digital signature


Re: Parsing error when "case" in "for" in $()

2012-09-11 Thread Eric Blake
On 09/11/2012 08:50 AM, Benoit Vaugon wrote:

> Bash Version: 4.1
> Patch Level: 7

> Repeat-By:
>   echo $(for x in whatever; do case y in *) echo 42;; esac; done)

The syntax error is still present in bash 4.2 patchlevel 37:

$  echo $(for x in whatever; do case y in *) echo 42;; esac; done)
bash: syntax error near unexpected token `;;'
$ bash --version | head -n1
GNU bash, version 4.2.37(1)-release (x86_64-redhat-linux-gnu)

and also present in very recent ksh and zsh:

# ksh -c 'echo $(for x in whatever; do case y in *) echo 42;; esac; done) '
ksh: syntax error at line 1: `;;' unexpected

but not in mksh or dash:

# dash -c 'echo $(for x in whatever; do case y in *) echo 42;; esac; done) '
42

Looks like you found a real bug, but a tough one to fix if even ksh gets
it wrong.

-- 
Eric Blake   ebl...@redhat.com+1-919-301-3266
Libvirt virtualization library http://libvirt.org



signature.asc
Description: OpenPGP digital signature


Re: Parsing error when "case" in "for" in $()

2012-09-11 Thread Steven W. Orr

On 09/11/12 17:20, quoth Chris F.A. Johnson:

On Tue, 11 Sep 2012, Benoit Vaugon wrote:
...

Description:
 Cannot use "case" construction in a "for" loop in a $() sub shell.
 Should work but produces parsing error.

Repeat-By:
 echo $(for x in whatever; do case y in *) echo 42;; esac; done)


The closing parentheses in the case statement is being interpreted as the
closing for $(


Fix:
 Probably by fixing the bash parser.


Balance the parentheses in the case statement:

echo $(for x in whatever; do case y in (*) echo 42;; esac; done)



Thanks. I didn't know that the opening paren was optional and was needed in 
such a case as a disambiguator. Very nice. And if you really want to match 
something that starts with an open paren, just backslash it.


As a style issue, it makes me wonder if I should always use the optional open 
paren as syntactic sugar...


--
Time flies like the wind. Fruit flies like a banana. Stranger things have  .0.
happened but none stranger than this. Does your driver's license say Organ ..0
Donor?Black holes are where God divided by zero. Listen to me! We are all- 000
individuals! What if this weren't a hypothetical question?
steveo at syslang.net





Re: Parsing error when "case" in "for" in $()

2012-09-11 Thread Chris F.A. Johnson

On Tue, 11 Sep 2012, Benoit Vaugon wrote:
...

Description:
 Cannot use "case" construction in a "for" loop in a $() sub shell.
 Should work but produces parsing error.

Repeat-By:
 echo $(for x in whatever; do case y in *) echo 42;; esac; done)


   The closing parentheses in the case statement is being interpreted as the
   closing for $(


Fix:
 Probably by fixing the bash parser.


   Balance the parentheses in the case statement:

echo $(for x in whatever; do case y in (*) echo 42;; esac; done)

--
   Chris F.A. Johnson, 
   Author:
   Pro Bash Programming: Scripting the GNU/Linux Shell (2009, Apress)
   Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)



Parsing error when "case" in "for" in $()

2012-09-11 Thread Benoit Vaugon

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' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' 
-DSHELL -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib  -D_GNU_SOURCE 
-DRECYCLES_PIDS -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=i686 -mtune=atom 
-fasynchronous-unwind-tables
uname output: Linux zeugma 2.6.35.14-106.fc14.i686 #1 SMP Wed Nov 23 
13:57:33 UTC 2011 i686 i686 i386 GNU/Linux

Machine Type: i386-redhat-linux-gnu

Bash Version: 4.1
Patch Level: 7
Release Status: release

Description:
  Cannot use "case" construction in a "for" loop in a $() sub shell.
  Should work but produces parsing error.

Repeat-By:
  echo $(for x in whatever; do case y in *) echo 42;; esac; done)

Fix:
  Probably by fixing the bash parser.