Merge branch 'index_range'

This commit is contained in:
ridiculousfish 2012-07-19 10:59:11 -07:00
commit bb4a05032b
7 changed files with 105 additions and 24 deletions

View file

@ -238,9 +238,31 @@ static int parse_index( std::vector<long> &indexes,
l_ind = var_count+l_ind+1;
}
indexes.push_back( l_ind );
src = end;
if ( *src==L'.' && *(src+1)==L'.' ){
src+=2;
long l_ind2 = wcstol( src, &end, 10 );
if( end==src || errno )
{
return 1;
}
src = end;
if( l_ind2 < 0 )
{
l_ind2 = var_count+l_ind2+1;
}
int direction = l_ind2<l_ind ? -1 : 1 ;
for (long jjj = l_ind; jjj*direction <= l_ind2*direction; jjj+=direction) {
// debug(0, L"Expand range [set]: %i\n", jjj);
indexes.push_back( jjj );
count++;
}
}
else {
indexes.push_back( l_ind );
count++;
}
while (iswspace(*src)) src++;
}

View file

@ -875,17 +875,14 @@ void expand_variable_error( parser_t &parser, const wchar_t *token, int token_po
/**
Parse an array slicing specification
*/
static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector<long> &idx )
static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector<long> &idx, int size )
{
wchar_t *end;
int pos = 1;
// debug( 0, L"parse_slice on '%ls'", in );
while( 1 )
{
long tmp;
@ -907,8 +904,34 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector<long>
}
// debug( 0, L"Push idx %d", tmp );
idx.push_back(tmp);
long i1 = tmp>-1 ? tmp : size+tmp+1;
pos = end-in;
while( in[pos]==INTERNAL_SEPARATOR )
pos++;
if ( in[pos]==L'.' && in[pos+1]==L'.' ){
pos+=2;
while( in[pos]==INTERNAL_SEPARATOR )
pos++;
long tmp1 = wcstol( &in[pos], &end, 10 );
if( ( errno ) || ( end == &in[pos] ) )
{
return 1;
}
pos = end-in;
// debug( 0, L"Push range %d %d", tmp, tmp1 );
long i2 = tmp1>-1 ? tmp1 : size+tmp1+1;
// debug( 0, L"Push range idx %d %d", i1, i2 );
short direction = i2<i1 ? -1 : 1 ;
for (long jjj = i1; jjj*direction <= i2*direction; jjj+=direction) {
// debug(0, L"Expand range [subst]: %i\n", jjj);
idx.push_back( jjj );
}
continue;
}
// debug( 0, L"Push idx %d", tmp );
idx.push_back( i1 );
}
if( end_ptr )
@ -1000,25 +1023,26 @@ static int expand_variables_internal( parser_t &parser, wchar_t * const in, std:
int all_vars=1;
wcstring_list_t var_item_list;
if( is_ok )
{
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 ) )
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( is_ok )
{
tokenize_variable_array( var_val.c_str(), var_item_list );
if( !all_vars )
{
wcstring_list_t string_values(var_idx_list.size());
@ -1026,11 +1050,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++)
{
long tmp = var_idx_list.at(j);
if( tmp < 0 )
{
tmp = ((long)var_item_list.size())+tmp+1;
}
/*
Check that we are within array
bounds. If not, truncate the list to
@ -1335,7 +1354,7 @@ static int expand_cmdsubst( parser_t &parser, const wcstring &input, std::vector
std::vector<long> slice_idx;
wchar_t *slice_end;
if( parse_slice( tail_begin, &slice_end, slice_idx ) )
if( parse_slice( tail_begin, &slice_end, slice_idx, sub_res.size() ) )
{
parser.error( SYNTAX_ERROR, -1, L"Invalid index value" );
return 0;
@ -1347,17 +1366,13 @@ static int expand_cmdsubst( parser_t &parser, const wcstring &input, std::vector
for( i=0; i < slice_idx.size(); i++ )
{
long idx = slice_idx.at(i);
if( idx < 0 )
{
idx = sub_res.size() + idx + 1;
}
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;
}
idx = idx-1;
sub_res2.push_back(sub_res.at(idx));

0
tests/test8.err Normal file
View file

25
tests/test8.in Normal file
View file

@ -0,0 +1,25 @@
# Test index ranges
echo Test variable expand
set n 10
set test (seq $n)
echo $test[1..$n] # normal range
echo $test[$n..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
echo Test variable set
set test1 $test
set test1[-1..1] $test; echo $test1
set test1[1..$n] $test; echo $test1
set test1[$n..1] $test; echo $test1
set test1[2..4 -2..-4] $test1[4..2 -4..-2]; echo $test1
echo Test command substitution
echo (seq 5)[-1..1]
echo (seq $n)[3..5 -2..2]
echo Test more
echo $test[(count $test)..1]
echo $test[1..(count $test)]

17
tests/test8.out Normal file
View file

@ -0,0 +1,17 @@
Test variable expand
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
Test variable set
10 9 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
10 7 8 9 6 5 2 3 4 1
Test command substitution
5 4 3 2 1
3 4 5 9 8 7 6 5 4 3 2
Test more
10 9 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9 10

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 test6.in tested ok
File test7.in tested ok
File test8.in tested ok