hush: fix more obscure ${var%...} cases

function                                             old     new   delta
add_till_closing_paren                               313     359     +46
builtin_exit                                          48      47      -1

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2010-05-22 00:26:06 +02:00
parent 7436950a75
commit a6ad397ea9
5 changed files with 45 additions and 24 deletions

View File

@ -45,6 +45,8 @@
* follow IFS rules more precisely, including update semantics * follow IFS rules more precisely, including update semantics
* builtins mandated by standards we don't support: * builtins mandated by standards we don't support:
* [un]alias, command, fc, getopts, newgrp, readonly, times * [un]alias, command, fc, getopts, newgrp, readonly, times
* make complex ${var%...} constructs support optional
* make here documents optional
* *
* Bash compat TODO: * Bash compat TODO:
* redirection of stdout+stderr: &> and >& * redirection of stdout+stderr: &> and >&
@ -5887,36 +5889,36 @@ static void add_till_backquote(o_string *dest, struct in_str *input)
* echo $(echo 'TEST)' BEST) TEST) BEST * echo $(echo 'TEST)' BEST) TEST) BEST
* echo $(echo \(\(TEST\) BEST) ((TEST) BEST * echo $(echo \(\(TEST\) BEST) ((TEST) BEST
* *
* BUG: enter: echo $(( `printf '(\x28 1'` + `echo 2))` )) * Also adapted to eat ${var%...} constructs, since ... part
* on the command line, press Enter. You get > prompt which is impossible * can contain arbitrary constructs, just like $(cmd).
* to exit with ^C.
*/ */
#define DOUBLE_CLOSE_CHAR_FLAG 0x80 #define DOUBLE_CLOSE_CHAR_FLAG 0x80
static void add_till_closing_paren(o_string *dest, struct in_str *input, char end_ch) static void add_till_closing_paren(o_string *dest, struct in_str *input, char end_ch)
{ {
int count = 0;
char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG; char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG;
end_ch &= (DOUBLE_CLOSE_CHAR_FLAG-1); end_ch &= (DOUBLE_CLOSE_CHAR_FLAG-1);
while (1) { while (1) {
int ch = i_getch(input); int ch = i_getch(input);
if (ch == EOF) { if (ch == EOF) {
syntax_error_unterm_ch(')'); syntax_error_unterm_ch(end_ch);
/*xfunc_die(); - redundant */ /*xfunc_die(); - redundant */
} }
if (ch == '(' || ch == '{') if (ch == end_ch) {
count++;
if (ch == ')' || ch == '}') {
count--;
if (count < 0 && ch == end_ch) {
if (!dbl) if (!dbl)
break; break;
if (i_peek(input) == ')') { /* we look for closing )) of $((EXPR)) */
i_getch(input); if (i_peek(input) == end_ch) {
i_getch(input); /* eat second ')' */
break; break;
} }
} }
}
o_addchr(dest, ch); o_addchr(dest, ch);
if (ch == '(' || ch == '{') {
ch = (ch == '(' ? ')' : '}');
add_till_closing_paren(dest, input, ch);
o_addchr(dest, ch);
continue;
}
if (ch == '\'') { if (ch == '\'') {
add_till_single_quote(dest, input); add_till_single_quote(dest, input);
o_addchr(dest, ch); o_addchr(dest, ch);
@ -5927,6 +5929,11 @@ static void add_till_closing_paren(o_string *dest, struct in_str *input, char en
o_addchr(dest, ch); o_addchr(dest, ch);
continue; continue;
} }
if (ch == '`') {
add_till_backquote(dest, input);
o_addchr(dest, ch);
continue;
}
if (ch == '\\') { if (ch == '\\') {
/* \x. Copy verbatim. Important for \(, \) */ /* \x. Copy verbatim. Important for \(, \) */
ch = i_getch(input); ch = i_getch(input);

View File

@ -43,21 +43,30 @@ Format: 'expected actual'
4 4 4 4
29 29 29 29
5 5 5 5
unary plus, minus
-4 -4 -4 -4
4 4 4 4
conditional expressions
1 1 1 1
32 32 32 32
32 32 32 32
1 1 1 1
1 1 1 1
32 32 32 32
check that parentheses in `cmd` are interpreted correctly
3 3
check that the unevaluated part of the ternary operator does not do evaluation or assignment
20 20 20 20
30 30 30 30
20 20 20 20
30 30 30 30
check precedence of assignment vs. conditional operator
hush: error in arithmetic hush: error in arithmetic
check precedence of assignment vs. conditional operator
associativity of assignment-operator operator
6 6 6 6
6,5,3 6,5,3 6,5,3 6,5,3
octal, hex
263 263 263 263
255 255 255 255
40 40 40 40

View File

@ -75,11 +75,11 @@ echo 4 $(( iv &= 4 ))
echo 29 $(( iv += (jv + 9))) echo 29 $(( iv += (jv + 9)))
echo 5 $(( (iv + 4) % 7 )) echo 5 $(( (iv + 4) % 7 ))
# unary plus, minus echo unary plus, minus
echo -4 $(( +4 - 8 )) echo -4 $(( +4 - 8 ))
echo 4 $(( -4 + 8 )) echo 4 $(( -4 + 8 ))
# conditional expressions echo conditional expressions
echo 1 $(( 4<5 ? 1 : 32)) echo 1 $(( 4<5 ? 1 : 32))
echo 32 $(( 4>5 ? 1 : 32)) echo 32 $(( 4>5 ? 1 : 32))
echo 32 $(( 4>(2+3) ? 1 : 32)) echo 32 $(( 4>(2+3) ? 1 : 32))
@ -87,8 +87,11 @@ echo 1 $(( 4<(2+3) ? 1 : 32))
echo 1 $(( (2+2)<(2+3) ? 1 : 32)) echo 1 $(( (2+2)<(2+3) ? 1 : 32))
echo 32 $(( (2+2)>(2+3) ? 1 : 32)) echo 32 $(( (2+2)>(2+3) ? 1 : 32))
# check that the unevaluated part of the ternary operator does not do echo 'check that parentheses in `cmd` are interpreted correctly'
# evaluation or assignment # \x28 is '('
echo 3 $(( ( `printf '(\x28 1'` + `echo 2\)\)` ) ))
echo check that the unevaluated part of the ternary operator does not do evaluation or assignment
x=i+=2 x=i+=2
y=j+=2 y=j+=2
#ash# declare -i i=1 j=1 #ash# declare -i i=1 j=1
@ -109,20 +112,20 @@ echo 20 $((1 ? 20 : (x+=2)))
echo 30 $((0 ? (y+=2) : 30)) echo 30 $((0 ? (y+=2) : 30))
#ash# echo $i,$y # ash mishandles this #ash# echo $i,$y # ash mishandles this
# check precedence of assignment vs. conditional operator echo check precedence of assignment vs. conditional operator
# should be an error # should be an error
#ash# declare -i x=2 #ash# declare -i x=2
x=2 x=2
#ashnote# bash reports error but continues, ash aborts - using subshell to 'emulate' bash: #ashnote# bash reports error but continues, ash aborts - using subshell to 'emulate' bash:
( y=$((1 ? 20 : x+=2)) ) ( y=$((1 ? 20 : x+=2)) )
# check precedence of assignment vs. conditional operator echo check precedence of assignment vs. conditional operator
#ash# declare -i x=2 #ash# declare -i x=2
x=2 x=2
# ash says "line NNN: syntax error: 0 ? x+=2 : 20" # ash says "line NNN: syntax error: 0 ? x+=2 : 20"
#ash# echo 20 $((0 ? x+=2 : 20)) #ash# echo 20 $((0 ? x+=2 : 20))
# associativity of assignment-operator operator echo associativity of assignment-operator operator
#ash# declare -i i=1 j=2 k=3 #ash# declare -i i=1 j=2 k=3
i=1 i=1
j=2 j=2
@ -130,7 +133,7 @@ k=3
echo 6 $((i += j += k)) echo 6 $((i += j += k))
echo 6,5,3 $i,$j,$k echo 6,5,3 $i,$j,$k
# octal, hex echo octal, hex
echo 263 $(( 0x100 | 007 )) echo 263 $(( 0x100 | 007 ))
echo 255 $(( 0xff )) echo 255 $(( 0xff ))
#ash# echo 255 $(( 16#ff )) #ash# echo 255 $(( 16#ff ))

View File

@ -37,4 +37,5 @@ ababcdcd_tail
ababcdcd ababcdcd
ab ab
ab ab
ab
End End

View File

@ -47,5 +47,6 @@ echo ${var%\\*}
a=ab}; echo ${a%\}}; a=ab}; echo ${a%\}};
a=abc; c=c; echo ${a%${c}} a=abc; c=c; echo ${a%${c}}
a=ab{{c; echo ${a%`echo {{c`}
echo End echo End