diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-17 16:46:57 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-17 16:46:57 +0200 |
commit | e32b6503e75d5bcbf8ffff69cafb09523ff2b482 (patch) | |
tree | d0d68a95f68d55215b86f792e11e89b1e75b1ed1 | |
parent | 203fd7bc66b869e5022ad33d26065e69eaaaf66b (diff) | |
download | busybox-w32-e32b6503e75d5bcbf8ffff69cafb09523ff2b482.tar.gz busybox-w32-e32b6503e75d5bcbf8ffff69cafb09523ff2b482.tar.bz2 busybox-w32-e32b6503e75d5bcbf8ffff69cafb09523ff2b482.zip |
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>
-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 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 | |||
5723 | if (errmsg) | 5723 | if (errmsg) |
5724 | goto arith_err; | 5724 | goto arith_err; |
5725 | debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len); | 5725 | debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len); |
5726 | if (len >= 0) { | 5726 | if (beg < 0) { |
5727 | if (beg < 0) { | 5727 | /* negative beg counts from the end */ |
5728 | /* negative beg counts from the end */ | 5728 | beg = (arith_t)strlen(val) + beg; |
5729 | beg = (arith_t)strlen(val) + beg; | 5729 | if (beg < 0) /* ${v: -999999} is "" */ |
5730 | if (beg < 0) /* ${v: -999999} is "" */ | 5730 | beg = len = 0; |
5731 | beg = len = 0; | 5731 | } |
5732 | } | 5732 | debug_printf_varexp("from val:'%s'\n", val); |
5733 | debug_printf_varexp("from val:'%s'\n", val); | 5733 | if (len < 0) { |
5734 | if (len == 0 || !val || beg >= strlen(val)) { | 5734 | /* in bash, len=-n means strlen()-n */ |
5735 | len = (arith_t)strlen(val) - beg + len; | ||
5736 | if (len < 0) /* bash compat */ | ||
5737 | die_if_script("%s: substring expression < 0", var); | ||
5738 | } | ||
5739 | if (len == 0 || !val || beg >= strlen(val)) { | ||
5735 | arith_err: | 5740 | arith_err: |
5736 | val = NULL; | ||
5737 | } else { | ||
5738 | /* Paranoia. What if user entered 9999999999999 | ||
5739 | * which fits in arith_t but not int? */ | ||
5740 | if (len >= INT_MAX) | ||
5741 | len = INT_MAX; | ||
5742 | val = to_be_freed = xstrndup(val + beg, len); | ||
5743 | } | ||
5744 | debug_printf_varexp("val:'%s'\n", val); | ||
5745 | } else | ||
5746 | //TODO: in bash, len=-n means strlen()-n | ||
5747 | #endif /* HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH */ | ||
5748 | { | ||
5749 | die_if_script("malformed ${%s:...}", var); | ||
5750 | val = NULL; | 5741 | val = NULL; |
5742 | } else { | ||
5743 | /* Paranoia. What if user entered 9999999999999 | ||
5744 | * which fits in arith_t but not int? */ | ||
5745 | if (len >= INT_MAX) | ||
5746 | len = INT_MAX; | ||
5747 | val = to_be_freed = xstrndup(val + beg, len); | ||
5751 | } | 5748 | } |
5749 | debug_printf_varexp("val:'%s'\n", val); | ||
5750 | #else /* not (HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH) */ | ||
5751 | die_if_script("malformed ${%s:...}", var); | ||
5752 | val = NULL; | ||
5753 | #endif | ||
5752 | } else { /* one of "-=+?" */ | 5754 | } else { /* one of "-=+?" */ |
5753 | /* Standard-mandated substitution ops: | 5755 | /* Standard-mandated substitution ops: |
5754 | * ${var?word} - indicate error if unset | 5756 | * ${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 @@ | |||
1 | all |0123456 | ||
2 | 4: |456 | ||
3 | 4:2 |45 | ||
4 | 4:-1 |45 | ||
5 | 4:-2 |4 | ||
6 | 4:-3 | | ||
7 | -4: |3456 | ||
8 | -4:2 |34 | ||
9 | -4:-1 |345 | ||
10 | -4:-2 |34 | ||
11 | -4:-3 |3 | ||
12 | -4:-4 | | ||
13 | -4:i=2 |34 | ||
14 | -4:i=-2|34 | ||
15 | -4:i=-3|3 | ||
16 | -4:i=-4| | ||
17 | -5: |23456 | ||
18 | -6: |123456 | ||
19 | -7: |0123456 | ||
20 | -8: | | ||
21 | -9: | | ||
22 | -9:-99 | | ||
23 | 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 @@ | |||
1 | set -- 0123456 | ||
2 | echo "all |"$1 | ||
3 | echo "4: |"${1:4} | ||
4 | echo "4:2 |"${1:4:2} | ||
5 | echo "4:-1 |"${1:4:-1} | ||
6 | echo "4:-2 |"${1:4:-2} | ||
7 | echo "4:-3 |"${1:4:-3} | ||
8 | echo "-4: |"${1: -4} | ||
9 | echo "-4:2 |"${1: -4:2} | ||
10 | echo "-4:-1 |"${1: -4:-1} | ||
11 | echo "-4:-2 |"${1: -4:-2} | ||
12 | echo "-4:-3 |"${1: -4:-3} | ||
13 | echo "-4:-4 |"${1: -4:-4} | ||
14 | i=2; echo "-4:i=2 |"${1: -4:i} | ||
15 | i=-2; echo "-4:i=-2|"${1: -4:i} | ||
16 | i=-3; echo "-4:i=-3|"${1: -4:i} | ||
17 | i=-4; echo "-4:i=-4|"${1: -4:i} | ||
18 | echo "-5: |"${1: -5} | ||
19 | echo "-6: |"${1: -6} | ||
20 | echo "-7: |"${1: -7} | ||
21 | echo "-8: |"${1: -8} | ||
22 | echo "-9: |"${1: -9} | ||
23 | echo "-9:-99 |"${1: -9:-99} | ||
24 | echo Ok:$? | ||