diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | Src/subst.c | 50 | ||||
-rw-r--r-- | Test/D04parameter.ztst | 64 |
3 files changed, 73 insertions, 46 deletions
diff --git a/ChangeLog b/ChangeLog index 71d44bc90..1334e29d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-11-07 Peter Stephenson <p.w.stephenson@ntlworld.com> + + * 37074: Src/subst.c, Test/D04parameter.ztst: extend previous + fix to cover whitespace at end of substitution. + 2015-11-06 Peter Stephenson <p.stephenson@samsung.com> * 37073: Src/subst.c, Test/D04parameter.ztst: fix case of diff --git a/Src/subst.c b/Src/subst.c index 528912134..febdc9bea 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -420,6 +420,22 @@ singsub(char **s) DPUTS(nonempty(&foo), "BUG: singsub() produced more than one word!"); } +/* + * Bit flags passed back from multsub() to paramsubst(). + */ +enum { + /* + * Set if the string had whitespace at the start + * that should cause word splitting against any preceeding string. + */ + WS_AT_START = 1, + /* + * Set if the string had whitespace at the end + * that should cause word splitting against any following string. + */ + WS_AT_END = 2 +}; + /* Perform substitution on a single word, *s. Unlike with singsub(), the * result can be more than one word. If split is non-zero, the string is * first word-split using IFS, but only for non-quoted "whitespace" (as @@ -432,14 +448,13 @@ singsub(char **s) * NULL to use IFS). The return value is true iff the expansion resulted * in an empty list. * - * *ws_at_start is set to 1 if the string had whitespace at thes start - * that should cause word splitting against any preceeding string. + * *ws_at_start is set to bits in the enum above as neeed. */ /**/ static int multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep, - int *ws_at_start) + int *ws_sub) { int l; char **r, **p, *x = *s; @@ -455,7 +470,7 @@ multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep, l++; if (!iwsep(STOUC(c))) break; - *ws_at_start = 1; + *ws_sub |= WS_AT_START; } } @@ -487,8 +502,10 @@ multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep, if (!WC_ZISTYPE(c, ISEP)) break; } - if (!*x) + if (!*x) { + *ws_sub |= WS_AT_END; break; + } insertlinknode(&foo, n, (void *)x), incnode(n); } } @@ -1730,7 +1747,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * whitespace. However, if there's no "x" the whitespace is * simply removed. */ - int ws_at_start = 0; + int ws_sub = 0; *s++ = '\0'; /* @@ -2280,7 +2297,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * necessary, when we handle (P) lower down. */ if (multsub(&val, 0, (aspar ? NULL : &aval), &isarr, NULL, - &ws_at_start) && quoted) { + &ws_sub) && quoted) { /* Empty quoted string --- treat as null string, not elided */ isarr = -1; aval = (char **) hcalloc(sizeof(char *)); @@ -2751,7 +2768,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) split_flags = PREFORK_NOSHWORDSPLIT; } multsub(&val, split_flags, (aspar ? NULL : &aval), - &isarr, NULL, &ws_at_start); + &isarr, NULL, &ws_sub); copied = 1; spbreak = 0; /* Leave globsubst on if forced */ @@ -2780,14 +2797,14 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * behavior on caller choice of PREFORK_SHWORDSPLIT. */ multsub(&val, spbreak ? PREFORK_SINGLE : PREFORK_NOSHWORDSPLIT, - NULL, &isarr, NULL, &ws_at_start); + NULL, &isarr, NULL, &ws_sub); } else { if (spbreak) split_flags = PREFORK_SPLIT|PREFORK_SHWORDSPLIT; else split_flags = PREFORK_NOSHWORDSPLIT; multsub(&val, split_flags, &aval, &isarr, NULL, - &ws_at_start); + &ws_sub); spbreak = 0; } if (arrasg) { @@ -3319,7 +3336,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) } if (haserr || errflag) return NULL; - ws_at_start = 0; + ws_sub = 0; } /* * This handles taking a length with ${#foo} and variations. @@ -3358,7 +3375,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) sprintf(buf, "%ld", len); val = dupstring(buf); isarr = 0; - ws_at_start = 0; + ws_sub = 0; } /* At this point we make sure that our arrayness has affected the * arrayness of the linked list. Then, we can turn our value into @@ -3388,7 +3405,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) if (isarr) { val = sepjoin(aval, sep, 1); isarr = 0; - ws_at_start = 0; + ws_sub = 0; } if (!ssub && (spbreak || spsep)) { aval = sepsplit(val, spsep, 0, 1); @@ -3673,10 +3690,15 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) * If a multsub result had whitespace at the start and we're * splitting and there's a previous string, now's the time to do so. */ - if (ws_at_start && aptr > ostr) { + if ((ws_sub & WS_AT_START) && aptr > ostr) { insertlinknode(l, n, dupstrpfx(ostr, aptr - ostr)), incnode(n); ostr = aptr; } + /* Likewise at the end */ + if ((ws_sub & WS_AT_END) && *fstr) { + insertlinknode(l, n, dupstring(fstr)); /* appended, no incnode */ + *fstr = '\0'; + } if (isarr) { char *x; char *y; diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 59c14a408..694b613c5 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -1751,26 +1751,26 @@ } foo=bar foo2="bar bar" - do_test ${:- foo} - do_test ${:- foo bar} - do_test ${:- $foo} - do_test ${:- $foo2} - do_test x${:- foo} - do_test x${:- foo bar} - do_test x${:- $foo} - do_test x${:- $foo2} - do_test x${foo:+ $foo} + do_test ${:- foo } + do_test ${:- foo bar } + do_test ${:- $foo } + do_test ${:- $foo2 } + do_test x${:- foo }y + do_test x${:- foo bar }y + do_test x${:- $foo }y + do_test x${:- $foo2 }y + do_test x${foo:+ $foo }y ) 0:We Love SH_WORD_SPLIT Day celebrated with space at start of internal subst >1: foo >2: foo bar >1: bar >2: bar bar ->2: x foo ->3: x foo bar ->2: x bar ->3: x bar bar ->2: x bar +>3: x foo y +>4: x foo bar y +>3: x bar y +>4: x bar bar y +>3: x bar y (unsetopt shwordsplit # default, for clarity do_test() { @@ -1778,23 +1778,23 @@ } foo=bar foo2="bar bar" - do_test ${:- foo} - do_test ${:- foo bar} - do_test ${:- $foo} - do_test ${:- $foo2} - do_test x${:- foo} - do_test x${:- foo bar} - do_test x${:- $foo} - do_test x${:- $foo2} - do_test x${foo:+ $foo} + do_test ${:- foo } + do_test ${:- foo bar } + do_test ${:- $foo } + do_test ${:- $foo2 } + do_test x${:- foo }y + do_test x${:- foo bar }y + do_test x${:- $foo }y + do_test x${:- $foo2 }y + do_test x${foo:+ $foo }y ) 0:We Love NO_SH_WORD_SPLIT Even More Day celebrated as sanity check ->1: foo ->1: foo bar ->1: bar ->1: bar bar ->1: x foo ->1: x foo bar ->1: x bar ->1: x bar bar ->1: x bar +>1: foo +>1: foo bar +>1: bar +>1: bar bar +>1: x foo y +>1: x foo bar y +>1: x bar y +>1: x bar bar y +>1: x bar y |