From e32b6503e75d5bcbf8ffff69cafb09523ff2b482 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Jul 2017 16:46:57 +0200 Subject: [PATCH] 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 --- shell/hush.c | 48 +++++++++++----------- shell/hush_test/hush-vars/var_bash1b.right | 23 +++++++++++ shell/hush_test/hush-vars/var_bash1b.tests | 24 +++++++++++ 3 files changed, 72 insertions(+), 23 deletions(-) create mode 100644 shell/hush_test/hush-vars/var_bash1b.right create mode 100755 shell/hush_test/hush-vars/var_bash1b.tests diff --git a/shell/hush.c b/shell/hush.c index fd2a3d0f5..836f3b83c 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 000000000..fafc0f07c --- /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 000000000..efbdef35c --- /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:$? -- 2.25.1