summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--Doc/Zsh/expn.yo3
-rw-r--r--Doc/Zsh/options.yo3
-rw-r--r--Src/params.c10
-rw-r--r--Src/zsh.h29
-rw-r--r--Test/D04parameter.ztst34
6 files changed, 70 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 756ef0bdd..16e9150ed 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-10-09 Peter Stephenson <pws@csr.com>
+
+ * 25831: Doc/Zsh/expn.yo, Doc/Zsh/options.yo, Src/params.c,
+ Src/zsh.h, Test/D04parameter.ztst: ensure failed subscript matches
+ of a type that are documented as strings rather than arrays
+ return an empty string rather than an empty array to avoid
+ strange RC_EXPAND_PARAM behaviour.
+
2008-10-08 Peter Stephenson <pws@csr.com>
* Nikolai Weibull: 25828: Completion/Unix/Command/_rm,
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index e2434431a..02b95d4f0 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -611,7 +611,8 @@ var(foo)tt(${)var(xx)tt(})var(bar),
where the parameter var(xx)
is set to tt(LPAR())var(a b c)tt(RPAR()), are substituted with
`var(fooabar foobbar foocbar)' instead of the default
-`var(fooa b cbar)'.
+`var(fooa b cbar)'. Note that an empty array will therefore cause
+all arguments to be removed.
Internally, each such expansion is converted into the
equivalent list for brace expansion. E.g., tt(${^var}) becomes
diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index 5c7b29cfd..e3bc27127 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -485,7 +485,8 @@ Array expansions of the form
`var(foo)tt(${)var(xx)tt(})var(bar)', where the parameter
var(xx) is set to tt(LPAR())var(a b c)tt(RPAR()), are substituted with
`var(fooabar foobbar foocbar)' instead of the default
-`var(fooa b cbar)'.
+`var(fooa b cbar)'. Note that an empty array will therefore cause
+all arguments to be removed.
)
pindex(REMATCH_PCRE)
cindex(regexp, PCRE)
diff --git a/Src/params.c b/Src/params.c
index 65b3ecff8..71cb2a907 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -1810,11 +1810,10 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
/* Overload v->isarr as the flag bits for hashed arrays. */
v->isarr = flags | (isvarat ? SCANPM_ISVAR_AT : 0);
/* If no flags were passed, we need something to represent *
- * `true' yet differ from an explicit WANTVALS. This is a *
- * bit of a hack, but makes some sense: When no subscript *
- * is provided, all values are substituted. */
+ * `true' yet differ from an explicit WANTVALS. Use a *
+ * special flag for this case. */
if (!v->isarr)
- v->isarr = SCANPM_MATCHMANY;
+ v->isarr = SCANPM_ARRONLY;
}
v->pm = pm;
v->flags = 0;
@@ -2188,7 +2187,8 @@ setstrvalue(Value v, char *val)
zsfree(val);
return;
}
- if ((v->pm->node.flags & PM_HASHED) && (v->isarr & SCANPM_MATCHMANY)) {
+ if ((v->pm->node.flags & PM_HASHED) &&
+ (v->isarr & (SCANPM_MATCHMANY|SCANPM_ARRONLY))) {
zerr("%s: attempt to set slice of associative array", v->pm->node.nam);
zsfree(val);
return;
diff --git a/Src/zsh.h b/Src/zsh.h
index 2ceab1dca..94d4503e4 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1532,16 +1532,25 @@ struct tieddata {
#define TYPESET_OPTNUM "LRZiEF"
/* Flags for extracting elements of arrays and associative arrays */
-#define SCANPM_WANTVALS (1<<0)
-#define SCANPM_WANTKEYS (1<<1)
-#define SCANPM_WANTINDEX (1<<2)
-#define SCANPM_MATCHKEY (1<<3)
-#define SCANPM_MATCHVAL (1<<4)
-#define SCANPM_MATCHMANY (1<<5)
-#define SCANPM_ASSIGNING (1<<6)
-#define SCANPM_KEYMATCH (1<<7)
-#define SCANPM_DQUOTED (1<<8)
-#define SCANPM_ISVAR_AT ((-1)<<15) /* Only sign bit is significant */
+#define SCANPM_WANTVALS (1<<0) /* Return value includes hash values */
+#define SCANPM_WANTKEYS (1<<1) /* Return value includes hash keys */
+#define SCANPM_WANTINDEX (1<<2) /* Return value includes array index */
+#define SCANPM_MATCHKEY (1<<3) /* Subscript matched against key */
+#define SCANPM_MATCHVAL (1<<4) /* Subscript matched against value */
+#define SCANPM_MATCHMANY (1<<5) /* Subscript matched repeatedly, return all */
+#define SCANPM_ASSIGNING (1<<6) /* Assigning whole array/hash */
+#define SCANPM_KEYMATCH (1<<7) /* keys of hash treated as patterns */
+#define SCANPM_DQUOTED (1<<8) /* substitution was double-quoted
+ * (only used for testing early end of
+ * subscript)
+ */
+#define SCANPM_ARRONLY (1<<9) /* value is array but we don't
+ * necessarily want to match multiple
+ * elements
+ */
+#define SCANPM_ISVAR_AT ((-1)<<15) /* "$foo[@]"-style substitution
+ * Only sign bit is significant
+ */
/*
* Flags for doing matches inside parameter substitutions, i.e.
diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst
index 376932b34..4cd137bbd 100644
--- a/Test/D04parameter.ztst
+++ b/Test/D04parameter.ztst
@@ -1086,3 +1086,37 @@
>no
>no
>no
+
+ rcexbug() {
+ emulate -L zsh
+ setopt rcexpandparam
+ local -A hash
+ local -a full empty
+ full=(X x)
+ hash=(X x)
+ print ORDINARY ARRAYS
+ : The following behaves as documented in zshoptions
+ print FULL expand=$full
+ : Empty arrays remove the adjacent argument
+ print EMPTY expand=$empty
+ print ASSOCIATIVE ARRAY
+ print Subscript flags returning many values
+ print FOUND key=$hash[(I)X] val=$hash[(R)x]
+ : This should behave like $empty, and does
+ print LOST key=$hash[(I)y] val=$hash[(R)Y]
+ print Subscript flags returning single values
+ : Doc says "substitutes ... empty string"
+ : so must not behave like an empty array
+ print STRING key=$hash[(i)y] val=$hash[(r)Y]
+ }
+ rcexbug
+0:Lookup failures on elements of arrays with RC_EXPAND_PARAM
+>ORDINARY ARRAYS
+>FULL expand=X expand=x
+>EMPTY
+>ASSOCIATIVE ARRAY
+>Subscript flags returning many values
+>FOUND key=X val=x
+>LOST
+>Subscript flags returning single values
+>STRING key= val=