zsh-workers
 help / color / mirror / code / Atom feed
* Re: Word splitting in zsh
       [not found] <000d01c0926a$ce26c590$21c9ca95@mow.siemens.ru>
@ 2001-02-09 18:18 ` Bart Schaefer
  2001-02-10 20:24   ` PATCH: 3.1.9-dev-8: " Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Bart Schaefer @ 2001-02-09 18:18 UTC (permalink / raw)
  To: Deborah Ariel Pickett, zsh-workers

(Distribution changed to -workers)

On Feb 9, 10:34am, Andrej Borsenkow wrote:
}
} > zagzig% echo $ZSH_VERSION
} > 3.1.9-dev-8
} > zagzig% set "a1 a2 a3" b c
} > zagzig% print -l ${1+"$@"}
} > a1 a2 a3 b c						<-- Yipes!
} 
} Well, this is "correct" *zsh* behaviour. The part after `+' is a word - not
} array. And is taken as single word and is never splitted. What happens here,
} is
} 
} - zsh evaluates "$@" that gives you array with three elements
} - but because of "scalar context" in this case (the best I can call it) array
} is concatenated forming the above value.

Yes, your analysis is correct; the bug is that there should not be a scalar
context there.  The effect of ${NAME:+WORD} and ${NAME:-WORD} should be to
replace the context of NAME with the context of WORD in the event that NAME
is (or not) set.  Put another way, the type of NAME should only determine
the type of the whole ${...} when NAME really is being substituted.

(One could argue, then, that ${NAME:=WORD} should make NAME into an array if
WORD expands to an array.  In fact, there are a number of things that this
would make simpler, though there also may be some things it would break.)

} Even worse, it is inconsistent with everything else - array joining is
} supposed to use IFS ... but it does not in this case.

Well, that ought to be relatively simple to fix, and probably isn't even
widely depended-upon.  Zsh scripts hardly ever bother fooling with IFS,
given all the other ways that one has to chop up strings.

} > I don't know exactly when this bug was introduced, though.
} 
} That is almost inevitable in current implementation.

Yes, but 3.0.6 doesn't *have* the current implementation, and it's got
the same problem as demonstrated for 3.0.8 in my previous message.  So
part of this got introduced quite some time ago, which is what I meant.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


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

* PATCH: 3.1.9-dev-8: Re: Word splitting in zsh
  2001-02-09 18:18 ` Word splitting in zsh Bart Schaefer
@ 2001-02-10 20:24   ` Bart Schaefer
  2001-02-12  7:38     ` Andrej Borsenkow
  2001-02-13  7:51     ` More incompatibility :-) " Andrej Borsenkow
  0 siblings, 2 replies; 16+ messages in thread
From: Bart Schaefer @ 2001-02-10 20:24 UTC (permalink / raw)
  To: Deborah Ariel Pickett, zsh-workers

On Feb 9, 10:34am, Andrej Borsenkow wrote:
}
} > zagzig% echo $ZSH_VERSION
} > 3.0.8
} > zagzig% setopt shwordsplit
} > zagzig% print -l ${1+"$@"}
} > a1
} > a2
} > a3
} > b
} > c
} > zagzig%
} >
} 
} > Well, that's not quite right,
} 
} It is simply wrong.
} 
}                                             but 3.1.9-dev-8 is even worse:
} >
} > zagzig% echo $ZSH_VERSION
} > 3.1.9-dev-8
} > zagzig% set "a1 a2 a3" b c
} > zagzig% print -l ${1+"$@"}
} > a1 a2 a3 b c						<-- Yipes!
} 
} Well, this is "correct" *zsh* behaviour. The part after `+' is a word -
} not array. And is taken as single word and is never splitted.

On Feb 9,  6:18pm, Bart Schaefer wrote:
}
} Yes, your analysis is correct; the bug is that there should not be a scalar
} context there.  The effect of ${NAME:+WORD} and ${NAME:-WORD} should be to
} replace the context of NAME with the context of WORD in the event that NAME
} is (or not) set.  Put another way, the type of NAME should only determine
} the type of the whole ${...} when NAME really is being substituted.

This turned out to be remarkably easy; patch and explanation below.

On Feb 9, 10:34am, Andrej Borsenkow wrote:
} 
} That is just because of above. The structure of WORD in ${name+WORD} is not
} remebered. But note the same bug again:
} 
} bor@itsrm2% set 'a b c' 1 2
} bor@itsrm2% IFS=: print -l ${1+"$@"}
} a b c 1 2
} bor@itsrm2% setopt shwordsplit
} bor@itsrm2% IFS=: print -l ${1+"$@"}
} a
} b
} c
} 1
} 2
} 
} IFS value is silently ignored.

This is actually something entirely different, and is not really a bug at
all.  The problem with Andrej's example is that ${1+"$@"} is expanded
before the assignment to IFS takes place.  If you replace the `print's
above with

    args() { print -l $* ++ ${1+"$@"} }
    IFS=: args "$@"

then you'll see that IFS is handled correctly (modulo the other bug).

OK, here's the patch; I won't commit this until I get some feedback on it.  

The solution is simply (1) pass &aval into multsub() so that it returns
an array when the word being expanded would expand to an array; (2) pass
the current value of `spbreak' through multsub() in case of ${=...}; (3)
turn off word splitting after multsub() returns, because multsub() will
have already performed quoting and splitting as appropriate.

This applies only to ${...+...} and ${...-...}, with or without the `:'.
As I mentioned, there would be some benefit to also doing this for the
${...=...} forms, because then things like ${(A)foo="$bar[@]"} would work
independently of the setting of shwordplit.

There's some question in my mind of whether ${~...} and ${^...} should be
treated this way, too; e.g. (this is what does NOT happen):

zsh% print -l ${^1+"x$@x"}
xa1:a2 a3x
xbx
xcx

That `^' and `~' are not propagated now could even be an argument for not
propagating `=' either, but that would cause a larger change in behavior
in the instances where the right-hand-side of the `+'/`-' is not quoted
(and the shwordsplit option is not set).

I've also left unchanged the behavior of ${(s( ))...}, ${(z)...}, etc.,
because those constructs aren't possible in Bourne shell and in general
the expansion flags take precedence over everything else -- and because
there's a lot more potential for breakage when messing with those.

Index: Src/subst.c
===================================================================
--- Src/subst.c	2001/01/16 17:18:12	1.72
+++ Src/subst.c	2001/02/10 18:31:20
@@ -749,7 +749,9 @@
     int chkset = 0;
     int vunset = 0;
     int wantt = 0;
-    int spbreak = isset(SHWORDSPLIT) && !ssub && !qt;
+    static int mult_spbreak, mult_shwsplit;
+    int spbreak = (!ssub && !qt &&
+		   (mult_spbreak? mult_shwsplit : isset(SHWORDSPLIT)));
     char *val = NULL, **aval = NULL;
     unsigned int fwidth = 0;
     struct value vbuf;
@@ -1378,8 +1380,14 @@
 	/* Fall Through! */
 	case '-':
 	    if (vunset) {
+		int shws = mult_shwsplit, spbr = mult_spbreak;
+		mult_shwsplit = spbreak;
+		mult_spbreak = 1;
 		val = dupstring(s);
-		multsub(&val, NULL, &isarr, NULL);
+		multsub(&val, (aspar ? NULL : &aval), &isarr, NULL);
+		mult_shwsplit = shws;
+		mult_spbreak = spbr;
+		spbreak = 0;
 		copied = 1;
 	    }
 	    break;

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


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

* RE: PATCH: 3.1.9-dev-8: Re: Word splitting in zsh
  2001-02-10 20:24   ` PATCH: 3.1.9-dev-8: " Bart Schaefer
@ 2001-02-12  7:38     ` Andrej Borsenkow
  2001-02-12 14:12       ` Andrej Borsenkow
  2001-02-13  7:51     ` More incompatibility :-) " Andrej Borsenkow
  1 sibling, 1 reply; 16+ messages in thread
From: Andrej Borsenkow @ 2001-02-12  7:38 UTC (permalink / raw)
  To: Bart Schaefer, Deborah Ariel Pickett, zsh-workers

>
> This applies only to ${...+...} and ${...-...}, with or without the `:'.
> As I mentioned, there would be some benefit to also doing this for the
> ${...=...} forms, because then things like ${(A)foo="$bar[@]"} would work
> independently of the setting of shwordplit.
>

Is the following a bug in shell and should zsh emulate it?

bor@itsrm2% sh
$ set "a b c" 1 2
$ args ${foo="$@"}
3
a b c
1
2
$ args $foo
5
a
b
c
1
2

Compare with zsh:

bor@itsrm2% setopt shwordsplit
bor@itsrm2% set "a b c" 1 2
bor@itsrm2% print -l ${foo="$@"}
a
b
c
1
2

To explain what's going on:

In case of ${name-word} or ${name+word} sh does exactly *one* expansion (as
opposed to zsh that does two) with the pseudocode (e.g. for -)

if defined name
  replace $name
else
  replace expanded word

(BTW I was surprised to see that expansions in word actually nest;
${xxx-${yyy-bar}} results in ``bar'').

But in case of ${name=bar} the definition is

Assign Default Values. If parameter is unset or null, the expansion of word
will be assigned to parameter. In all cases, the final value of parameter will
be substituted. Only variables, not positional parameters or special
parameters, can be assigned in this way.

BUT sh has only scalar parameters - so, the "final value" can only be scalar
that it then word splitted - as happens in zsh :-) But it looks, like sh
behaves as in case of ${...-...}/${...+...} - i.e. it substitutes expansion of
word and assigns it to name. It smells like a bug in (our) sh to me.

-andrej

P.S. Deborah, it's probably becoming way too specific. Should we still Cc you?


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

* RE: PATCH: 3.1.9-dev-8: Re: Word splitting in zsh
  2001-02-12  7:38     ` Andrej Borsenkow
@ 2001-02-12 14:12       ` Andrej Borsenkow
  2001-02-12 19:38         ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Andrej Borsenkow @ 2001-02-12 14:12 UTC (permalink / raw)
  To: zsh-workers


> >
>
> Is the following a bug in shell and should zsh emulate it?
>


And is this a bug or feature in zsh (with Bart's patch):

bor@itsrm2% baz=("aa bb" cc)
bor@itsrm2% print -l "${(A)foo=$baz[@]}"
aa bb
cc

Again the same problem for ${name=word} - should the whole evaluate to the
$name (with proper quoting) or to the word? I believe it is a bug because next
command where foo is already defined:

bor@itsrm2% print -l "${(A)foo=$baz[@]}"
aa bb cc

both cases should evaluate to the value of $foo, if I read specs properly, and
be identical, i.e. as in the second case.

-andrej


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

* Re: PATCH: 3.1.9-dev-8: Re: Word splitting in zsh
  2001-02-12 14:12       ` Andrej Borsenkow
@ 2001-02-12 19:38         ` Bart Schaefer
  0 siblings, 0 replies; 16+ messages in thread
From: Bart Schaefer @ 2001-02-12 19:38 UTC (permalink / raw)
  To: zsh-workers

On Feb 12, 10:38am, Andrej Borsenkow wrote:
}
} > This applies only to ${...+...} and ${...-...}, with or without the `:'.
} > As I mentioned, there would be some benefit to also doing this for the
} > ${...=...} forms, because then things like ${(A)foo="$bar[@]"} would work
} > independently of the setting of shwordplit.
} >
} 
} Is the following a bug in shell and should zsh emulate it?
} 
} bor@itsrm2% sh
} $ set "a b c" 1 2
} $ args ${foo="$@"}
} 3
} a b c
} 1
} 2

Bash seems to emulate it.

} In case of ${name-word} or ${name+word} sh does exactly *one* expansion (as
} opposed to zsh that does two)

That's not precisely what's happening in zsh.  It does only one expansion,
but it does word splitting based on the outer (lack of) quotes rather than
the inner ones.  Which I suppose could be called "two expansions" ...

The equivalent of the patch that I made for ${x+y} and ${x-y}, applied to
${x=y}, would have the effect of emulating the above behavior.

On Feb 12,  5:12pm, Andrej Borsenkow wrote:
} Subject: RE: PATCH: 3.1.9-dev-8: Re: Word splitting in zsh
}
} And is this a bug or feature in zsh (with Bart's patch):

Note that my patch makes absolutely no difference to this; read the very
first double-excerpted paragraph above.

} bor@itsrm2% baz=("aa bb" cc)
} bor@itsrm2% print -l "${(A)foo=$baz[@]}"
} aa bb
} cc
} bor@itsrm2% print -l "${(A)foo=$baz[@]}"
} aa bb cc
} 
} both cases should evaluate to the value of $foo, if I read specs
} properly, and be identical, i.e. as in the second case.

This is a slightly different bug; what's interesting is how bash handles
it ... note the difference between ${x+y} and ${x=y}:

[schaefer@zagzig schaefer]$ set "a1 a2 a3" b c                                 
[schaefer@zagzig schaefer]$ for i in "${1+$@}"; do echo "$i"; done
a1 a2 a3
b
c
[schaefer@zagzig schaefer]$ for i in "${foo=$@}"; do echo "$i"; done
a1 a2 a3 b c
[schaefer@zagzig schaefer]$ for i in "${foo+$@}"; do echo "$i"; done
a1 a2 a3
b
c

To "fix" this in zsh is trivial, if we want it fixed; just copy some
code from above the "Check for ${..?..} or ${..=..} or one of those."
block:

Index: Src/subst.c
===================================================================
--- Src/subst.c	2001/02/10 20:33:32	1.73
+++ Src/subst.c	2001/02/12 19:22:18
@@ -1454,6 +1454,14 @@
 		}
 		*idend = sav;
 		copied = 1;
+		if (isarr) {
+		  if (nojoin)
+		    isarr = -1;
+		  if (qt && !getlen && isarr > 0) {
+		    val = sepjoin(aval, sep, 1);
+		    isarr = 0;
+		  }
+		}
 	    }
 	    break;
 	case '?':

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


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

* More incompatibility :-) RE: PATCH: 3.1.9-dev-8: Re: Word splitting in zsh
  2001-02-10 20:24   ` PATCH: 3.1.9-dev-8: " Bart Schaefer
  2001-02-12  7:38     ` Andrej Borsenkow
@ 2001-02-13  7:51     ` Andrej Borsenkow
  2001-02-13  9:26       ` Bart Schaefer
  1 sibling, 1 reply; 16+ messages in thread
From: Andrej Borsenkow @ 2001-02-13  7:51 UTC (permalink / raw)
  To: zsh-workers

>
> OK, here's the patch; I won't commit this until I get some feedback on it.
>

This fixes one more incompatibility, so I am in favour of applying it.

Zsh:

bor@itsrm2% foo=$'foo\nbar'
bor@itsrm2% print "$foo"
foo
bar
bor@itsrm2% setopt shwordsplit
bor@itsrm2% bar=${1-$foo}
bor@itsrm2% print "$bar"
foo bar

sh:

$ foo=`echo 'foo\nbar\c'`
$ echo "$foo"
foo
bar
$ bar=${1-$foo}
$ echo "$bar"
foo
bar

This just proves my point again - wordsplitting should be done once after all
subst were done on current word. And only in context where wordsplitting is to
be actually done.

> +    static int mult_spbreak, mult_shwsplit;

They are static. Is there any chance, that two unrelated substitutions may run
at the same time? E.g. inside nested command substitution? This forms its own
context and both above must be reset.

-andrej


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

* Re: More incompatibility :-) RE: PATCH: 3.1.9-dev-8: Re: Word splitting in zsh
  2001-02-13  7:51     ` More incompatibility :-) " Andrej Borsenkow
@ 2001-02-13  9:26       ` Bart Schaefer
  2001-02-13  9:57         ` Andrej Borsenkow
  0 siblings, 1 reply; 16+ messages in thread
From: Bart Schaefer @ 2001-02-13  9:26 UTC (permalink / raw)
  To: Andrej Borsenkow, zsh-workers

On Feb 13, 10:51am, Andrej Borsenkow wrote:
}
} > +    static int mult_spbreak, mult_shwsplit;
} 
} They are static. Is there any chance, that two unrelated substitutions
} may run at the same time? E.g. inside nested command substitution?
} This forms its own context and both above must be reset.

They are saved, set, and restored in a small block around the call to
multsub(), and otherwise referenced only on first entry to paramsubst().
They have no effect other than to override the current setting of the
shwordsplit option.  That does mean that

	print ${=foo+"$(unsetopt shwordsplit;print -l $bar)"}

actually *does* split the value of $bar within the command subst.  Hmm.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


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

* RE: More incompatibility :-) RE: PATCH: 3.1.9-dev-8: Re: Word splitting in zsh
  2001-02-13  9:26       ` Bart Schaefer
@ 2001-02-13  9:57         ` Andrej Borsenkow
  2001-02-13 19:33           ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Andrej Borsenkow @ 2001-02-13  9:57 UTC (permalink / raw)
  To: zsh-workers


>
> They are saved, set, and restored in a small block around the call to
> multsub(), and otherwise referenced only on first entry to paramsubst().
> They have no effect other than to override the current setting of the
> shwordsplit option.  That does mean that
>
> 	print ${=foo+"$(unsetopt shwordsplit;print -l $bar)"}
>
> actually *does* split the value of $bar within the command subst.  Hmm.
>

Yep. That is exactly what I meant. I'm not sure what is current status, but I
always assumed that any flag applies to current value only and not propagates
to nested substitutions. At least this sounds logical.

-andrej


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

* Re: More incompatibility :-) RE: PATCH: 3.1.9-dev-8: Re: Word splitting in zsh
  2001-02-13  9:57         ` Andrej Borsenkow
@ 2001-02-13 19:33           ` Bart Schaefer
  2001-02-14 18:00             ` Peter Stephenson
  0 siblings, 1 reply; 16+ messages in thread
From: Bart Schaefer @ 2001-02-13 19:33 UTC (permalink / raw)
  To: Andrej Borsenkow, zsh-workers

On Feb 13, 12:57pm, Andrej Borsenkow wrote:
> Subject: RE: More incompatibility :-) RE: PATCH: 3.1.9-dev-8: Re: Word spl
> 
> > 	print ${=foo+"$(unsetopt shwordsplit;print -l $bar)"}
> >
> > actually *does* split the value of $bar within the command subst.  Hmm.
> 
> Yep. That is exactly what I meant. I'm not sure what is current
> status, but I always assumed that any flag applies to current value
> only and not propagates to nested substitutions. At least this sounds
> logical.

Depends on what you mean by "nested substitutions."

Without my patch, the flag effectively applies to all nested substitutions
because splitting is done again at each level *after* the value propagates
up from the any nested substitution.

With my patch, for exactly the ${x+y} and ${x-y} cases, the current state
of splitting is deliberately propagated to the right-hand-side, which is
not so much a nested substitution as it is a "alternate" substitution.
However, the way that I propagated it causes it to override `setopt' for
the shwordsplit option, which is correct in the current shell but not in
subshells i.e. $(...).

The two possible solutions to this are (1) make ${=...} behave the way
Andrej says is "logical", so that e.g. with shwordsplit turned off, in
${=x+${y}} no word splitting would happen at all (because it's not on
in $y, even though it's on for $x; or (2) figure out how to reset the
value of mult_spbreak to 0 during $(...) (mult_shwsplit is ignored if
mult_spbreak is 0).

(1) actually means removing mult_spbreak and mult_shwsplit entirely; I
put them in because I thought to do otherwise would be too great a
behavior change from the way zsh works without the patch.


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

* Re: More incompatibility :-) RE: PATCH: 3.1.9-dev-8: Re: Word splitting in zsh
  2001-02-13 19:33           ` Bart Schaefer
@ 2001-02-14 18:00             ` Peter Stephenson
  2001-02-15  6:17               ` Andrej Borsenkow
  0 siblings, 1 reply; 16+ messages in thread
From: Peter Stephenson @ 2001-02-14 18:00 UTC (permalink / raw)
  To: Zsh hackers list

> The two possible solutions to this are (1) make ${=...} behave the way
> Andrej says is "logical", so that e.g. with shwordsplit turned off, in
> ${=x+${y}} no word splitting would happen at all (because it's not on
> in $y, even though it's on for $x; or (2) figure out how to reset the
> value of mult_spbreak to 0 during $(...) (mult_shwsplit is ignored if
> mult_spbreak is 0).
> 
> (1) actually means removing mult_spbreak and mult_shwsplit entirely; I
> put them in because I thought to do otherwise would be too great a
> behavior change from the way zsh works without the patch.

I'd go for the original patch, plus (1).  Almost certainly if there are
side effects we won't find out until the patch is in place anyway.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
Cambridge Silicon Radio, Unit 300, Science Park, Milton Road,
Cambridge, CB4 0XL, UK                          Tel: +44 (0)1223 392070


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

* RE: More incompatibility :-) RE: PATCH: 3.1.9-dev-8: Re: Word splitting in zsh
  2001-02-14 18:00             ` Peter Stephenson
@ 2001-02-15  6:17               ` Andrej Borsenkow
  2001-02-15  8:34                 ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Andrej Borsenkow @ 2001-02-15  6:17 UTC (permalink / raw)
  To: Zsh hackers list


>
> > The two possible solutions to this are (1) make ${=...} behave the way
> > Andrej says is "logical", so that e.g. with shwordsplit turned off, in
> > ${=x+${y}} no word splitting would happen at all (because it's not on
> > in $y, even though it's on for $x; or (2) figure out how to reset the
> > value of mult_spbreak to 0 during $(...) (mult_shwsplit is ignored if
> > mult_spbreak is 0).
> >
> > (1) actually means removing mult_spbreak and mult_shwsplit entirely; I
> > put them in because I thought to do otherwise would be too great a
> > behavior change from the way zsh works without the patch.
>
> I'd go for the original patch, plus (1).  Almost certainly if there are
> side effects we won't find out until the patch is in place anyway.
>

Ehh ... I did not mean it actually. My concern was that in ${=$(...)} the `='
must not affect what happens inside of $(...). What I believe should happen in
case of ${x+${y}} - first, value is computed. It is either $x or $y - without
any wordsplitting. Then `=' is applied to the result. It is different from
just turning wordsplitting on - consider ${=${${foo}[2]}} where foo is array.
Here internal ${foo} should not be wordsplitted, else it is hard to get
predictable result.

-andrej



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

* Re: More incompatibility :-) RE: PATCH: 3.1.9-dev-8: Re: Word splitting in zsh
  2001-02-15  6:17               ` Andrej Borsenkow
@ 2001-02-15  8:34                 ` Bart Schaefer
  2001-02-15 10:35                   ` More incompatibility (word splitting) Peter Stephenson
  0 siblings, 1 reply; 16+ messages in thread
From: Bart Schaefer @ 2001-02-15  8:34 UTC (permalink / raw)
  To: Zsh hackers list

On Feb 15,  9:17am, Andrej Borsenkow wrote:
} Subject: RE: More incompatibility :-) RE: PATCH: 3.1.9-dev-8: Re: Word spl
}
} Ehh ... I did not mean it actually. My concern was that in ${=$(...)}
} the `=' must not affect what happens inside of $(...).

It could be argued either way.  The doc says:

     Perform word splitting using the rules for SH_WORD_SPLIT during the
     evaluation of SPEC, but regardless of whether the parameter
     appears in double quotes;

The $(...) is in fact part of SPEC.  The problem is that, because ${=...}
is not implemented by actually toggling SH_WORD_SPLIT, it's surprising
what happens in cases like ${=x+$(setopt noshwordsplit; ...)}.

} What I believe
} should happen in case of ${x+${y}} - first, value is computed. It
} is either $x or $y - without any wordsplitting. Then `=' is applied
} to the result.

What you've described is exactly what zsh does (withOUT my patch).  This
is what causes ${1+"$@"} to behave strangely:  "$@" is expanded to an
array, but then the elements of the result are subject to splitting, if
splitting is enabled for the context (no matter why).

My patch attempted to make it the responsibility of multsub() to do any
splitting necessary on the right-hand-side of +/-, which works as long
as the entire RHS is a parameter substition.  However, In the case of
${1+some words "$@" more words}, prefork() [called by multsub()] just
doesn't do enough:  It yields "some words $1" ... "$@[-1] more words",
where sh would give "some" "words" "$1" ... "$@[-1]" "more" "words".

I've just about reached the conclusion that the RHS of these kinds of
expansions will have to be re-lexed in order to be wordsplit properly.
Once they've been lexed as a single word during the first pass, there
is no provision for differentiating the quoted and unquoted substrings
after expansion -- except within "nested" expansions, which doesn't
cover all the possible cases.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


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

* Re: More incompatibility (word splitting)
  2001-02-15  8:34                 ` Bart Schaefer
@ 2001-02-15 10:35                   ` Peter Stephenson
  2001-02-16  7:43                     ` PATCH: " Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Peter Stephenson @ 2001-02-15 10:35 UTC (permalink / raw)
  To: Zsh hackers list

Bart wrote:
> On Feb 15,  9:17am, Andrej Borsenkow wrote:
> } Ehh ... I did not mean it actually.
> 
> It could be argued either way.
> 
> ... The problem is that
> ... it's surprising
> 
> } What I believe should happen
> 
> ... behave strangely
> 
> ... just doesn't do enough
> 
> I've just about reached the conclusion ...
> ... doesn't cover all the possible cases.

It sounds like Bart's original patch will have to do for the time being.
I think that's fairly unobjectionable, but it looks like nothing else
simple will quite fit.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
Cambridge Silicon Radio, Unit 300, Science Park, Milton Road,
Cambridge, CB4 0XL, UK                          Tel: +44 (0)1223 392070


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

* PATCH: Re: More incompatibility (word splitting)
  2001-02-15 10:35                   ` More incompatibility (word splitting) Peter Stephenson
@ 2001-02-16  7:43                     ` Bart Schaefer
  2001-02-16  8:50                       ` Andrej Borsenkow
  0 siblings, 1 reply; 16+ messages in thread
From: Bart Schaefer @ 2001-02-16  7:43 UTC (permalink / raw)
  To: Zsh hackers list

On Feb 15, 10:35am, Peter Stephenson wrote:
}
} It sounds like Bart's original patch will have to do for the time being.

Here's the patch as I'm willing to commit it right now.  I'm going to be
out of town all next week, so I'm not going to be able to mess with it
any further, and I don't want to put something really broken into CVS
right before I disappear.

This includes the hunk from 13455 and one line from 13452, plus a comment
explaining the shortcomings of the code as it stands.  The effect is that
the ${1+"$@"} case is no longer worse than in 3.0.8, though the ${=1+"$@"}
case is still no better; but "${(A)foo=$@}" should be much better.

Index: Src/subst.c
--- zsh-forge/current/Src/subst.c	Tue Jan 16 07:12:14 2001
+++ zsh-3.1.9/Src/subst.c	Thu Feb 15 23:19:55 2001
@@ -1379,7 +1379,14 @@
 	case '-':
 	    if (vunset) {
 		val = dupstring(s);
-		multsub(&val, NULL, &isarr, NULL);
+		/*
+		 * This is not good enough for sh emulation!  Sh would
+		 * split unquoted substrings, yet not split quoted ones
+		 * (except according to $@ rules); but this leaves the
+		 * unquoted substrings unsplit, and other code below
+		 * for spbreak splits even within the quoted substrings.
+		 */
+		multsub(&val, (aspar ? NULL : &aval), &isarr, NULL);
 		copied = 1;
 	    }
 	    break;
@@ -1446,6 +1453,14 @@
 		}
 		*idend = sav;
 		copied = 1;
+		if (isarr) {
+		  if (nojoin)
+		    isarr = -1;
+		  if (qt && !getlen && isarr > 0) {
+		    val = sepjoin(aval, sep, 1);
+		    isarr = 0;
+		  }
+		}
 	    }
 	    break;
 	case '?':

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


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

* RE: PATCH: Re: More incompatibility (word splitting)
  2001-02-16  7:43                     ` PATCH: " Bart Schaefer
@ 2001-02-16  8:50                       ` Andrej Borsenkow
  2001-02-16 17:03                         ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Andrej Borsenkow @ 2001-02-16  8:50 UTC (permalink / raw)
  To: Zsh hackers list


> 
> Here's the patch as I'm willing to commit it right now.  I'm going to be
> out of town all next week, so I'm not going to be able to mess with it
> any further, and I don't want to put something really broken into CVS
> right before I disappear.
>

Does it really fix two described incompatibilities? O

bor@itsrm2% Src/zsh
bor@itsrm2% setopt shwordsplit 
bor@itsrm2% foo=$'foo\nbar'
bor@itsrm2% print "$foo"
foo
bar
bor@itsrm2% bar=${1-$foo}
bor@itsrm2% print "$bar"
foo bar   <= wrong
bor@itsrm2% set "a b c" 1 2
bor@itsrm2% print -l ${1+"$@"}
a
b
c
1
2
bor@itsrm2% exit

-andrej


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

* Re: PATCH: Re: More incompatibility (word splitting)
  2001-02-16  8:50                       ` Andrej Borsenkow
@ 2001-02-16 17:03                         ` Bart Schaefer
  0 siblings, 0 replies; 16+ messages in thread
From: Bart Schaefer @ 2001-02-16 17:03 UTC (permalink / raw)
  To: Zsh hackers list

On Feb 16, 11:50am, Andrej Borsenkow wrote:
} Subject: RE: PATCH: Re: More incompatibility (word splitting)
}
} > Here's the patch as I'm willing to commit it right now.
} 
} Does it really fix two described incompatibilities? O

It fixes the incompatibility with 3.0.8, i.e. ${1+"$@"} does the right
thing when *not* emulating sh, which it didn't before.

It fixes "${(A)foo=$bar[@]}" but not [ ${foo=""} = "true" ].

Although actually, sigh, it breaks "${(A)=foo=$bar}" in that it splits
$bar and assigns the array to $foo but then doesn't split $foo when it
substitutes the end result.


--- zsh-forge/current/Src/subst.c	Fri Feb 16 00:35:19 2001
+++ zsh-3.1.9/Src/subst.c	Fri Feb 16 08:18:49 2001
@@ -1015,7 +1015,7 @@
 		spbreak = 0;
 		s++;
 	    } else
-		spbreak = 1;
+		spbreak = 2;
 	} else if ((c == '#' || c == Pound) &&
 		   (iident(cc = s[1])
 		    || cc == '*' || cc == Star || cc == '@'
@@ -1414,8 +1414,6 @@
 		    if (spsep || spbreak) {
 			aval = sepsplit(val, spsep, 0, 1);
 			isarr = 2;
-			sep = spsep = NULL;
-			spbreak = 0;
 			l = arrlen(aval);
 			if (l && !*(aval[l-1]))
 			    l--;
@@ -1456,10 +1454,12 @@
 		if (isarr) {
 		  if (nojoin)
 		    isarr = -1;
-		  if (qt && !getlen && isarr > 0) {
+		  if (qt && !getlen && isarr > 0 && !spsep && spbreak < 2) {
 		    val = sepjoin(aval, sep, 1);
 		    isarr = 0;
 		  }
+		  sep = spsep = NULL;
+		  spbreak = 0;
 		}
 	    }
 	    break;

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


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

end of thread, other threads:[~2001-02-16 17:05 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <000d01c0926a$ce26c590$21c9ca95@mow.siemens.ru>
2001-02-09 18:18 ` Word splitting in zsh Bart Schaefer
2001-02-10 20:24   ` PATCH: 3.1.9-dev-8: " Bart Schaefer
2001-02-12  7:38     ` Andrej Borsenkow
2001-02-12 14:12       ` Andrej Borsenkow
2001-02-12 19:38         ` Bart Schaefer
2001-02-13  7:51     ` More incompatibility :-) " Andrej Borsenkow
2001-02-13  9:26       ` Bart Schaefer
2001-02-13  9:57         ` Andrej Borsenkow
2001-02-13 19:33           ` Bart Schaefer
2001-02-14 18:00             ` Peter Stephenson
2001-02-15  6:17               ` Andrej Borsenkow
2001-02-15  8:34                 ` Bart Schaefer
2001-02-15 10:35                   ` More incompatibility (word splitting) Peter Stephenson
2001-02-16  7:43                     ` PATCH: " Bart Schaefer
2001-02-16  8:50                       ` Andrej Borsenkow
2001-02-16 17:03                         ` 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).