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
* builtins mandated by standards we don't support:
* [un]alias, command, fc, getopts, newgrp, readonly, times
* make complex ${var%...} constructs support optional
* make here documents optional
*
* Bash compat TODO:
* 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
*
* BUG: enter: echo $(( `printf '(\x28 1'` + `echo 2))` ))
* on the command line, press Enter. You get > prompt which is impossible
* to exit with ^C.
* Also adapted to eat ${var%...} constructs, since ... part
* can contain arbitrary constructs, just like $(cmd).
*/
#define DOUBLE_CLOSE_CHAR_FLAG 0x80
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;
end_ch &= (DOUBLE_CLOSE_CHAR_FLAG-1);
while (1) {
int ch = i_getch(input);
if (ch == EOF) {
syntax_error_unterm_ch(')');
syntax_error_unterm_ch(end_ch);
/*xfunc_die(); - redundant */
}
if (ch == '(' || ch == '{')
count++;
if (ch == ')' || ch == '}') {
count--;
if (count < 0 && ch == end_ch) {
if (!dbl)
break;
if (i_peek(input) == ')') {
i_getch(input);
break;
}
if (ch == end_ch) {
if (!dbl)
break;
/* we look for closing )) of $((EXPR)) */
if (i_peek(input) == end_ch) {
i_getch(input); /* eat second ')' */
break;
}
}
o_addchr(dest, ch);
if (ch == '(' || ch == '{') {
ch = (ch == '(' ? ')' : '}');
add_till_closing_paren(dest, input, ch);
o_addchr(dest, ch);
continue;
}
if (ch == '\'') {
add_till_single_quote(dest, input);
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);
continue;
}
if (ch == '`') {
add_till_backquote(dest, input);
o_addchr(dest, ch);
continue;
}
if (ch == '\\') {
/* \x. Copy verbatim. Important for \(, \) */
ch = i_getch(input);

View File

@ -43,21 +43,30 @@ Format: 'expected actual'
4 4
29 29
5 5
unary plus, minus
-4 -4
4 4
conditional expressions
1 1
32 32
32 32
1 1
1 1
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
30 30
20 20
30 30
check precedence of assignment vs. conditional operator
hush: error in arithmetic
check precedence of assignment vs. conditional operator
associativity of assignment-operator operator
6 6
6,5,3 6,5,3
octal, hex
263 263
255 255
40 40

View File

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

View File

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

View File

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