1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-30 07:10:58 +02:00

37074: extend previous fix to over whitespace at end

This commit is contained in:
Peter Stephenson 2015-11-07 18:05:43 +00:00
parent 0fcc6c8fb2
commit e8d6041f69
3 changed files with 73 additions and 46 deletions

View file

@ -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> 2015-11-06 Peter Stephenson <p.stephenson@samsung.com>
* 37073: Src/subst.c, Test/D04parameter.ztst: fix case of * 37073: Src/subst.c, Test/D04parameter.ztst: fix case of

View file

@ -420,6 +420,22 @@ singsub(char **s)
DPUTS(nonempty(&foo), "BUG: singsub() produced more than one word!"); 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 /* 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 * 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 * 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 * NULL to use IFS). The return value is true iff the expansion resulted
* in an empty list. * in an empty list.
* *
* *ws_at_start is set to 1 if the string had whitespace at thes start * *ws_at_start is set to bits in the enum above as neeed.
* that should cause word splitting against any preceeding string.
*/ */
/**/ /**/
static int static int
multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep, multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep,
int *ws_at_start) int *ws_sub)
{ {
int l; int l;
char **r, **p, *x = *s; char **r, **p, *x = *s;
@ -455,7 +470,7 @@ multsub(char **s, int pf_flags, char ***a, int *isarr, char *sep,
l++; l++;
if (!iwsep(STOUC(c))) if (!iwsep(STOUC(c)))
break; 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)) if (!WC_ZISTYPE(c, ISEP))
break; break;
} }
if (!*x) if (!*x) {
*ws_sub |= WS_AT_END;
break; break;
}
insertlinknode(&foo, n, (void *)x), incnode(n); 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 * whitespace. However, if there's no "x" the whitespace is
* simply removed. * simply removed.
*/ */
int ws_at_start = 0; int ws_sub = 0;
*s++ = '\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. * necessary, when we handle (P) lower down.
*/ */
if (multsub(&val, 0, (aspar ? NULL : &aval), &isarr, NULL, 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 */ /* Empty quoted string --- treat as null string, not elided */
isarr = -1; isarr = -1;
aval = (char **) hcalloc(sizeof(char *)); 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; split_flags = PREFORK_NOSHWORDSPLIT;
} }
multsub(&val, split_flags, (aspar ? NULL : &aval), multsub(&val, split_flags, (aspar ? NULL : &aval),
&isarr, NULL, &ws_at_start); &isarr, NULL, &ws_sub);
copied = 1; copied = 1;
spbreak = 0; spbreak = 0;
/* Leave globsubst on if forced */ /* 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. */ * behavior on caller choice of PREFORK_SHWORDSPLIT. */
multsub(&val, multsub(&val,
spbreak ? PREFORK_SINGLE : PREFORK_NOSHWORDSPLIT, spbreak ? PREFORK_SINGLE : PREFORK_NOSHWORDSPLIT,
NULL, &isarr, NULL, &ws_at_start); NULL, &isarr, NULL, &ws_sub);
} else { } else {
if (spbreak) if (spbreak)
split_flags = PREFORK_SPLIT|PREFORK_SHWORDSPLIT; split_flags = PREFORK_SPLIT|PREFORK_SHWORDSPLIT;
else else
split_flags = PREFORK_NOSHWORDSPLIT; split_flags = PREFORK_NOSHWORDSPLIT;
multsub(&val, split_flags, &aval, &isarr, NULL, multsub(&val, split_flags, &aval, &isarr, NULL,
&ws_at_start); &ws_sub);
spbreak = 0; spbreak = 0;
} }
if (arrasg) { if (arrasg) {
@ -3319,7 +3336,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
} }
if (haserr || errflag) if (haserr || errflag)
return NULL; return NULL;
ws_at_start = 0; ws_sub = 0;
} }
/* /*
* This handles taking a length with ${#foo} and variations. * 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); sprintf(buf, "%ld", len);
val = dupstring(buf); val = dupstring(buf);
isarr = 0; isarr = 0;
ws_at_start = 0; ws_sub = 0;
} }
/* At this point we make sure that our arrayness has affected the /* At this point we make sure that our arrayness has affected the
* arrayness of the linked list. Then, we can turn our value into * 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) { if (isarr) {
val = sepjoin(aval, sep, 1); val = sepjoin(aval, sep, 1);
isarr = 0; isarr = 0;
ws_at_start = 0; ws_sub = 0;
} }
if (!ssub && (spbreak || spsep)) { if (!ssub && (spbreak || spsep)) {
aval = sepsplit(val, spsep, 0, 1); 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 * 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. * 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); insertlinknode(l, n, dupstrpfx(ostr, aptr - ostr)), incnode(n);
ostr = aptr; 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) { if (isarr) {
char *x; char *x;
char *y; char *y;

View file

@ -1751,26 +1751,26 @@
} }
foo=bar foo=bar
foo2="bar bar" foo2="bar bar"
do_test ${:- foo} do_test ${:- foo }
do_test ${:- foo bar} do_test ${:- foo bar }
do_test ${:- $foo} do_test ${:- $foo }
do_test ${:- $foo2} do_test ${:- $foo2 }
do_test x${:- foo} do_test x${:- foo }y
do_test x${:- foo bar} do_test x${:- foo bar }y
do_test x${:- $foo} do_test x${:- $foo }y
do_test x${:- $foo2} do_test x${:- $foo2 }y
do_test x${foo:+ $foo} do_test x${foo:+ $foo }y
) )
0:We Love SH_WORD_SPLIT Day celebrated with space at start of internal subst 0:We Love SH_WORD_SPLIT Day celebrated with space at start of internal subst
>1: foo >1: foo
>2: foo bar >2: foo bar
>1: bar >1: bar
>2: bar bar >2: bar bar
>2: x foo >3: x foo y
>3: x foo bar >4: x foo bar y
>2: x bar >3: x bar y
>3: x bar bar >4: x bar bar y
>2: x bar >3: x bar y
(unsetopt shwordsplit # default, for clarity (unsetopt shwordsplit # default, for clarity
do_test() { do_test() {
@ -1778,23 +1778,23 @@
} }
foo=bar foo=bar
foo2="bar bar" foo2="bar bar"
do_test ${:- foo} do_test ${:- foo }
do_test ${:- foo bar} do_test ${:- foo bar }
do_test ${:- $foo} do_test ${:- $foo }
do_test ${:- $foo2} do_test ${:- $foo2 }
do_test x${:- foo} do_test x${:- foo }y
do_test x${:- foo bar} do_test x${:- foo bar }y
do_test x${:- $foo} do_test x${:- $foo }y
do_test x${:- $foo2} do_test x${:- $foo2 }y
do_test x${foo:+ $foo} do_test x${foo:+ $foo }y
) )
0:We Love NO_SH_WORD_SPLIT Even More Day celebrated as sanity check 0:We Love NO_SH_WORD_SPLIT Even More Day celebrated as sanity check
>1: foo >1: foo
>1: foo bar >1: foo bar
>1: bar >1: bar
>1: bar bar >1: bar bar
>1: x foo >1: x foo y
>1: x foo bar >1: x foo bar y
>1: x bar >1: x bar y
>1: x bar bar >1: x bar bar y
>1: x bar >1: x bar y