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

Partial implementation of "nameref", sort of.



This is incomplete, but presented for consideration of how to proceed
with it.

There are obviously some additional checks that could be made, e.g.,
be sure that a PM_FAKENAMEREF is also a PM_SCALAR and is not a numeric
subtype, etc.

With this patch:

% typeset -n foo=bar
% bar=hello
% echo $foo
hello

However, it doesn't work for ${foo} because the itype_end() test in
paramsubst() doesn't account for the braces.


diff --git a/Src/builtin.c b/Src/builtin.c
index 08be1ac..8d8b125 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -120,7 +120,7 @@ static struct builtin builtins[] =
     BUILTIN("trap", BINF_PSPECIAL | BINF_HANDLES_OPTS, bin_trap, 0, -1, 0, NULL, NULL),
     BUILTIN("true", 0, bin_true, 0, -1, 0, NULL, NULL),
     BUILTIN("type", 0, bin_whence, 0, -1, 0, "ampfsSw", "v"),
-    BUILTIN("typeset", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klprtuxmz", NULL),
+    BUILTIN("typeset", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klprtuxmzn", NULL),
     BUILTIN("umask", 0, bin_umask, 0, 1, 0, "S", NULL),
     BUILTIN("unalias", 0, bin_unhash, 1, -1, 0, "ms", "a"),
     BUILTIN("unfunction", 0, bin_unhash, 1, -1, 0, "m", "f"),
@@ -2369,6 +2369,11 @@ bin_typeset(char *name, char **argv, Options ops, int func)
 	else if (OPT_PLUS(ops,optval))
 	    off |= bit;
     }
+    if (OPT_MINUS(ops,'n')) {
+	on |= PM_FAKENAMEREF;
+    } else if (on || OPT_PLUS(ops,'n')) {
+	off |= PM_FAKENAMEREF;
+    }
     roff = off;
 
     /* Sanity checks on the options.  Remove conflicting options. */
diff --git a/Src/subst.c b/Src/subst.c
index a2bb648..842eb03 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -2237,9 +2237,11 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
 	while (inull(*s))
 	    s++;
 	v = (Value) NULL;
-    } else if (aspar) {
+    } else if (aspar || ((s = itype_end(s, IIDENT, 0)) && !*s)) {
+	struct value vtmp;
+	char *stmp = s = idbeg;
 	/*
-	 * No subexpression, but in any case the value is going
+	 * No subexpression, but in any case the value may be going
 	 * to give us the name of a parameter on which we do
 	 * our remaining processing.  In other words, this
 	 * makes ${(P)param} work like ${(P)${param}}.  (Probably
@@ -2247,12 +2249,20 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
 	 * and it's been kludged into the subexp code because no
 	 * opportunity for a kludge has been neglected.)
 	 */
-	if ((v = fetchvalue(&vbuf, &s, 1, (qt ? SCANPM_DQUOTED : 0)))) {
-	    val = idbeg = getstrvalue(v);
-	    subexp = 1;
-	} else
+	if ((v = fetchvalue(&vtmp, &stmp, 1, (qt ? SCANPM_DQUOTED : 0)))) {
+	    if (aspar || (v->pm->node.flags & PM_FAKENAMEREF)) {
+		s = stmp;
+		vbuf = vtmp;
+		val = idbeg = getstrvalue(v);
+		aspar = subexp = 1;
+	    }
+	} else if (aspar)
 	    vunset = 1;
-    }
+	if (!aspar) {
+	    v = (Value) NULL;
+	}
+    } else
+	s = idbeg;
     /*
      * We need to retrieve a value either if we haven't already
      * got it from a subexpression, or if the processing so
diff --git a/Src/zsh.h b/Src/zsh.h
index 94e9ffc..dfd9c53 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1661,6 +1661,7 @@ struct tieddata {
 
 #define PM_KSHSTORED	(1<<17) /* function stored in ksh form              */
 #define PM_ZSHSTORED	(1<<18) /* function stored in zsh form              */
+#define PM_FAKENAMEREF	(1<<19) /* behaves like a ksh nameref, sort of      */
 
 /* Remaining flags do not correspond directly to command line arguments */
 #define PM_LOCAL	(1<<21) /* this parameter will be made local        */



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