about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@zsh.org>2015-06-19 14:58:37 +0100
committerPeter Stephenson <pws@zsh.org>2015-06-19 14:58:37 +0100
commit879ef7e076289ff09d600dc3bb9c29ce441265db (patch)
tree7e60502da2192c54ac936a7d35117a06b35236df
parent601be75605b4e3f78393950d089e6c8e5d555567 (diff)
downloadzsh-879ef7e076289ff09d600dc3bb9c29ce441265db.tar.gz
zsh-879ef7e076289ff09d600dc3bb9c29ce441265db.tar.xz
zsh-879ef7e076289ff09d600dc3bb9c29ce441265db.zip
Expand non-assignment arguments in assign list consistently.
-rw-r--r--Src/exec.c48
-rw-r--r--Test/B02typeset.ztst2
2 files changed, 46 insertions, 4 deletions
diff --git a/Src/exec.c b/Src/exec.c
index ef3e85948..967f86e23 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -3485,21 +3485,63 @@ execcmd(Estate state, int input, int output, int how, int last1)
 		    state->pc = assignspc;
 		    assigns = newlinklist();
 		    while (postassigns--) {
-			Asgment asg = (Asgment)zhalloc(sizeof(struct asgment));
 			wordcode ac = *state->pc++;
-			int htok;
 			char *name = ecgetstr(state, EC_DUPTOK, &htok);
+			Asgment asg;
+			int htok;
 			local_list1(svl);
 
 			DPUTS(wc_code(ac) != WC_ASSIGN,
 			      "BUG: bad assignment list for typeset");
 			if (htok) {
 			    init_list1(svl, name);
+			    if (WC_ASSIGN_TYPE(ac) == WC_ASSIGN_SCALAR &&
+				WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC) {
+				char *data;
+				/*
+				 * Special case: this is a name only, so
+				 * it's not required to be a single
+				 * expansion.  Furthermore, for
+				 * consistency with the builtin
+				 * interface, it may expand into
+				 * scalar assignments:
+				 *  ass=(one=two three=four)
+				 *  typeset a=b $ass
+				 */
+				/* Unused dummy value for name */
+				(void)ecgetstr(state, EC_DUPTOK, &htok);
+				prefork(&svl, PREFORK_TYPESET);
+				if (errflag) {
+				    state->pc = opc;
+				    break;
+				}
+				globlist(&svl, 0);
+				if (errflag) {
+				    state->pc = opc;
+				    break;
+				}
+				while ((data = ugetnode(&svl))) {
+				    char *ptr;
+				    asg = (Asgment)zhalloc(sizeof(struct asgment));
+				    asg->is_array = 0;
+				    if ((ptr = strchr(data, '='))) {
+					*ptr++ = '\0';
+					asg->name = data;
+					asg->value.scalar = ptr;
+				    } else {
+					asg->name = data;
+					asg->value.scalar = NULL;
+				    }
+				    uaddlinknode(assigns, &asg->node);
+				}
+				continue;
+			    }
 			    prefork(&svl, PREFORK_SINGLE);
-			    name= empty(&svl) ? "" :
+			    name = empty(&svl) ? "" :
 				(char *)getdata(firstnode(&svl));
 			}
 			untokenize(name);
+			asg = (Asgment)zhalloc(sizeof(struct asgment));
 			asg->name = name;
 			if (WC_ASSIGN_TYPE(ac) == WC_ASSIGN_SCALAR) {
 			    char *val = ecgetstr(state, EC_DUPTOK, &htok);
diff --git a/Test/B02typeset.ztst b/Test/B02typeset.ztst
index 57a7caa12..1819b6c84 100644
--- a/Test/B02typeset.ztst
+++ b/Test/B02typeset.ztst
@@ -231,7 +231,7 @@
 
  typeset -T THIS will not work
 1:Tied array syntax
-?(eval):typeset:1: -T requires names of scalar and array
+?(eval):typeset:1: too many arguments for -T
 
  local array[2]=x
 1:Illegal local array element assignment