hush: support ${VAR:N:-M}
No binary (build failed)
—
(log yok)
| @@ -5723,32 +5723,34 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |
| if (errmsg) | |
| goto arith_err; | |
| debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len); | |
| - | if (len >= 0) { |
| - | if (beg < 0) { |
| - | /* negative beg counts from the end */ |
| - | beg = (arith_t)strlen(val) + beg; |
| - | if (beg < 0) /* ${v: -999999} is "" */ |
| - | beg = len = 0; |
| - | } |
| - | debug_printf_varexp("from val:'%s'\n", val); |
| - | if (len == 0 || !val || beg >= strlen(val)) { |
| + | if (beg < 0) { |
| + | /* negative beg counts from the end */ |
| + | beg = (arith_t)strlen(val) + beg; |
| + | if (beg < 0) /* ${v: -999999} is "" */ |
| + | beg = len = 0; |
| + | } |
| + | debug_printf_varexp("from val:'%s'\n", val); |
| + | if (len < 0) { |
| + | /* in bash, len=-n means strlen()-n */ |
| + | len = (arith_t)strlen(val) - beg + len; |
| + | if (len < 0) /* bash compat */ |
| + | die_if_script("%s: substring expression < 0", var); |
| + | } |
| + | if (len == 0 || !val || beg >= strlen(val)) { |
| arith_err: | |
| - | val = NULL; |
| - | } else { |
| - | /* Paranoia. What if user entered 9999999999999 |
| - | * which fits in arith_t but not int? */ |
| - | if (len >= INT_MAX) |
| - | len = INT_MAX; |
| - | val = to_be_freed = xstrndup(val + beg, len); |
| - | } |
| - | debug_printf_varexp("val:'%s'\n", val); |
| - | } else |
| - | //TODO: in bash, len=-n means strlen()-n |
| - | #endif /* HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH */ |
| - | { |
| - | die_if_script("malformed ${%s:...}", var); |
| val = NULL; | |
| + | } else { |
| + | /* Paranoia. What if user entered 9999999999999 |
| + | * which fits in arith_t but not int? */ |
| + | if (len >= INT_MAX) |
| + | len = INT_MAX; |
| + | val = to_be_freed = xstrndup(val + beg, len); |
| } | |
| + | debug_printf_varexp("val:'%s'\n", val); |
| + | #else /* not (HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH) */ |
| + | die_if_script("malformed ${%s:...}", var); |
| + | val = NULL; |
| + | #endif |
| } else { /* one of "-=+?" */ | |
| /* Standard-mandated substitution ops: | |
| * ${var?word} - indicate error if unset | |
| @@ -0,0 +1,23 @@ | |
| + | all |0123456 |
| + | 4: |456 |
| + | 4:2 |45 |
| + | 4:-1 |45 |
| + | 4:-2 |4 |
| + | 4:-3 | |
| + | -4: |3456 |
| + | -4:2 |34 |
| + | -4:-1 |345 |
| + | -4:-2 |34 |
| + | -4:-3 |3 |
| + | -4:-4 | |
| + | -4:i=2 |34 |
| + | -4:i=-2|34 |
| + | -4:i=-3|3 |
| + | -4:i=-4| |
| + | -5: |23456 |
| + | -6: |123456 |
| + | -7: |0123456 |
| + | -8: | |
| + | -9: | |
| + | -9:-99 | |
| + | Ok:0 |
| @@ -0,0 +1,24 @@ | |
| + | set -- 0123456 |
| + | echo "all |"$1 |
| + | echo "4: |"${1:4} |
| + | echo "4:2 |"${1:4:2} |
| + | echo "4:-1 |"${1:4:-1} |
| + | echo "4:-2 |"${1:4:-2} |
| + | echo "4:-3 |"${1:4:-3} |
| + | echo "-4: |"${1: -4} |
| + | echo "-4:2 |"${1: -4:2} |
| + | echo "-4:-1 |"${1: -4:-1} |
| + | echo "-4:-2 |"${1: -4:-2} |
| + | echo "-4:-3 |"${1: -4:-3} |
| + | echo "-4:-4 |"${1: -4:-4} |
| + | i=2; echo "-4:i=2 |"${1: -4:i} |
| + | i=-2; echo "-4:i=-2|"${1: -4:i} |
| + | i=-3; echo "-4:i=-3|"${1: -4:i} |
| + | i=-4; echo "-4:i=-4|"${1: -4:i} |
| + | echo "-5: |"${1: -5} |
| + | echo "-6: |"${1: -6} |
| + | echo "-7: |"${1: -7} |
| + | echo "-8: |"${1: -8} |
| + | echo "-9: |"${1: -9} |
| + | echo "-9:-99 |"${1: -9:-99} |
| + | echo Ok:$? |