Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: Inconsistency with SHWORDSPLIT and leading spaces
OK, I know what you're all thinking now. "What about whitespace at the
end of an internal parameter argument subject to word-splitting?
Doesn't that need handling, too? Isn't this, in fact, the most burning
question of our day?"
Grmph.
This is essentially equivalent. I haven't tested RC_EXPAND_PARAM (see
under "soul-destroying") but the following is generic enough it ought to
be OK.
pws
diff --git a/Src/subst.c b/Src/subst.c
index 5289121..4d04fa7 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,14 @@ 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;
}
+ 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 59c14a4..694b613 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
Messages sorted by:
Reverse Date,
Date,
Thread,
Author