diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-17 17:49:11 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-17 17:49:11 +0200 |
commit | 826360ff238eb23191950dd4c5051195eab9733a (patch) | |
tree | d9dbd7da77e985e181af0b8ad406d467379b498b /shell/ash.c | |
parent | 4f8079de877cf2b7206e4cabaf465fb7d8cc4f62 (diff) | |
download | busybox-w32-826360ff238eb23191950dd4c5051195eab9733a.tar.gz busybox-w32-826360ff238eb23191950dd4c5051195eab9733a.tar.bz2 busybox-w32-826360ff238eb23191950dd4c5051195eab9733a.zip |
ash: more general format ${var:EXPR:EXPR}
function old new delta
subevalvar 1171 1202 +31
localcmd 364 366 +2
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/shell/ash.c b/shell/ash.c index eb5156bea..aaf0561b8 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -6612,7 +6612,6 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6612 | char *loc; | 6612 | char *loc; |
6613 | char *rmesc, *rmescend; | 6613 | char *rmesc, *rmescend; |
6614 | char *str; | 6614 | char *str; |
6615 | IF_BASH_SUBSTR(int pos, len, orig_len;) | ||
6616 | int amount, resetloc; | 6615 | int amount, resetloc; |
6617 | IF_BASH_PATTERN_SUBST(int workloc;) | 6616 | IF_BASH_PATTERN_SUBST(int workloc;) |
6618 | IF_BASH_PATTERN_SUBST(char *repl = NULL;) | 6617 | IF_BASH_PATTERN_SUBST(char *repl = NULL;) |
@@ -6641,14 +6640,23 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6641 | /* NOTREACHED */ | 6640 | /* NOTREACHED */ |
6642 | 6641 | ||
6643 | #if BASH_SUBSTR | 6642 | #if BASH_SUBSTR |
6644 | case VSSUBSTR: | 6643 | case VSSUBSTR: { |
6645 | //TODO: support more general format ${v:EXPR:EXPR}, | 6644 | int pos, len, orig_len; |
6646 | // where EXPR follows $(()) rules | 6645 | char *colon; |
6646 | |||
6647 | loc = str = stackblock() + strloc; | 6647 | loc = str = stackblock() + strloc; |
6648 | |||
6649 | # if !ENABLE_FEATURE_SH_MATH | ||
6650 | # define ash_arith number | ||
6651 | # endif | ||
6648 | /* Read POS in ${var:POS:LEN} */ | 6652 | /* Read POS in ${var:POS:LEN} */ |
6649 | pos = atoi(loc); /* number(loc) errors out on "1:4" */ | 6653 | colon = strchr(loc, ':'); |
6650 | len = str - startp - 1; | 6654 | if (colon) *colon = '\0'; |
6655 | pos = ash_arith(loc); | ||
6656 | if (colon) *colon = ':'; | ||
6651 | 6657 | ||
6658 | /* Read LEN in ${var:POS:LEN} */ | ||
6659 | len = str - startp - 1; | ||
6652 | /* *loc != '\0', guaranteed by parser */ | 6660 | /* *loc != '\0', guaranteed by parser */ |
6653 | if (quotes) { | 6661 | if (quotes) { |
6654 | char *ptr; | 6662 | char *ptr; |
@@ -6662,26 +6670,21 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6662 | } | 6670 | } |
6663 | } | 6671 | } |
6664 | orig_len = len; | 6672 | orig_len = len; |
6665 | |||
6666 | if (*loc++ == ':') { | 6673 | if (*loc++ == ':') { |
6667 | /* ${var::LEN} */ | 6674 | /* ${var::LEN} */ |
6668 | len = number(loc); | 6675 | len = ash_arith(loc); |
6669 | } else { | 6676 | } else { |
6670 | /* Skip POS in ${var:POS:LEN} */ | 6677 | /* Skip POS in ${var:POS:LEN} */ |
6671 | len = orig_len; | 6678 | len = orig_len; |
6672 | while (*loc && *loc != ':') { | 6679 | while (*loc && *loc != ':') { |
6673 | /* TODO? | ||
6674 | * bash complains on: var=qwe; echo ${var:1a:123} | ||
6675 | if (!isdigit(*loc)) | ||
6676 | ash_msg_and_raise_error(msg_illnum, str); | ||
6677 | */ | ||
6678 | loc++; | 6680 | loc++; |
6679 | } | 6681 | } |
6680 | if (*loc++ == ':') { | 6682 | if (*loc++ == ':') { |
6681 | len = number(loc); | 6683 | len = ash_arith(loc); |
6682 | } | 6684 | } |
6683 | //TODO: number() chokes on "-n". In bash, LEN=-n means strlen()-n | ||
6684 | } | 6685 | } |
6686 | # undef ash_arith | ||
6687 | |||
6685 | if (pos < 0) { | 6688 | if (pos < 0) { |
6686 | /* ${VAR:$((-n)):l} starts n chars from the end */ | 6689 | /* ${VAR:$((-n)):l} starts n chars from the end */ |
6687 | pos = orig_len + pos; | 6690 | pos = orig_len + pos; |
@@ -6689,12 +6692,16 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6689 | if ((unsigned)pos >= orig_len) { | 6692 | if ((unsigned)pos >= orig_len) { |
6690 | /* apart from obvious ${VAR:999999:l}, | 6693 | /* apart from obvious ${VAR:999999:l}, |
6691 | * covers ${VAR:$((-9999999)):l} - result is "" | 6694 | * covers ${VAR:$((-9999999)):l} - result is "" |
6692 | * (bash-compat) | 6695 | * (bash compat) |
6693 | */ | 6696 | */ |
6694 | pos = 0; | 6697 | pos = 0; |
6695 | len = 0; | 6698 | len = 0; |
6696 | } | 6699 | } |
6697 | if (len > (orig_len - pos)) | 6700 | if (len < 0) { |
6701 | /* ${VAR:N:-M} sets LEN to strlen()-M */ | ||
6702 | len = (orig_len - pos) + len; | ||
6703 | } | ||
6704 | if ((unsigned)len > (orig_len - pos)) | ||
6698 | len = orig_len - pos; | 6705 | len = orig_len - pos; |
6699 | 6706 | ||
6700 | for (str = startp; pos; str++, pos--) { | 6707 | for (str = startp; pos; str++, pos--) { |
@@ -6710,6 +6717,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6710 | amount = loc - expdest; | 6717 | amount = loc - expdest; |
6711 | STADJUST(amount, expdest); | 6718 | STADJUST(amount, expdest); |
6712 | return loc; | 6719 | return loc; |
6720 | } | ||
6713 | #endif /* BASH_SUBSTR */ | 6721 | #endif /* BASH_SUBSTR */ |
6714 | } | 6722 | } |
6715 | 6723 | ||
@@ -6754,6 +6762,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6754 | #if BASH_PATTERN_SUBST | 6762 | #if BASH_PATTERN_SUBST |
6755 | workloc = expdest - (char *)stackblock(); | 6763 | workloc = expdest - (char *)stackblock(); |
6756 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { | 6764 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { |
6765 | int len; | ||
6757 | char *idx, *end; | 6766 | char *idx, *end; |
6758 | 6767 | ||
6759 | if (!repl) { | 6768 | if (!repl) { |