summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorOliver Kiddle <opk@zsh.org>2016-09-16 00:00:28 +0200
committerOliver Kiddle <opk@zsh.org>2016-09-16 00:00:28 +0200
commitfbafc5b509e311efee064bbd12396a2e207f3393 (patch)
tree9fdf8f236fb1d25b54079e81cf75bf05eeca0b26 /Src
parent00708285e94ce42a31fd59bbcd06d010a6d0d6ee (diff)
downloadzsh-fbafc5b509e311efee064bbd12396a2e207f3393.tar.gz
zsh-fbafc5b509e311efee064bbd12396a2e207f3393.tar.xz
zsh-fbafc5b509e311efee064bbd12396a2e207f3393.zip
39332: support ksh's [[ -v varname ]] condition for checking if variables are set
Diffstat (limited to 'Src')
-rw-r--r--Src/cond.c2
-rw-r--r--Src/params.c30
-rw-r--r--Src/parse.c4
3 files changed, 34 insertions, 2 deletions
diff --git a/Src/cond.c b/Src/cond.c
index f25ebd4a3..42e9de30f 100644
--- a/Src/cond.c
+++ b/Src/cond.c
@@ -351,6 +351,8 @@ evalcond(Estate state, char *fromtest)
 	return (!S_ISSOCK(dostat(left)));
     case 'u':
 	return (!(dostat(left) & S_ISUID));
+    case 'v':
+	return (!issetvar(left));
     case 'w':
 	return (!doaccess(left, W_OK));
     case 'x':
diff --git a/Src/params.c b/Src/params.c
index 842b2f0d1..384c30a1a 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -626,6 +626,36 @@ getvaluearr(Value v)
 	return NULL;
 }
 
+/* Return whether the variable is set         *
+ * checks that array slices are within range  *
+ * used for [[ -v ... ]] condition test       */
+
+/**/
+int
+issetvar(char *name)
+{
+    struct value vbuf;
+    Value v;
+    int slice;
+    char **arr;
+
+    if (!(v = getvalue(&vbuf, &name, 1)) || *name)
+	return 0; /* no value or more chars after the variable name */
+    if (v->isarr & ~SCANPM_ARRONLY)
+	return v->end > 1; /* for extracted elements, end gives us a count */
+
+    slice = v->start != 0 || v->end != -1;
+    if (PM_TYPE(v->pm->node.flags) != PM_ARRAY || !slice)
+	return !slice && !(v->pm->node.flags & PM_UNSET);
+
+    if (!v->end) /* empty array slice */
+	return 0;
+    /* get the array and check end is within range */
+    if (!(arr = getvaluearr(v)))
+	return 0;
+    return arrlen_ge(arr, v->end < 0 ? - v->end : v->end);
+}
+
 /*
  * Split environment string into (name, value) pair.
  * this is used to avoid in-place editing of environment table
diff --git a/Src/parse.c b/Src/parse.c
index d3c418184..24b8cd97f 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -2385,7 +2385,7 @@ par_cond_2(void)
     s1 = tokstr;
     dble = (s1 && *s1 == '-'
 	    && (!n_testargs
-		|| strspn(s1+1, "abcdefghknoprstuwxzLONGS") == 1)
+		|| strspn(s1+1, "abcdefghknoprstuvwxzLONGS") == 1)
 	    && !s1[2]);
     if (tok != STRING) {
 	/* Check first argument for [[ STRING ]] re-interpretation */
@@ -2464,7 +2464,7 @@ par_cond_double(char *a, char *b)
 {
     if (a[0] != '-' || !a[1])
 	COND_ERROR("parse error: condition expected: %s", a);
-    else if (!a[2] && strspn(a+1, "abcdefgknoprstuwxzhLONGS") == 1) {
+    else if (!a[2] && strspn(a+1, "abcdefgknoprstuvwxzhLONGS") == 1) {
 	ecadd(WCB_COND(a[1], 0));
 	ecstr(b);
     } else {