* assoc array assignment problem. @ 1999-09-21 1:37 Tanaka Akira 1999-09-21 4:59 ` Bart Schaefer 0 siblings, 1 reply; 5+ messages in thread From: Tanaka Akira @ 1999-09-21 1:37 UTC (permalink / raw) To: zsh-workers Z(2):akr@localhost% Src/zsh -f localhost% typeset -A arr localhost% a='$b' localhost% b='c' localhost% arr[$a]=d localhost% print -lr - ${(kv)arr} c d localhost% Hm. Variable expansion is performed twice. I think it should be: localhost% print -lr - ${(kv)arr} $b d localhost% -- Tanaka Akira ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: assoc array assignment problem. 1999-09-21 1:37 assoc array assignment problem Tanaka Akira @ 1999-09-21 4:59 ` Bart Schaefer 1999-09-28 12:15 ` Peter Stephenson 0 siblings, 1 reply; 5+ messages in thread From: Bart Schaefer @ 1999-09-21 4:59 UTC (permalink / raw) To: Tanaka Akira, zsh-workers On Sep 21, 10:37am, Tanaka Akira wrote: } Subject: assoc array assignment problem. } } Z(2):akr@localhost% Src/zsh -f } localhost% typeset -A arr } localhost% a='$b' } localhost% b='c' } localhost% arr[$a]=d } localhost% print -lr - ${(kv)arr} } c } d } localhost% } } Hm. Variable expansion is performed twice. This is not an associative array problem; it affects all arrays. Note: zagzig<17> q=() zagzig<18> g=7 zagzig<19> f='$g' zagzig<20> q[$f]=seven zagzig<21> print $#q $q 7 seven zagzig<22> The first substitution happens at the expected time, during evaluation of the line. The second one happens at execute time in addvars() -- assignment is implemented as if `x=y somecommand` where somecommand is null. addvars() calls setsparam(), which discovers that there is no parameter named "q[$g]" and therefore creates "q" and then makes a call to getvalue() to retrieve a Value structure for the parameter that it just created. getvalue() then expands $g (as it would for ${q[$g]} in which the stuff inside the ${ } has _not_ previously been expanded) and you get the effect above. And you can't even protect it with double-quoting, though using single quotes counterintuitively (but expectedly, given the explaination above) produces the desired result: zagzig<26> arr['$a']=d zagzig<27> print -lr - ${(kv)arr} $x d zagzig<28> I really have no idea when this got introduced. It might have something to do with zsh-workers/4826 and follow-ons, back last year; 3.1.5-pws-4 would be it, but I no longer have anything that old around to try. The right thing would be for the parser to know that it shouldn't expand inside the [] on the left-hand side of an assignment, thereby delaying the one interesting expansion to getvalue(); but that may be a bit too much to bite off ... -- Bart Schaefer Brass Lantern Enterprises http://www.well.com/user/barts http://www.brasslantern.com ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: assoc array assignment problem. 1999-09-21 4:59 ` Bart Schaefer @ 1999-09-28 12:15 ` Peter Stephenson 1999-09-28 13:04 ` Peter Stephenson 0 siblings, 1 reply; 5+ messages in thread From: Peter Stephenson @ 1999-09-28 12:15 UTC (permalink / raw) To: zsh-workers "Bart Schaefer" wrote: > } Hm. Variable expansion is performed twice. > > This is not an associative array problem; it affects all arrays. Note: > > zagzig<17> q=() > zagzig<18> g=7 > zagzig<19> f='$g' > zagzig<20> q[$f]=seven > zagzig<21> print $#q $q > 7 seven > zagzig<22> > > The first substitution happens at the expected time, during evaluation > of the line. The second one happens at execute time in addvars() -- > assignment is implemented as if `x=y somecommand` where somecommand is > null. Two comments: - addvars() is performing an initial substitution on the LHS, but the parameter expansion code isn't; with $q[$f], nothing gets substituted until the look up for q[$f] on hitting the first `$'. I don't see why addvars() needs to do that initial substitution, though: in the old days, you could do `foo=bar; $foo=something' to set bar, but now you can't. So I suspect that first substitution may be redundant, and that all substitution should be delayed until the parameter code, as it is when a parameter is being used rather than asssigned. However, this does untokenize the name, which maybe partly explains the following behaviour. - The weirdest thing seems to me to be that getindex() is untokenizing the [...] part, only for it to be retokenized again down in getarg(). This can't be right, can it? It would be far better if what getindex() gets is correctly tokenized according to whether or not you want it substituted (including not untokenizing it in addvars()), and if that was respected this problem would go away. That should be OK, because the subscript should already be tokenized in just the same way as the parameter expansion. Shouldn't it? - (three comments, among the comments are): Looking at addvars(), it seems that the following (with no existing $foo): setopt restricted foo=bar cat /dev/null could be bad for business, but AIX is unable even to give me the satisfaction of a core dump. I get fed up with this shell sometimes. Maybe I'll take a look at this, but I'd prefer to retreat into a hole in the ground. -- Peter Stephenson <pws@ibmth.df.unipi.it> Tel: +39 050 844536 WWW: http://www.ifh.de/~pws/ Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: assoc array assignment problem. 1999-09-28 12:15 ` Peter Stephenson @ 1999-09-28 13:04 ` Peter Stephenson 1999-09-30 16:58 ` Bart Schaefer 0 siblings, 1 reply; 5+ messages in thread From: Peter Stephenson @ 1999-09-28 13:04 UTC (permalink / raw) To: zsh-workers I wrote: > Two comments: This is supposed to take care of the first and the third. Now the following works: typeset -A assoc foo=random arg='$foo' assoc[$arg]=bar print ${(kv)assoc} $foo bar and the restricted mode crash should go, too. I don't think either of these should have adverse effects. The other issue --- tokenization and retokenization of the subscript --- turns out to be more complicated. In an expression like "$foo[(r)b*]", you would indeed need to tokenize what you have already. Perhaps that could be done by paramsubst(), which knows if it's in quotes, but as the code that uses this is buried in fetchvalue() it's hard to be sure. Alternatively, it could be given a flag that it was in double quotes and so needed (with certain flags only) to retokenize the expression. Alternatively, it could be left as it is with consequent inefficiency. I discovered another problem. foo= assoc[$foo]=rod print ${(kv)assoc} rod $foo bar unset assoc[$foo] assoc[] "assoc[$foo]" "assoc[]" print ${(kv)assoc} rod $foo bar I haven't found anything which gets rid of it. --- Src/exec.c.subst Tue Sep 28 13:58:30 1999 +++ Src/exec.c Tue Sep 28 14:37:08 1999 @@ -1336,9 +1336,6 @@ for (n = firstnode(l); n; incnode(n)) { v = (Varasg) getdata(n); name = dupstring(v->name); - singsub(&name); - if (errflag) - return; untokenize(name); if (xtr) fprintf(stderr, "%s=", name); @@ -1370,15 +1367,13 @@ } if (xtr) fprintf(stderr, "%s ", val); - if (export) { - if (export < 0) { - /* We are going to fork so do not bother freeing this */ - pm = (Param) paramtab->removenode(paramtab, name); - if (isset(RESTRICTED) && (pm->flags & PM_RESTRICTED)) { - zerr("%s: restricted", pm->nam, 0); - zsfree(val); - return; - } + if (export && !strchr(name, '[')) { + if (export < 0 && isset(RESTRICTED) && + (pm = (Param) paramtab->removenode(paramtab, name)) && + (pm->flags & PM_RESTRICTED)) { + zerr("%s: restricted", pm->nam, 0); + zsfree(val); + return; } allexp = opts[ALLEXPORT]; opts[ALLEXPORT] = 1; -- Peter Stephenson <pws@ibmth.df.unipi.it> Tel: +39 050 844536 WWW: http://www.ifh.de/~pws/ Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: assoc array assignment problem. 1999-09-28 13:04 ` Peter Stephenson @ 1999-09-30 16:58 ` Bart Schaefer 0 siblings, 0 replies; 5+ messages in thread From: Bart Schaefer @ 1999-09-30 16:58 UTC (permalink / raw) To: zsh-workers On Sep 28, 3:04pm, Peter Stephenson wrote: } Subject: Re: assoc array assignment problem. } } I discovered another problem. } } foo= } assoc[$foo]=rod } print ${(kv)assoc} } rod $foo bar The fact that you get a leading space there even when there are no quotes around the expansion should be telling us something. If the key were the empty string, print would drop it and you'd get "rod $foo bar" with no leading space. The key for the "rod" value in the $assoc hash table is "\233" (meta-escape). Now, the "\233" is coming from singsub(&s) where s = "$foo" at line 863 in getarg(). So perhaps the following will take care of it; I've tried a few tests and didn't find anything that it breaks, but maybe someone else will discover a reason this needs to be more complicated. Index: Src/params.c =================================================================== @@ -869,6 +869,7 @@ ht = newparamtable(17, v->pm->nam); v->pm->sets.hfn(v->pm, ht); } + untokenize(s); if (!(v->pm = (Param) ht->getnode(ht, s))) { HashTable tht = paramtab; paramtab = ht; -- Bart Schaefer Brass Lantern Enterprises http://www.well.com/user/barts http://www.brasslantern.com ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~1999-09-30 17:00 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 1999-09-21 1:37 assoc array assignment problem Tanaka Akira 1999-09-21 4:59 ` Bart Schaefer 1999-09-28 12:15 ` Peter Stephenson 1999-09-28 13:04 ` Peter Stephenson 1999-09-30 16:58 ` Bart Schaefer
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/zsh/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).