zsh-workers
 help / color / mirror / code / Atom feed
* Re: BUG: zsh-3.1.5-pws-14: parameter expansion not working properly
@ 1999-04-15  6:49 Sven Wischnowsky
  1999-04-15 11:03 ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Sven Wischnowsky @ 1999-04-15  6:49 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> Now that I've seen/used it in practice a few times, I'm not so sure any
> more.  The more radical change, and one which bothers me a lot, is the
> effect when the array has more than one element:
> 
> 	foo=(xa yb zc)
> 	print -l "${${(@)foo}[1]}" "${(@)${foo}[1]}"
> 
> Zsh 3.0.5 prints
> 
> 	xa
> 	x
> 
> But 3.1.5-pws-14 prints
> 
> 	x
> 	xa
> 
> That's completely reversed the semantics, and thus is a serious problem.

(Do you really get `xa' in the last case?)

This (and the need to repeat the `(@)') comes from the fact that
multsub() doesn't get any information about where the words came
from. I.e. if they are an `array' (even if only one string) or not. I
already said this at least once. To solve this better we would need a
way to make `paramsubst()' notify `multsub()' if the thing is an
array. This could be done by using a subst.c-global variable that is
set in multsub() and paramsubst() and tested in multsub() after
prefork(), of course.
And then we would have to decide when we want to accept an array at
the call of multsub(). Always, if the sub-expression is an array? Even
if the whole thing is in double quotes? If it is in double quotes and
we don't want it always, when? Hm, maybe when the `(@)' flag is given
or the things came from an array. But then there would be no way to
make an array be treated as a scalar further down up then by using
the `(j:...:)' flag. But then again, this may be ok.

Or maybe we make the inner expression be taken as an array if it is a
parameter expansion that results in an array and make it be used as a
scalar value in all other cases, independent of quoting (which means
that the quoting will only have it's normal effect on the inner
expressions). That way the `(@)' has only an effect to the `outside',
not on the treatment of an inner expression when given in an outer
one (something I already described -- and didn't like, too). This
would give the same as 3.0.5 again for your example above, with the
`x' returned as an array, which noone will notice (and the `(@)'
wouldn't have any effect in `"${(@)${foo}[1]}"').

There may be other problems I don't see, though (apart from changing
the manual again).

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 16+ messages in thread
* Re: BUG: zsh-3.1.5-pws-14: parameter expansion not working properly
@ 1999-05-10  9:13 Sven Wischnowsky
  0 siblings, 0 replies; 16+ messages in thread
From: Sven Wischnowsky @ 1999-05-10  9:13 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> The only good alternatives at this point are probably [a] go back to the
> 3.0 behavior of (@), or [b] leave it the way this mult_isarr patch leaves
> it.  Can anyone think of something in between that makes sense?

It just occured to me that I didn't say that I would be in favor of
using the patch. I.e. to keep the things we have done to the `(@)'
stuff plus the patch. I consider the previous patches important,
because it allows one to distinguish arrays with one element from
strings and this last patch made things more consistent.

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 16+ messages in thread
* Re: BUG: zsh-3.1.5-pws-14: parameter expansion not working properly
@ 1999-04-16  7:36 Sven Wischnowsky
  1999-04-16  7:48 ` Andrej Borsenkow
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Sven Wischnowsky @ 1999-04-16  7:36 UTC (permalink / raw)
  To: zsh-workers


[ There is a little patchlet below. I don't suggest using it to
  everyone just now, it's just that I can think about this better when 
  I have cod to play with. Didn't have the time for this yesterday. ]

Bart Schaefer wrote:

> Think about it this way:
> 
> 1. The expression "${(@)foo}" produces an array of quoted words.
> 
> 2. In the expression "${${(@)foo}}", the outer ${ ... } can include both
> flags in leading () and subscripts in trailing [].  The inner ${(@)foo}
> should *still* produce an array of quoted words, to which the flags and
> subscripts of the outer ${ ... } are applied.
> 
> 3. To work like the old zsh, the subscripts should apply *before* any
> split or join operation implied by the flags (or by the lack of a flag).
> The exception being the (P) flag, because it is defined to change the
> interpretation of the parameter's name and thus must "bind tighter" than
> anything including subscripts.
> 
> In pws-14+, at step (2), the inner expression does NOT produce an array
> unless the outer expression uses (@).  This is what I think is wrong.

Agreed (again) -- I mentioned this in 5841.

> I don't think it's possible to "pass down" from paramsubst-->multsub
> the knowledge of whether an array should be returned [except when (P)];
> it has to be "passed up," multsub<--prefork<--stringsubst<--paramsubst.

I don't understand the difference between making the the arrows point
to the left or the right here.

> Beyond those three steps, things get fuzzy.  In trying to reason about
> this without actually seeing it in action, I *believe* that it's OK if:
> 
> 4. *After* the subscripts are applied, the outer ${ ... } joins the
> quoted words into a single string, *unless*: the (@) flag is present
> or the [@] subscript was applied, and the (j) flag is not present.

This one is very important. If we make it this way (and the patch
below does that), it means that we still need the plethora of `(@)'
flags: with `foo' being an array "${${(@)foo}[1,2]}" selects the first 
two elements of it, joins them, and returns *one* string.
So, this doesn't help much to simplify the syntax needed in some of
the more common cases.

> I know that's still a change from the old behavior, so I can't be sure
> that it'll work out, but I *think* it will.
> 
> 5. Finally, the string is split again according to SHWORDSPLIT or the
> (s) flag.
> 
> 6. If there is a split, or if (@) or [@] was present, an array of quoted
> words is returned.  If there's another outer ${ ... }, go to step (3).

These two are done in a piece of code I didn't change anyway and were
only affected by the outcome of the call to multsub().
> 
> } With respect to the outer paramsubst()s this would make things
> } independent of whether the whole thing is in quotes or not, only the
> } inner paramsubst()s `control' if the outer ones work on an array
> } by testing if the thing is in quotes and if the `(@)' flag (or
> } something similar like the `s' flag or `=') is used.
> 
> As I just said, I don't *think* it should be independent of whether the
> whole thing is in quotes.  The quotes should affect what happens at (4),
> but they should *not* affect what happens at 2-->3 or 6-->3.

Obviously, I wasn't clear enough again. In terms of code: I wanted to
say that at the call to multsub(), the information about whether we
are in quotes should not be used. But of course, it should be used
after that -- as usual. Only make sure that we get correct information 
about the array-ness whether we are in quotes or not. And of course,
the quotes also affect the way the inner expression is expanded and
hence if it yields an array or not.

> Does that make sense?

Yes, and the behavior with the patch looks better than before to
me. We only need to discuss the `is there a way to avoid the need for
the many (@) flags' thing.

Bye
 Sven

--- os/subst.c	Wed Apr 14 11:58:36 1999
+++ Src/subst.c	Fri Apr 16 09:09:32 1999
@@ -245,35 +245,43 @@
  * the result is stored in *a. If `a' is zero a multiple word result is *
  * joined using sep or the IFS parameter if sep is zero and the result  *
  * is returned in *s.  The return value is true iff the expansion       *
- * resulted in an empty list                                            */
+ * resulted in an empty list.                                           *
+ * The mult_isarr variable is used by paramsubst() to tell if it yields *
+ * an array.                                                            */
+
+static int mult_isarr;
 
 /**/
 static int
 multsub(char **s, char ***a, int *isarr, char *sep)
 {
     LinkList foo;
-    int l;
+    int l, omi = mult_isarr;
     char **r, **p;
 
+    mult_isarr = 0;
     foo = newlinklist();
     addlinknode(foo, *s);
     prefork(foo, 0);
     if (errflag) {
 	if (isarr)
 	    *isarr = 0;
+	mult_isarr = omi;
 	return 0;
     }
-    if ((l = countlinknodes(foo)) > 1 || a) {
+    if ((l = countlinknodes(foo))) {
 	p = r = ncalloc((l + 1) * sizeof(char*));
 	while (nonempty(foo))
 	    *p++ = (char *)ugetnode(foo);
 	*p = NULL;
-	if (a) {
+	if (a && mult_isarr) {
 	    *a = r;
 	    *isarr = 1;
+	    mult_isarr = omi;
 	    return 0;
 	}
 	*s = sepjoin(r, NULL);
+	mult_isarr = omi;
 	return 0;
     }
     if (l)
@@ -282,6 +290,7 @@
 	*s = dupstring("");
     if (isarr)
 	*isarr = 0;
+    mult_isarr = omi;
     return !l;
 }
 
@@ -977,16 +986,12 @@
 	skipparens(*s, *s == Inpar ? Outpar : Outbrace, &s);
 	sav = *s;
 	*s = 0;
-	if (multsub(&val, ((!aspar && (!quoted || nojoin)) ? &aval : NULL),
-		    &isarr, NULL) &&
-	    quoted) {
+	if (multsub(&val, (aspar ? NULL : &aval), &isarr, NULL) && quoted) {
 	    isarr = -1;
 	    aval = alloc(sizeof(char *));
 	    aspar = 0;
 	} else if (aspar)
 	    idbeg = val;
-	if (isarr)
-	    isarr = -1;
 	copied = 1;
 	*s = sav;
 	v = (Value) NULL;
@@ -1465,6 +1470,7 @@
 	val = dupstring(buf);
 	isarr = 0;
     }
+    mult_isarr = isarr;
     if (isarr > 0 && !plan9 && (!aval || !aval[0])) {
 	val = dupstring("");
 	isarr = 0;

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 16+ messages in thread
* Re: BUG: zsh-3.1.5-pws-14: parameter expansion not working properly
@ 1999-04-15 12:08 Sven Wischnowsky
  1999-04-15 20:10 ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Sven Wischnowsky @ 1999-04-15 12:08 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> In what direction is the data flowing at this point?  Up or down the call
> stack?  I think you mean up; but paramsubst() is of course the caller of
> multsub() as well ...

I was slightly confused by this up/down thing, too. Again:

We have this call chain:

   A paramsubst(), calls
   B    multsub(), calls
   C       paramsubst()

Now, we could make the multsub() save (and at the end restore) the
value of, say `static int mult_isarr'. It then sets it to zero and
calls paramsubst() (via prefork(), as usual). At the end of
paramsubst() we set `mult_isarr = isarr'.

After the prefork(), multsub() now knows that the list it gets was an
array expression if `mult_isarr != 0'.

This was the first part of what I meant -- getting information about
the array'ness. With the other part I meant the call to multsub() we
are talking about here (line 980). There we have to decide if we give
`&aval' or `NULL' to multsub() where it is used to decide if the
joining should be done -- the problem to solve, as you said.

> Ideally, I think, it should still happen after, but the (non-)array-ness
> of whatever comes back from prefork() should be propagated up through
> isarr by multsub() -- which brings us back to the static global.

And this is what I meant (I just think less in terms of `isarr' then
in terms of `aval' -- and deciding when to give it to multsub()).

> No, that's too confusing and not necessary.  The only real issue is the
> "precedence" if you will, of subscripting vs. joining.  We "solved" the
> problem of subscripting scalars that were accidentally treated as arrays,
> by forcing all quoted arrays to be taken as scalars; I think we need to
> back off from that and concentrate on not accidentally treating scalars
> as arrays.

I don't think I understand this. And I thought I kept it from arrays
being accidentally being treated as scalars.

>From your first mail about this I got the impression that you wanted
nested expressions to keep their knowledge about whether they are
arrays or not, so that (with foo being an array) in "${${${${(@)foo}}}[1]}"
the outer paramsubst() (A) gets notified by multsub() (B) that the
inner paramsubst() (C) returned an array and the subscripting gives
the first array element. This `notification' would be done by having
multsub() use `&aval' instead of `&val' and by setting `*isarr', of
course.
With respect to the outer paramsubst()s this would make things
independent of whether the whole thing is in quotes or not, only the
inner paramsubst()s `control' if the outer ones work on an array
by testing if the thing is in quotes and if the `(@)' flag (or
something similar like the `s' flag or `=') is used.

Hope this makes it clearer.

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 16+ messages in thread
* Re: BUG: zsh-3.1.5-pws-14: parameter expansion not working properly
@ 1999-04-12  7:17 Sven Wischnowsky
  1999-04-14 17:27 ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Sven Wischnowsky @ 1999-04-12  7:17 UTC (permalink / raw)
  To: zsh-workers


mason@primenet.com.au wrote:

> Here's a fragment of the expansion similar to that used in
> cvsentries() in Misc/compctl-examples 
> 
> % zsh-3.1.5
> % a=("${(f@)$(echo foo; echo bar)}"); print -l $a
> foo
> bar
> % a=("${${(f@)$(echo foo; echo bar)}:#f*}"); print -l $a
> bar
> % zsh-3.1.5-pws-14
> % a=("${(f@)$(echo foo; echo bar)}"); print -l $a
> foo
> bar
> % a=("${${(f@)$(echo foo; echo bar)}:#f*}"); print -l $a
> 
> %

Yes, this has changed lately because the old behavior sometimes
yielded unpredictable results. The rule of thumb is now that one
should use the `(@)' flag whenever the thing is in double quotes and
one wants to work on arrays.

Bye
 Sven

--- ../zold/Misc/compctl-examples	Mon Oct 26 23:59:45 1998
+++ Misc/compctl-examples	Mon Apr 12 09:14:44 1999
@@ -11,15 +11,15 @@
 # page.
 #
 #------------------------------------------------------------------------------
-hosts=("${${(s: :)${(s:	:)${${(f)$(</etc/hosts)}%%\#*}#*[ 	]*}}:#}")
-ports=( "${${${(f)$(</etc/services)}:#\#*}%%[ 	]*}" )
+hosts=("${(@)${(@s: :)${(@s:	:)${(@)${(@f)$(</etc/hosts)}%%\#*}#*[ 	]*}}:#}")
+ports=( "${(@)${(@)${(@f)$(</etc/services)}:#\#*}%%[ 	]*}" )
 
 # groups=( $(cut -d: -f1 /etc/group) )
 # groups=( $(ypcat group.byname | cut -d: -f1) ) # if you use NIS
 
 # It can be done without forking, but it used too much memory in old zsh's:
-groups=( "${${(f)$(</etc/group)}%%:*}" )
-#groups=( "${${(f)$(ypcat groups)}%%:*}" ) # if you use NIS
+groups=( "${(@)${(@f)$(</etc/group)}%%:*}" )
+#groups=( "${(@)${(@f)$(ypcat groups)}%%:*}" ) # if you use NIS
 
 # Completion for zsh builtins.
 compctl -z -P '%' bg
@@ -251,7 +251,7 @@
 # Note that 'r[-exec,;]' must come first
 if [[ -r /proc/filesystems ]]; then
     # Linux
-    filesystems='"${${(f)$(</proc/filesystems)}#*	}"'
+    filesystems='"${(@)${(@f)$(</proc/filesystems)}#*	}"'
 else
     filesystems='ufs 4.2 4.3 nfs tmp mfs S51K S52K'
 fi
@@ -563,7 +563,7 @@
 cvsentries() {
     setopt localoptions nullglob unset
     if [[ -f ${pref}CVS/Entries ]]; then
-	reply=( "${pref}${^${${${(f@)$(<${pref}CVS/Entries)}:#D*}#/}%%/*}" )
+	reply=( "${pref}${^${(@)${(@)${(f@)$(<${pref}CVS/Entries)}:#D*}#/}%%/*}" )
     fi
 }
 
@@ -574,7 +574,7 @@
 }
 
 cvsrevisions() {
-    reply=( "${${${(M)${(f)$(cvs -q status -vl .)}:#	*}##[ 	]##}%%[ 	]*}" )
+    reply=( "${(@)${(@)${(@M)${(@f)$(cvs -q status -vl .)}:#	*}##[ 	]##}%%[ 	]*}" )
 }
 
 cvsrepositories() {
@@ -582,7 +582,7 @@
     [[ -f CVS/Root ]] && root=$(<CVS/Root)
     reply=(
 	$root/^CVSROOT(:t)
-	"${${(M)${(f)$(<$root/CVSROOT/modules)}:#[^#]*}%%[ 	]*}"
+	"${(@)${(@M)${(@f)$(<$root/CVSROOT/modules)}:#[^#]*}%%[ 	]*}"
     )
 }
 
@@ -622,7 +622,7 @@
 	'c[-1,--rcfile]' -f - \
 	'p[1] s[-b]' -k '(p l c i b a)' - \
 	'c[-1,--queryformat] N[-1,{]' \
-		-s '"${${(f)$(rpm --querytags)}#RPMTAG_}"' -S '}' - \
+		-s '"${(@)${(@f)$(rpm --querytags)}#RPMTAG_}"' -S '}' - \
 	'W[1,-q*] C[-1,-([^-]*|)f*]' -f - \
 	'W[1,-i*], W[1,-q*] C[-1,-([^-]*|)p*]' \
 		-/g '*.rpm' + -f -- rpm
@@ -635,7 +635,7 @@
 function talkmatch {
     local u
     reply=($(users))
-    for u in "${${(f)$(rwho 2>/dev/null)}%%:*}"; do
+    for u in "${(@)${(@f)$(rwho 2>/dev/null)}%%:*}"; do
 	reply=($reply ${u%% *}@${u##* })
     done
 }

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 16+ messages in thread
* BUG: zsh-3.1.5-pws-14: parameter expansion not working properly
@ 1999-04-10 11:28 Geoff Wing
  0 siblings, 0 replies; 16+ messages in thread
From: Geoff Wing @ 1999-04-10 11:28 UTC (permalink / raw)
  To: zsh-workers

Here's a fragment of the expansion similar to that used in
cvsentries() in Misc/compctl-examples 

% zsh-3.1.5
% a=("${(f@)$(echo foo; echo bar)}"); print -l $a
foo
bar
% a=("${${(f@)$(echo foo; echo bar)}:#f*}"); print -l $a
bar
% zsh-3.1.5-pws-14
% a=("${(f@)$(echo foo; echo bar)}"); print -l $a
foo
bar
% a=("${${(f@)$(echo foo; echo bar)}:#f*}"); print -l $a

%
-- 
Geoff Wing   <gcw@pobox.com>            Mobile : (Australia) 0412 162 441
Work URL: http://www.primenet.com.au/   Ego URL: http://pobox.com/~gcw/


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~1999-05-10 10:04 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-04-15  6:49 BUG: zsh-3.1.5-pws-14: parameter expansion not working properly Sven Wischnowsky
1999-04-15 11:03 ` Bart Schaefer
  -- strict thread matches above, loose matches on Subject: below --
1999-05-10  9:13 Sven Wischnowsky
1999-04-16  7:36 Sven Wischnowsky
1999-04-16  7:48 ` Andrej Borsenkow
1999-04-16  9:04   ` Bart Schaefer
1999-04-16  9:26     ` Andrej Borsenkow
1999-04-18 23:39 ` Bart Schaefer
1999-05-07 11:51 ` Peter Stephenson
1999-05-07 13:36   ` Sven Wischnowsky
1999-05-09 17:49     ` Bart Schaefer
1999-04-15 12:08 Sven Wischnowsky
1999-04-15 20:10 ` Bart Schaefer
1999-04-12  7:17 Sven Wischnowsky
1999-04-14 17:27 ` Bart Schaefer
1999-04-10 11:28 Geoff Wing

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).