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

[PATCH] Fix saving and restoring of subscripted inline assignments



When an external command is run with a subscripted inline assignment, the assigned parameter is restored to its previous value after the command returns:

% export var=12345
% var[2,4]=ABC printenv var
1ABC5
% typeset -p var
export var=12345

The same isn't true for builtins and user defined functions:

% myprintenv() { echo ${(P)1} }
% var[2,4]=ABC myprintenv var
1ABC5
% typeset -p var
export var=1ABC5

The former works because the parameter is only assigned in the forked process used to run the external command. Thus the value of the parameter remains unchanged in the main shell.

In the case of the latter, everything runs in the same process. There is code to save and restore parameters modified by inline assignments but that code doesn't account for the fact that the assigned parameters may be subscripted. In the example above, it tries to save and restore the parameter var[2,4], instead of the parameter var, which naturally fails. This looks more like a bug than a feature. The patch below fixes it by taking into account the possible presence of subscripts.

Fix saving and restoring of subscripted inline assignments

Philippe

diff --git a/Src/exec.c b/Src/exec.c
index 17899262d..20caf40d1 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -4467,14 +4467,16 @@ static void
 save_params(Estate state, Wordcode pc, LinkList *restore_p, LinkList *remove_p)
 {
     Param pm;
-    char *s;
     wordcode ac;
 
     *restore_p = newlinklist();
     *remove_p = newlinklist();
 
     while (wc_code(ac = *pc) == WC_ASSIGN) {
-	s = ecrawstr(state->prog, pc + 1, NULL);
+	char *s = ecrawstr(state->prog, pc + 1, NULL);
+	char *ss = itype_end(s, INAMESPC, 0);
+	int slen = *ss == '[' || *ss == Inbrack ? ss - s : strlen(s);
+	addlinknode(*remove_p, s = dupstring_wlen(s, slen));
 	if ((pm = (Param) paramtab->getnode(paramtab, s))) {
 	    Param tpm = NULL;
 	    if (pm->env)
@@ -4503,11 +4505,9 @@ save_params(Estate state, Wordcode pc, LinkList *restore_p, LinkList *remove_p)
 		tpm->node.nam = pm->node.nam;
 		copyparam(tpm, pm, 1);
 	    }
-	    addlinknode(*remove_p, dupstring(s));
 	    if (tpm)
 		addlinknode(*restore_p, tpm);
-	} else
-	    addlinknode(*remove_p, dupstring(s));
+	}
 
 	pc += (WC_ASSIGN_TYPE(ac) == WC_ASSIGN_SCALAR ?
 	       3 : WC_ASSIGN_NUM(ac) + 2);
diff --git a/Test/A06assign.ztst b/Test/A06assign.ztst
index d653d75b3..3cb73a3fe 100644
--- a/Test/A06assign.ztst
+++ b/Test/A06assign.ztst
@@ -539,12 +539,16 @@
   call
   HELLO=${HELLO}liness call
   call
+  HELLO[2,4]=oo call
+  call
   unset HELLO
 0:save and restore when using original value in temporary
 >world
 >universe
 >world
 >worldliness
+>world
+>wood
 >world
 
  (integer i n x


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