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>
* 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!");
}
/*
* 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;

View file

@ -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