diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-01-09 17:01:00 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-01-09 17:07:06 +0100 |
commit | 740058b42bbfdab225706f8284e8d72b74a5df3b (patch) | |
tree | d910fbfe111ddfb761315d9fa2607151e58f265b | |
parent | 426134128112738c97a665170b21153ef0764b7d (diff) | |
download | busybox-w32-740058b42bbfdab225706f8284e8d72b74a5df3b.tar.gz busybox-w32-740058b42bbfdab225706f8284e8d72b74a5df3b.tar.bz2 busybox-w32-740058b42bbfdab225706f8284e8d72b74a5df3b.zip |
ash: fix var_bash5.tests - ${VAR/pattern/repl} construct
function old new delta
subevalvar 1198 1279 +81
rmescapes 308 330 +22
preglob 8 10 +2
parsefname 152 154 +2
expandarg 973 975 +2
argstr 1144 1146 +2
mklocal 290 288 -2
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 6/1 up/down: 111/-2) Total: 109 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/ash.c | 97 |
1 files changed, 72 insertions, 25 deletions
diff --git a/shell/ash.c b/shell/ash.c index b73a79975..5381f34eb 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -5811,7 +5811,6 @@ ash_arith(const char *s) | |||
5811 | #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */ | 5811 | #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */ |
5812 | #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */ | 5812 | #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */ |
5813 | #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */ | 5813 | #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */ |
5814 | #define RMESCAPE_SLASH 0x20 /* Stop globbing after slash */ | ||
5815 | 5814 | ||
5816 | /* Add CTLESC when necessary. */ | 5815 | /* Add CTLESC when necessary. */ |
5817 | #define QUOTES_ESC (EXP_FULL | EXP_CASE | EXP_QPAT) | 5816 | #define QUOTES_ESC (EXP_FULL | EXP_CASE | EXP_QPAT) |
@@ -5992,8 +5991,12 @@ esclen(const char *start, const char *p) | |||
5992 | /* | 5991 | /* |
5993 | * Remove any CTLESC characters from a string. | 5992 | * Remove any CTLESC characters from a string. |
5994 | */ | 5993 | */ |
5994 | #if !BASH_PATTERN_SUBST | ||
5995 | #define rmescapes(str, flag, slash_position) \ | ||
5996 | rmescapes(str, flag) | ||
5997 | #endif | ||
5995 | static char * | 5998 | static char * |
5996 | rmescapes(char *str, int flag) | 5999 | rmescapes(char *str, int flag, int *slash_position) |
5997 | { | 6000 | { |
5998 | static const char qchars[] ALIGN1 = { | 6001 | static const char qchars[] ALIGN1 = { |
5999 | IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' }; | 6002 | IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' }; |
@@ -6002,9 +6005,8 @@ rmescapes(char *str, int flag) | |||
6002 | unsigned inquotes; | 6005 | unsigned inquotes; |
6003 | unsigned protect_against_glob; | 6006 | unsigned protect_against_glob; |
6004 | unsigned globbing; | 6007 | unsigned globbing; |
6005 | IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;) | ||
6006 | 6008 | ||
6007 | p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash)); | 6009 | p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position)); |
6008 | if (!p) | 6010 | if (!p) |
6009 | return str; | 6011 | return str; |
6010 | 6012 | ||
@@ -6084,10 +6086,11 @@ rmescapes(char *str, int flag) | |||
6084 | goto copy; | 6086 | goto copy; |
6085 | } | 6087 | } |
6086 | #if BASH_PATTERN_SUBST | 6088 | #if BASH_PATTERN_SUBST |
6087 | else if (*p == '/' && slash) { | 6089 | else if (slash_position && p == str + *slash_position) { |
6088 | /* stop handling globbing and mark location of slash */ | 6090 | /* stop handling globbing */ |
6089 | globbing = slash = 0; | 6091 | globbing = 0; |
6090 | *p = CTLESC; | 6092 | *slash_position = q - r; |
6093 | slash_position = NULL; | ||
6091 | } | 6094 | } |
6092 | #endif | 6095 | #endif |
6093 | protect_against_glob = globbing; | 6096 | protect_against_glob = globbing; |
@@ -6111,7 +6114,7 @@ rmescapes(char *str, int flag) | |||
6111 | static char * | 6114 | static char * |
6112 | preglob(const char *pattern, int flag) | 6115 | preglob(const char *pattern, int flag) |
6113 | { | 6116 | { |
6114 | return rmescapes((char *)pattern, flag | RMESCAPE_GLOB); | 6117 | return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL); |
6115 | } | 6118 | } |
6116 | 6119 | ||
6117 | /* | 6120 | /* |
@@ -6454,7 +6457,7 @@ expari(int flag) | |||
6454 | expdest = p; | 6457 | expdest = p; |
6455 | 6458 | ||
6456 | if (flag & QUOTES_ESC) | 6459 | if (flag & QUOTES_ESC) |
6457 | rmescapes(p + 1, 0); | 6460 | rmescapes(p + 1, 0, NULL); |
6458 | 6461 | ||
6459 | len = cvtnum(ash_arith(p + 1)); | 6462 | len = cvtnum(ash_arith(p + 1)); |
6460 | 6463 | ||
@@ -6742,20 +6745,57 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6742 | char *rmesc, *rmescend; | 6745 | char *rmesc, *rmescend; |
6743 | char *str; | 6746 | char *str; |
6744 | int amount, resetloc; | 6747 | int amount, resetloc; |
6748 | int argstr_flags; | ||
6745 | IF_BASH_PATTERN_SUBST(int workloc;) | 6749 | IF_BASH_PATTERN_SUBST(int workloc;) |
6746 | IF_BASH_PATTERN_SUBST(char *repl = NULL;) | 6750 | IF_BASH_PATTERN_SUBST(int slash_pos;) |
6751 | IF_BASH_PATTERN_SUBST(char *repl;) | ||
6747 | int zero; | 6752 | int zero; |
6748 | char *(*scan)(char*, char*, char*, char*, int, int); | 6753 | char *(*scan)(char*, char*, char*, char*, int, int); |
6749 | 6754 | ||
6750 | //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)", | 6755 | //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)", |
6751 | // p, varname, strloc, subtype, startloc, varflags, quotes); | 6756 | // p, varname, strloc, subtype, startloc, varflags, quotes); |
6752 | 6757 | ||
6753 | argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ? | 6758 | #if BASH_PATTERN_SUBST |
6754 | (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0) | 6759 | repl = NULL; |
6755 | ); | 6760 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { |
6761 | /* Find '/' and replace with NUL */ | ||
6762 | repl = p; | ||
6763 | for (;;) { | ||
6764 | /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */ | ||
6765 | if (*repl == '\0') { | ||
6766 | repl = NULL; | ||
6767 | break; | ||
6768 | } | ||
6769 | if (*repl == '/') { | ||
6770 | *repl = '\0'; | ||
6771 | break; | ||
6772 | } | ||
6773 | if ((unsigned char)*repl == CTLESC | ||
6774 | && repl[1] | ||
6775 | ) { | ||
6776 | repl++; | ||
6777 | } | ||
6778 | repl++; | ||
6779 | } | ||
6780 | } | ||
6781 | #endif | ||
6782 | argstr_flags = EXP_TILDE; | ||
6783 | if (subtype != VSASSIGN && subtype != VSQUESTION) | ||
6784 | argstr_flags |= (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE); | ||
6785 | argstr(p, argstr_flags); | ||
6786 | #if BASH_PATTERN_SUBST | ||
6787 | slash_pos = -1; | ||
6788 | if (repl) { | ||
6789 | slash_pos = expdest - ((char *)stackblock() + strloc); | ||
6790 | STPUTC('/', expdest); | ||
6791 | argstr(repl + 1, argstr_flags); | ||
6792 | *repl = '/'; | ||
6793 | } | ||
6794 | #endif | ||
6756 | STPUTC('\0', expdest); | 6795 | STPUTC('\0', expdest); |
6757 | argbackq = saveargbackq; | 6796 | argbackq = saveargbackq; |
6758 | startp = (char *)stackblock() + startloc; | 6797 | startp = (char *)stackblock() + startloc; |
6798 | //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc); | ||
6759 | 6799 | ||
6760 | switch (subtype) { | 6800 | switch (subtype) { |
6761 | case VSASSIGN: | 6801 | case VSASSIGN: |
@@ -6853,6 +6893,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6853 | resetloc = expdest - (char *)stackblock(); | 6893 | resetloc = expdest - (char *)stackblock(); |
6854 | 6894 | ||
6855 | #if BASH_PATTERN_SUBST | 6895 | #if BASH_PATTERN_SUBST |
6896 | repl = NULL; | ||
6897 | |||
6856 | /* We'll comeback here if we grow the stack while handling | 6898 | /* We'll comeback here if we grow the stack while handling |
6857 | * a VSREPLACE or VSREPLACEALL, since our pointers into the | 6899 | * a VSREPLACE or VSREPLACEALL, since our pointers into the |
6858 | * stack will need rebasing, and we'll need to remove our work | 6900 | * stack will need rebasing, and we'll need to remove our work |
@@ -6867,8 +6909,10 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6867 | 6909 | ||
6868 | rmesc = startp; | 6910 | rmesc = startp; |
6869 | rmescend = (char *)stackblock() + strloc; | 6911 | rmescend = (char *)stackblock() + strloc; |
6912 | //bb_error_msg("str7:'%s'", rmescend); | ||
6870 | if (quotes) { | 6913 | if (quotes) { |
6871 | rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW); | 6914 | //TODO: how to handle slash_pos here if string changes (shortens?) |
6915 | rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL); | ||
6872 | if (rmesc != startp) { | 6916 | if (rmesc != startp) { |
6873 | rmescend = expdest; | 6917 | rmescend = expdest; |
6874 | startp = (char *)stackblock() + startloc; | 6918 | startp = (char *)stackblock() + startloc; |
@@ -6881,12 +6925,13 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6881 | * The result is a_\_z_c (not a\_\_z_c)! | 6925 | * The result is a_\_z_c (not a\_\_z_c)! |
6882 | * | 6926 | * |
6883 | * The search pattern and replace string treat backslashes differently! | 6927 | * The search pattern and replace string treat backslashes differently! |
6884 | * RMESCAPE_SLASH causes preglob to work differently on the pattern | 6928 | * "&slash_pos" causes rmescapes() to work differently on the pattern |
6885 | * and string. It's only used on the first call. | 6929 | * and string. It's only used on the first call. |
6886 | */ | 6930 | */ |
6887 | preglob(str, IF_BASH_PATTERN_SUBST( | 6931 | //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos); |
6888 | (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ? | 6932 | rmescapes(str, RMESCAPE_GLOB, |
6889 | RMESCAPE_SLASH : ) 0); | 6933 | repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos) |
6934 | ); | ||
6890 | 6935 | ||
6891 | #if BASH_PATTERN_SUBST | 6936 | #if BASH_PATTERN_SUBST |
6892 | workloc = expdest - (char *)stackblock(); | 6937 | workloc = expdest - (char *)stackblock(); |
@@ -6895,11 +6940,13 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6895 | char *idx, *end; | 6940 | char *idx, *end; |
6896 | 6941 | ||
6897 | if (!repl) { | 6942 | if (!repl) { |
6898 | repl = strchr(str, CTLESC); | 6943 | //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos); |
6899 | if (repl) | 6944 | if (slash_pos >= 0) { |
6945 | repl = str + slash_pos; | ||
6900 | *repl++ = '\0'; | 6946 | *repl++ = '\0'; |
6901 | else | 6947 | } else { |
6902 | repl = nullstr; | 6948 | repl = nullstr; |
6949 | } | ||
6903 | } | 6950 | } |
6904 | //bb_error_msg("str:'%s' repl:'%s'", str, repl); | 6951 | //bb_error_msg("str:'%s' repl:'%s'", str, repl); |
6905 | 6952 | ||
@@ -7419,7 +7466,7 @@ expandmeta(struct strlist *str /*, int flag*/) | |||
7419 | INT_ON; | 7466 | INT_ON; |
7420 | nometa: | 7467 | nometa: |
7421 | *exparg.lastp = str; | 7468 | *exparg.lastp = str; |
7422 | rmescapes(str->text, 0); | 7469 | rmescapes(str->text, 0, NULL); |
7423 | exparg.lastp = &str->next; | 7470 | exparg.lastp = &str->next; |
7424 | break; | 7471 | break; |
7425 | default: /* GLOB_NOSPACE */ | 7472 | default: /* GLOB_NOSPACE */ |
@@ -7648,7 +7695,7 @@ expandmeta(struct strlist *str /*, int flag*/) | |||
7648 | */ | 7695 | */ |
7649 | nometa: | 7696 | nometa: |
7650 | *exparg.lastp = str; | 7697 | *exparg.lastp = str; |
7651 | rmescapes(str->text, 0); | 7698 | rmescapes(str->text, 0, NULL); |
7652 | exparg.lastp = &str->next; | 7699 | exparg.lastp = &str->next; |
7653 | } else { | 7700 | } else { |
7654 | *exparg.lastp = NULL; | 7701 | *exparg.lastp = NULL; |
@@ -11328,7 +11375,7 @@ parsefname(void) | |||
11328 | if (quoteflag == 0) | 11375 | if (quoteflag == 0) |
11329 | n->type = NXHERE; | 11376 | n->type = NXHERE; |
11330 | TRACE(("Here document %d\n", n->type)); | 11377 | TRACE(("Here document %d\n", n->type)); |
11331 | rmescapes(wordtext, 0); | 11378 | rmescapes(wordtext, 0, NULL); |
11332 | here->eofmark = wordtext; | 11379 | here->eofmark = wordtext; |
11333 | here->next = NULL; | 11380 | here->next = NULL; |
11334 | if (heredoclist == NULL) | 11381 | if (heredoclist == NULL) |