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

Re: [PATCH] Implement references to positional parameters



Synced and merged:

Implement references to positional parameters

Note that the patch is built on top of workers/54364.
diff --git a/Src/params.c b/Src/params.c
index 319fadfe5..99cfe6ef8 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;
 
@@ -4986,6 +4993,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' */
 
 /**/
@@ -6388,6 +6438,23 @@ resolve_nameref_rec(Param pm, const Param stop, int keep_lastref)
 	    pm = resolve_nameref_rec(pm, stop, keep_lastref);
 	    ref->node.flags &= ~PM_TAGGED;
 	}
+    } 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 f772d583f..68f56a398 100644
--- a/Test/K01nameref.ztst
+++ b/Test/K01nameref.ztst
@@ -1339,14 +1339,14 @@ 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 1 01 \! \? - _
  do
   edgelocal $edge
   edgelocal "$edge""[1]"
   edgeupper $edge
  done
 0:references to builtin specials
-F:Subscripting on 1 01 ! ? - should print first character but do not
+F:Subscripting on 00 1 01 ! ? - should print first character but do not
 >typeset -n x=argv
 >argv
 >typeset -n x='argv[1]'
@@ -1359,12 +1359,16 @@ F:Subscripting on 1 01 ! ? - should print first character but do not
 >edgelocal
 >typeset -n x='0[1]'
 >e
->typeset -n x=1
+>typeset -n x=00
+>edgelocal
+>typeset -n x='00[1]'
 >
+>typeset -n x=1
+>1
 >typeset -n x='1[1]'
 >
 >typeset -n x=01
->
+>01
 >typeset -n x='01[1]'
 >
 >typeset -n x=!
@@ -1403,6 +1407,7 @@ F:Subscripting on 1 01 ! ? - should print first character but do not
 ?edgelocal: invalid name reference: #[1]
 ?edgeupper: invalid name reference: #
 ?edgeupper: invalid name reference: 0
+?edgeupper: invalid name reference: 00
 ?edgeupper: invalid name reference: 1
 ?edgeupper: invalid name reference: 01
 
@@ -1418,6 +1423,75 @@ F:$$[1] reference should print the first digit of $$ but prints nothing
 >$$[1]
 >$$
 
+ 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
 # assignable special with side-effects.  This crashed at one time.


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