Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [PATCH] Implement references to positional parameters



And one more update.

Implement references to positional parameters

Philippe

diff --git a/Src/params.c b/Src/params.c
index 81c3da74e..1ab6af595 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -224,6 +224,8 @@ static const struct gsu_integer ttyidle_gsu =
 
 static const struct gsu_scalar argzero_gsu =
 { argzerogetfn, argzerosetfn, nullunsetfn };
+static const struct gsu_scalar argn_gsu =
+{ argngetfn, argnsetfn, argnunsetfn };
 static const struct gsu_scalar username_gsu =
 { usernamegetfn, usernamesetfn, stdunsetfn };
 static const struct gsu_scalar dash_gsu =
@@ -484,6 +486,8 @@ static initparam argvparam_pm = IPDEF9("", &pparams, NULL, \
 			  (zsfree((PM)->u.str), (PM)->u.str = (S)))
 
 static Param argvparam;
+static Param *argnparams;
+static size_t argnparams_size;
 
 /*
  * Lists of references to nested variables ("Param" instances) indexed
@@ -856,6 +860,9 @@ createparamtable(void)
     }
 
     argvparam = (Param) &argvparam_pm;
+    argnparams = zshcalloc(8 * sizeof(Param));
+    argnparams_size = 8;
+    argnparams[0] = (Param) paramtab->getnode(paramtab, "0");
 
     noerrs = 2;
 
@@ -4898,6 +4905,49 @@ argzerogetfn(UNUSED(Param pm))
     return argzero;
 }
 
+/* Function to get value for positional parameters */
+
+/**/
+static char *
+argngetfn(Param pm)
+{
+    return arrlen_gt(pparams, pm->u.val - 1) ?
+	pparams[pm->u.val - 1] : (char *) hcalloc(1);
+}
+
+/* Function to set value for positional parameters */
+
+/**/
+static void
+argnsetfn(Param pm, char *x)
+{
+    int len = arrlen(pparams);
+    int ppar = pm->u.val;
+    if (ppar <= len)
+	zsfree(pparams[ppar - 1]);
+    else if (x) {
+	int i;
+	pparams = (char **) zrealloc(pparams, sizeof(char *) * ppar + 1);
+	for (i = len; i < ppar - 1; i++)
+	    pparams[i] = ztrdup("");
+	pparams[ppar] = 0;
+    }
+    if (x) {
+	pparams[ppar - 1] = ztrdup(x);
+	zsfree(x);
+    } else if (ppar <= len)
+	memmove(pparams + ppar - 1, pparams + ppar, (len - ppar + 1) * sizeof(char *));
+}
+
+/* Function to unset positional parameters */
+
+/**/
+static void
+argnunsetfn(Param pm, UNUSED(int exp))
+{
+    argnsetfn(pm, NULL);
+}
+
 /* Function to get value for special parameter `HISTSIZE' */
 
 /**/
@@ -6290,6 +6340,23 @@ resolve_nameref_rec(Param pm, const Param stop, int keep_lastref)
 	if ((pm = loadparamnode(paramtab, upscope(pm, ref), refname)) &&
 	    pm != stop && !(pm->node.flags & PM_UNSET))
 	    pm = resolve_nameref_rec(pm, stop, keep_lastref);
+    } else if (idigit(*refname)) {
+	int ppar = zstrtol(refname, NULL, 10);
+	if (ppar >= argnparams_size) {
+	    size_t old_size = argnparams_size;
+	    size_t new_size = argnparams_size = MAX(2 * old_size, ppar);
+	    argnparams = zrealloc(argnparams, new_size * sizeof(Param));
+	    memset(argnparams + old_size, 0,
+		   (new_size - old_size) * sizeof(Param));
+	}
+	if (!(pm = argnparams[ppar])) {
+	    pm = argnparams[ppar] = zshcalloc(sizeof(*pm));
+	    pm->node.nam = zalloc(snprintf(NULL, 0, "%d", ppar) + 1);
+	    sprintf(pm->node.nam, "%d", ppar);
+	    pm->node.flags = PM_SCALAR | PM_SPECIAL;
+	    pm->u.val = ppar;
+	    pm->gsu.s = &argn_gsu;
+	}
     } else if (keep_lastref)
 	pm = ref;
     unqueue_signals();
diff --git a/Test/K01nameref.ztst b/Test/K01nameref.ztst
index 0336a507d..6cfe6d1d0 100644
--- a/Test/K01nameref.ztst
+++ b/Test/K01nameref.ztst
@@ -1419,24 +1419,25 @@ F:previously this could create an infinite recursion and crash
 
  edgelocal() ( local -n x=$1; typeset -p x; print -r $x )
  edgeupper() ( local -nu x=$1; typeset -p x; print -r $x )
- for edge in argv ARGC \@ \* \# 0 1 01 \! \? \$ - _
+ for edge in argv ARGC \@ \* \# 0 00 2 02 \! \? \$ - _
  do
-  edgelocal $edge
-  edgeupper $edge
+  edgelocal $edge foo
+  edgeupper $edge foo
  done
  unfunction edgelocal edgeupper
 0q:references to builtin specials
-F:BUG:References to 1, 2, ... are supported but don't work (always expand to "")
 >typeset -n x=argv
->argv
+>argv foo
 >typeset -n x=ARGC
->1
+>2
 >typeset -n x=0
 >edgelocal
->typeset -n x=1
->
->typeset -n x=01
->
+>typeset -n x=00
+>edgelocal
+>typeset -n x=2
+>foo
+>typeset -n x=02
+>foo
 >typeset -n x=!
 >0
 >typeset -un x=!
@@ -1466,8 +1467,78 @@ F:BUG:References to 1, 2, ... are supported but don't work (always expand to "")
 ?edgelocal: invalid variable name: #
 ?edgeupper: invalid variable name: #
 ?edgeupper: invalid variable name: 0
-?edgeupper: invalid variable name: 1
-?edgeupper: invalid variable name: 01
+?edgeupper: invalid variable name: 00
+?edgeupper: invalid variable name: 2
+?edgeupper: invalid variable name: 02
+
+ tst() {
+   typeset -n ref0=0 2>&1
+   typeset -n ref00=00 2>&1
+   typeset -n ref2=2 2>&1
+   typeset -n ref02=02 2>&1
+   echo ${(q)0} ${(q)*} - $ref0 - $ref00 - $ref2 - $ref02
+   ref0=TST
+   ref2=BBB
+   echo ${(q)0} ${(q)*} - $ref0 - $ref00 - $ref2 - $ref02
+   ref00=Tst
+   ref02=Bbb
+   echo ${(q)0} ${(q)*} - $ref0 - $ref00 - $ref2 - $ref02; typeset -p -- 0 00 2 02 2>&1
+   unset ref0
+   unset ref2
+   echo ${(q)0} ${(q)*} - $ref0 - $ref00 - $ref2 - $ref02; typeset -p -- 0 00 2 02 2>&1
+   ref0=tst
+   ref2=bbb
+   echo ${(q)0} ${(q)*} - $ref0 - $ref00 - $ref2 - $ref02; typeset -p -- 0 00 2 02 2>&1
+   { ref0=(TST TST) 2>&1 } always { TRY_BLOCK_ERROR=0 }
+   { ref2=(BBB BBB) 2>&1 } always { TRY_BLOCK_ERROR=0 }
+   echo ${(q)0} ${(q)*} - $ref0 - $ref00 - $ref2 - $ref02; typeset -p -- 0 00 2 02 2>&1
+   typeset -n ref5=5 2>&1
+   ref5=zzz
+   echo ${(q)0} ${(q)*}
+   unset ref2
+   echo ${(q)0} ${(q)*}
+   unset ref2
+   echo ${(q)0} ${(q)*}
+   unset ref2
+   echo ${(q)0} ${(q)*}
+   unset ref2
+   echo ${(q)0} ${(q)*}
+   unset ref2
+   echo ${(q)0} ${(q)*}
+ }
+ tst aaa bbb ccc
+ unfunction tst
+0:references to positional parameters
+>tst aaa bbb ccc - tst - tst - bbb - bbb
+>TST aaa BBB ccc - TST - TST - BBB - BBB
+>Tst aaa Bbb ccc - Tst - Tst - Bbb - Bbb
+>tst:typeset:11: no such variable: 00
+>tst:typeset:11: no such variable: 2
+>tst:typeset:11: no such variable: 02
+>typeset -g 0=Tst
+>Tst aaa ccc - Tst - Tst - ccc - ccc
+>tst:typeset:14: no such variable: 00
+>tst:typeset:14: no such variable: 2
+>tst:typeset:14: no such variable: 02
+>typeset -g 0=Tst
+>tst aaa bbb - tst - tst - bbb - bbb
+>tst:typeset:17: no such variable: 00
+>tst:typeset:17: no such variable: 2
+>tst:typeset:17: no such variable: 02
+>typeset -g 0=tst
+>tst:18: 0: attempt to assign array value to non-array
+>tst:19: 2: attempt to assign array value to non-array
+>tst aaa bbb - tst - tst - bbb - bbb
+>tst:typeset:20: no such variable: 00
+>tst:typeset:20: no such variable: 2
+>tst:typeset:20: no such variable: 02
+>typeset -g 0=tst
+>tst aaa bbb '' '' zzz
+>tst aaa '' '' zzz
+>tst aaa '' zzz
+>tst aaa zzz
+>tst aaa
+>tst aaa
 
 #
 # The following tests are run in interactive mode, using PS1 as an


Messages sorted by: Reverse Date, Date, Thread, Author