diff --git a/builtin_set.cpp b/builtin_set.cpp index 5915e91d2..57b477594 100644 --- a/builtin_set.cpp +++ b/builtin_set.cpp @@ -238,9 +238,31 @@ static int parse_index( std::vector &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 &idx ) +static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector &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 } // 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 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)); diff --git a/tests/test8.err b/tests/test8.err new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test8.in b/tests/test8.in new file mode 100644 index 000000000..c3c733848 --- /dev/null +++ b/tests/test8.in @@ -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)] diff --git a/tests/test8.out b/tests/test8.out new file mode 100644 index 000000000..72af9bb81 --- /dev/null +++ b/tests/test8.out @@ -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 diff --git a/tests/test8.status b/tests/test8.status new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/tests/test8.status @@ -0,0 +1 @@ +0 diff --git a/tests/top.out b/tests/top.out index 5614a6619..0c7b1103a 100644 --- a/tests/top.out +++ b/tests/top.out @@ -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