aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--expand.cpp64
-rw-r--r--tests/test8.err0
-rw-r--r--tests/test8.in21
-rw-r--r--tests/test8.out9
-rw-r--r--tests/test8.status1
-rw-r--r--tests/top.out1
6 files changed, 61 insertions, 35 deletions
diff --git a/expand.cpp b/expand.cpp
index ab75a40a..c370725a 100644
--- a/expand.cpp
+++ b/expand.cpp
@@ -727,7 +727,7 @@ 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, int size=-1 )
+static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector<long> &idx, int size )
{
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 );
+ long i1 = tmp>-1 ? tmp : size+tmp+1;
pos = end-in;
if ( in[pos]==L'.' && in[pos+1]==L'.' ){
pos+=2;
@@ -767,23 +768,19 @@ static int parse_slice( const wchar_t *in, wchar_t **end_ptr, std::vector<long>
}
pos = end-in;
- if ( size>-1 ) {
- // debug( 0, L"Push range idx %d %d", tmp, tmp1 );
- long i1 = tmp>-1 ? tmp : size+tmp+1;
- 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 );
- }
+ // 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(tmp);
- // idx.push_back(tmp2);
+ idx.push_back( i1 );
}
if( end_ptr )
@@ -875,25 +872,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( 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 )
{
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 )
{
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++)
{
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
@@ -1224,10 +1217,11 @@ static int expand_cmdsubst( parser_t &parser, const wcstring &input, std::vector
long idx = slice_idx.at(i);
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 00000000..e69de29b
--- /dev/null
+++ b/tests/test8.err
diff --git a/tests/test8.in b/tests/test8.in
new file mode 100644
index 00000000..e03d9d05
--- /dev/null
+++ b/tests/test8.in
@@ -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]
+
diff --git a/tests/test8.out b/tests/test8.out
new file mode 100644
index 00000000..e118e572
--- /dev/null
+++ b/tests/test8.out
@@ -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
diff --git a/tests/test8.status b/tests/test8.status
new file mode 100644
index 00000000..573541ac
--- /dev/null
+++ b/tests/test8.status
@@ -0,0 +1 @@
+0
diff --git a/tests/top.out b/tests/top.out
index 5614a661..0c7b1103 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