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

Re: Typeset with array



On Fri, 19 Jun 2015 12:39:30 +0100
Peter Stephenson <p.stephenson@xxxxxxxxxxx> wrote:
> Also, execcmd() needs some work --- currently, the reserved word
> doesn't actually force you to use a builtin of the same name, we just
> rely on execcmd() finding the builtin in the hash table.  If that was
> disabled but there was an external command of the same name it would
> execute that, missing the special assigment commands on the end.  This
> probably isn't the right thing to do.

This fixes this: we look up the same handler as the builtin for the
reserved word, but ignore whether the builtin is disabled because we
know the reserved word is enabled.  We now force the WC_TYPESET
interface even if there aren't any assignments to ensure consistency.

"builtin typeset" used the builtin interface even if the reserved word
is enabled --- I think that's correct.

One drive-by fix to ensure we don't force an array where there's an
existing parameter we can use that's a hash.

With a few more tests I think this is just about ready for the master
branch.

pws


diff --git a/Src/builtin.c b/Src/builtin.c
index 5eb7bfb..dd28c8b 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2020,7 +2020,8 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
 
     /* attempting a type conversion, or making a tied colonarray? */
     tc = 0;
-    if (ASG_ARRAYP(asg) && PM_TYPE(on) == PM_SCALAR)
+    if (ASG_ARRAYP(asg) && PM_TYPE(on) == PM_SCALAR &&
+	!(usepm && (PM_TYPE(pm->node.flags) & (PM_ARRAY|PM_HASHED))))
 	on |= PM_ARRAY;
     if (usepm && ASG_ARRAYP(asg) && newspecial == NS_NONE &&
 	PM_TYPE(pm->node.flags) != PM_ARRAY &&
diff --git a/Src/exec.c b/Src/exec.c
index 6066d55..57e8f63 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -2543,14 +2543,26 @@ execcmd(Estate state, int input, int output, int how, int last1)
 	    checked = !has_token(cmdarg);
 	    if (!checked)
 		break;
-	    if (!(cflags & (BINF_BUILTIN | BINF_COMMAND)) &&
-		(hn = shfunctab->getnode(shfunctab, cmdarg))) {
-		is_shfunc = 1;
-		break;
-	    }
-	    if (!(hn = builtintab->getnode(builtintab, cmdarg))) {
-		checked = !(cflags & BINF_BUILTIN);
-		break;
+	    if (type == WC_TYPESET &&
+		(hn = builtintab->getnode2(builtintab, cmdarg))) {
+		/*
+		 * If reserved word for typeset command found (and so
+		 * enabled), use regardless of whether builtin is
+		 * enabled as we share the implementation.
+		 *
+		 * Reserved words take precedence over shell functions.
+		 */
+		checked = 1;
+	    } else {
+		if (!(cflags & (BINF_BUILTIN | BINF_COMMAND)) &&
+		    (hn = shfunctab->getnode(shfunctab, cmdarg))) {
+		    is_shfunc = 1;
+		    break;
+		}
+		if (!(hn = builtintab->getnode(builtintab, cmdarg))) {
+		    checked = !(cflags & BINF_BUILTIN);
+		    break;
+		}
 	    }
 	    orig_cflags |= cflags;
 	    cflags &= ~BINF_BUILTIN & ~BINF_COMMAND;
diff --git a/Src/parse.c b/Src/parse.c
index a95ec60..5357851 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -131,13 +131,11 @@ struct heredocs *hdocs;
  *     - followed by strings
  *
  *   WC_TYPESET
- *     Variant of WC_SIMPLE used when trailing assignments are
- *     needed.  N.B.: if they are not, we use WC_SIMPLE even
- *     if this is a TYPESET keyword.
+ *     Variant of WC_SIMPLE used when TYPESET reserved word found.
  *     - data contains the number of string arguments (plus command)
  *     - followed by strings
  *     - followed by number of assignments
- *     - followed by assignments
+ *     - followed by assignments if non-zero number.
  *
  *   WC_SUBSH
  *     - data unused
@@ -1728,7 +1726,7 @@ static int
 par_simple(int *cmplx, int nr)
 {
     int oecused = ecused, isnull = 1, r, argc = 0, p, isfunc = 0, sr = 0;
-    int c = *cmplx, nrediradd, assignments = 0, ppost = 0;
+    int c = *cmplx, nrediradd, assignments = 0, ppost = 0, is_typeset = 0;
     wordcode postassigns = 0;
 
     r = ecused;
@@ -1814,7 +1812,7 @@ par_simple(int *cmplx, int nr)
 	    incmdpos = 0;
 
 	    if (tok == TYPESET)
-		intypeset = 1;
+		intypeset = is_typeset = 1;
 
 	    if (!isset(IGNOREBRACES) && *tokstr == Inbrace)
 	    {
@@ -2024,9 +2022,12 @@ par_simple(int *cmplx, int nr)
     intypeset = 0;
 
     if (!isfunc) {
-	if (postassigns) {
+	if (is_typeset) {
 	    ecbuf[p] = WCB_TYPESET(argc);
-	    ecbuf[ppost] = postassigns;
+	    if (postassigns)
+		ecbuf[ppost] = postassigns;
+	    else
+		ecadd(0);
 	} else
 	    ecbuf[p] = WCB_SIMPLE(argc);
     }



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