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

Quoting and ${(e)param} (was Re: destructive list-expand)

On May 16,  2:49pm, Sven Wischnowsky wrote:
} Subject: Re: destructive list-expand
} Part of the reason may probably be fixed by this (not to be committed
} until some knowledgeable person comments):
} Index: Src/subst.c
} ===================================================================
} RCS file: /cvsroot/zsh/zsh/Src/subst.c,v
} retrieving revision 1.17
} diff -u -r1.17 subst.c
} --- Src/subst.c	2001/04/28 17:38:01	1.17
} +++ Src/subst.c	2001/05/16 12:39:51
} @@ -720,9 +720,13 @@
}      if (!(err ? parsestr(s) : parsestrnoerr(s))) {
}  	if (!single) {
} +            int qt = 0;
} +
}  	    for (; *s; s++)
} -		if (*s == Qstring)
} +		if (!qt && *s == Qstring)
}  		    *s = String;
} +                else if (*s == Dnull)
} +                    qt = !qt;
}  	}
}  	return 0;
}      }
} That loop is in subst_parse_str() and turns all Qstring tokens into
} String, even the one inside those double quotes in the parameter
} expression. That makes the inner substitution return a string instead
} of an array.
} The patch leaves all Qstring's inside Dnull's unchanged.

Probably the Qstring should change to String when (err == 0), as in
that case parsestrnoerr() will not have complained about unmatched
quotes.  Or will that mean that there are no Qstring to begin with?
} The other part of the problem (not tackled by the patch) is that the
} pattern after `:#...' is not tokenized. In paramsubst() is some code
} that tokenizes the pattern, but only if it things the whole parameter
} expansion is inside quotes.

I believe that's because in the normal [non-(e)] case, the pattern will
already have been tokenized when the expansion is not in quotes, so it
would be redundant to tokenize it again.  I'm pretty far from sure about
this, though.

But, not tokenized where?  parsestr() untokenizes and re-tokenizes its
whole argument ... as if it were in double quotes ...

} But the result of a ${(e)...} is not
} considered to be in double quotes exactly because of the loop above.

Right, that loop must be attempting to undo the implicit double-quoting
from parsestr().  It just doesn't undo enough of it.

} I'm not sure how to fix this.

It looks to me as though the only "right" way is to create a new flavor
of parsestr() that parses as if NOT in quotes, and call the appropriate
one from subst_parse_str() (which means passing in `qt' and not just
`single', I suspect).

Does anyone remember anything else that might bear on this?  Peter?

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   

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