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:
parent
0fcc6c8fb2
commit
e8d6041f69
3 changed files with 73 additions and 46 deletions
|
@ -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
|
||||
|
|
50
Src/subst.c
50
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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue