From e32b6503e75d5bcbf8ffff69cafb09523ff2b482 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Jul 2017 16:46:57 +0200 Subject: 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 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'shell/hush.c') 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 -- cgit v1.2.3