diff options
author | Denys Vlasenko | 2017-07-17 16:46:57 +0200 |
---|---|---|
committer | Denys Vlasenko | 2017-07-17 16:46:57 +0200 |
commit | e32b6503e75d5bcbf8ffff69cafb09523ff2b482 (patch) | |
tree | d0d68a95f68d55215b86f792e11e89b1e75b1ed1 /shell | |
parent | 203fd7bc66b869e5022ad33d26065e69eaaaf66b (diff) | |
download | busybox-e32b6503e75d5bcbf8ffff69cafb09523ff2b482.zip busybox-e32b6503e75d5bcbf8ffff69cafb09523ff2b482.tar.gz |
hush: support ${VAR:N:-M}
function old new delta
expand_one_var 1602 1615 +13
builtin_type 114 116 +2
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r-- | shell/hush.c | 48 | ||||
-rw-r--r-- | shell/hush_test/hush-vars/var_bash1b.right | 23 | ||||
-rwxr-xr-x | shell/hush_test/hush-vars/var_bash1b.tests | 24 |
3 files changed, 72 insertions, 23 deletions
diff --git a/shell/hush.c b/shell/hush.c index fd2a3d0..836f3b8 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -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 diff --git a/shell/hush_test/hush-vars/var_bash1b.right b/shell/hush_test/hush-vars/var_bash1b.right new file mode 100644 index 0000000..fafc0f0 --- /dev/null +++ b/shell/hush_test/hush-vars/var_bash1b.right @@ -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 diff --git a/shell/hush_test/hush-vars/var_bash1b.tests b/shell/hush_test/hush-vars/var_bash1b.tests new file mode 100755 index 0000000..efbdef3 --- /dev/null +++ b/shell/hush_test/hush-vars/var_bash1b.tests @@ -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:$? |