aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-01-09 17:01:00 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-01-09 17:07:06 +0100
commit740058b42bbfdab225706f8284e8d72b74a5df3b (patch)
treed910fbfe111ddfb761315d9fa2607151e58f265b
parent426134128112738c97a665170b21153ef0764b7d (diff)
downloadbusybox-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.c97
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
5995static char * 5998static char *
5996rmescapes(char *str, int flag) 5999rmescapes(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)
6111static char * 6114static char *
6112preglob(const char *pattern, int flag) 6115preglob(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)