Add variable expand ranges

echo $PATH[-1..1] #now works

Add tests for ranges
This commit is contained in:
maxfl 2012-07-08 09:19:11 +08:00
parent c0e996acf8
commit 5f05756e65
6 changed files with 61 additions and 35 deletions

View file

@ -727,7 +727,7 @@ void expand_variable_error( parser_t &parser, const wchar_t *token, int token_po
/** /**
Parse an array slicing specification Parse an array slicing specification
*/ */
static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector<long> &idx, int size=-1 ) static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector<long> &idx, int size )
{ {
wchar_t *end; wchar_t *end;
@ -757,6 +757,7 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector<long>
} }
// debug( 0, L"Push idx %d", tmp ); // debug( 0, L"Push idx %d", tmp );
long i1 = tmp>-1 ? tmp : size+tmp+1;
pos = end-in; pos = end-in;
if ( in[pos]==L'.' && in[pos+1]==L'.' ){ if ( in[pos]==L'.' && in[pos+1]==L'.' ){
pos+=2; pos+=2;
@ -767,23 +768,19 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector<long>
} }
pos = end-in; pos = end-in;
if ( size>-1 ) { // debug( 0, L"Push range %d %d", tmp, tmp1 );
// debug( 0, L"Push range idx %d %d", tmp, tmp1 ); long i2 = tmp1>-1 ? tmp1 : size+tmp1+1;
long i1 = tmp>-1 ? tmp : size+tmp+1; // debug( 0, L"Push range idx %d %d", i1, i2 );
long i2 = tmp1>-1 ? tmp1 : size+tmp1+1; short direction = i2<i1 ? -1 : 1 ;
// debug( 0, L"Push range idx %d %d", i1, i2 ); for (long jjj = i1; jjj*direction <= i2*direction; jjj+=direction) {
short direction = i2<i1 ? -1 : 1 ; // debug(0, L"Expand range [subst]: %i\n", jjj);
for (long jjj = i1; jjj*direction <= i2*direction; jjj+=direction) { idx.push_back( jjj );
// debug(0, L"Expand range [subst]: %i\n", jjj);
idx.push_back( jjj );
}
} }
continue; continue;
} }
// debug( 0, L"Push idx %d", tmp ); // debug( 0, L"Push idx %d", tmp );
idx.push_back(tmp); idx.push_back( i1 );
// idx.push_back(tmp2);
} }
if( end_ptr ) if( end_ptr )
@ -875,25 +872,26 @@ static int expand_variables_internal( parser_t &parser, wchar_t * const in, std:
int all_vars=1; int all_vars=1;
wcstring_list_t var_item_list; wcstring_list_t var_item_list;
if( in[stop_pos] == L'[' )
{
wchar_t *slice_end;
all_vars=0;
if( parse_slice( in + stop_pos, &slice_end, var_idx_list ) )
{
parser.error( SYNTAX_ERROR,
-1,
L"Invalid index value" );
is_ok = 0;
}
stop_pos = (slice_end-in);
}
if( is_ok ) if( is_ok )
{ {
tokenize_variable_array( var_val.c_str(), var_item_list ); tokenize_variable_array( var_val.c_str(), var_item_list );
if( in[stop_pos] == L'[' )
{
wchar_t *slice_end;
all_vars=0;
if( parse_slice( in + stop_pos, &slice_end, var_idx_list, var_item_list.size() ) )
{
parser.error( SYNTAX_ERROR,
-1,
L"Invalid index value" );
is_ok = 0;
break;
}
stop_pos = (slice_end-in);
}
if( !all_vars ) if( !all_vars )
{ {
wcstring_list_t string_values(var_idx_list.size()); wcstring_list_t string_values(var_idx_list.size());
@ -901,11 +899,6 @@ static int expand_variables_internal( parser_t &parser, wchar_t * const in, std:
for( size_t j=0; j<var_idx_list.size(); j++) for( size_t j=0; j<var_idx_list.size(); j++)
{ {
long tmp = var_idx_list.at(j); long tmp = var_idx_list.at(j);
if( tmp < 0 )
{
tmp = ((long)var_item_list.size())+tmp+1;
}
/* /*
Check that we are within array Check that we are within array
bounds. If not, truncate the list to bounds. If not, truncate the list to
@ -1224,10 +1217,11 @@ static int expand_cmdsubst( parser_t &parser, const wcstring &input, std::vector
long idx = slice_idx.at(i); long idx = slice_idx.at(i);
if( idx < 1 || (size_t)idx > sub_res.size() ) if( idx < 1 || (size_t)idx > sub_res.size() )
{ {
parser.error( SYNTAX_ERROR, -1, L"Invalid index value" ); parser.error( SYNTAX_ERROR,
-1,
ARRAY_BOUNDS_ERR );
return 0; return 0;
} }
idx = idx-1; idx = idx-1;
sub_res2.push_back(sub_res.at(idx)); sub_res2.push_back(sub_res.at(idx));

0
tests/test8.err Normal file
View file

21
tests/test8.in Normal file
View file

@ -0,0 +1,21 @@
# Test index ranges
# Test variable expand
set test (seq 10)
echo $test[1..10] # normal range
echo $test[10..1] # inverted range
echo $test[2..5 8..6] # several ranges
echo $test[-1..-2] # range with negative limits
echo $test[-1..1] # range with mixed limits
# Test variable set
set test1 $test
set test1[-1..1] $test # reverse variable
echo $echo $test1
set test1[2..4 -2..-4] $test1[4..2 -4..-2]
echo $test1
# Test command substitution
echo (seq 5)[-1..1]
echo (seq 10)[3..5 -2..2]

9
tests/test8.out Normal file
View file

@ -0,0 +1,9 @@
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
2 3 4 5 8 7 6
10 9
10 9 8 7 6 5 4 3 2 1
10 9 8 7 6 5 4 3 2 1
10 7 8 9 6 5 2 3 4 1
5 4 3 2 1
3 4 5 9 8 7 6 5 4 3 2

1
tests/test8.status Normal file
View file

@ -0,0 +1 @@
0

View file

@ -6,3 +6,4 @@ File test4.in tested ok
File test5.in tested ok File test5.in tested ok
File test6.in tested ok File test6.in tested ok
File test7.in tested ok File test7.in tested ok
File test8.in tested ok