Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: while alias
- X-seq: zsh-users 28338
- From: Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
- To: Zsh-Users List <zsh-users@xxxxxxx>
- Subject: Re: while alias
- Date: Tue, 8 Nov 2022 12:39:18 +0000 (GMT)
- Archived-at: <https://zsh.org/users/28338>
- Importance: Normal
- In-reply-to: <CAH+w=7an3D6d-6XX+PG=yNE4nJZdRR3NmnMWL7ENjxTbV2ra+g@mail.gmail.com>
- List-id: <zsh-users.zsh.org>
- References: <CAP+y1xA2rYkSgO2Xpo7NfDKeJwE5+Gc8BdFCsw8b8Mw0RGBvsg@mail.gmail.com> <CAH+w=7an3D6d-6XX+PG=yNE4nJZdRR3NmnMWL7ENjxTbV2ra+g@mail.gmail.com>
(This is really for zsh-workers but in case anyone wants to see the result...)
> On 08/11/2022 06:13 Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> On Mon, Nov 7, 2022 at 5:57 PM Pier Paolo Grassi <pierpaolog@xxxxxxxxx> wrote:
> >
> > Hello, I have the following alias defined:
> >
> > WI='while {read -r it; ! [[ $? -ne 0 && -z $it ]]}'
> >
> > that works fine except in command substitution:
>
> Put spaces around your braces.
>
> alias WI='while { read -r it; ! [[ $? -ne 0 && -z $it ]] }'
>
> Aliases in command substitutions are parsed by a complicated dance
> requiring that they be expanded and then backtracked over and then
> re-parsed. The character count for the "{" and/or "}" tokens is off
> by one for the backtracking step when they don't have surrounding
> whitespace. (Leaving it to PWS, who choreographed this dance number,
> to fix the footwork if possible.)
Yes, it's that full combination of a command substitution, an
alias, and expansion text with a lexically significant closing brace
with no preceding space that's doing it, so it's very specific.
This will come as a shock, but there's a hack in the lexical analyser!
(Counselling will be available by the usual channels.) It seems
that the lexer really doesn't like closing braces without a space
before them and sometimes we have to fix up the text after the event.
It seems the extra special code for command substitution needs a
slightly modified version of the hack. The new test in D08 checks
the case Pier Paolo hit; it turns out the existing test just above
checks the case where we do after all need to unget an extra closing
brace, i.e. lex_add_raw ends up 1 in the code added by the first hunk.
I am not going to attempt to get my mind round this any further
and will be going out for some fresh air.
pws
diff --git a/Src/lex.c b/Src/lex.c
index ece02659e..e2f8bcfb1 100644
--- a/Src/lex.c
+++ b/Src/lex.c
@@ -1429,10 +1429,18 @@ gettokstr(int c, int sub)
peek == STRING && lexbuf.ptr[-1] == '}' &&
lexbuf.ptr[-2] != Bnull) {
/* hack to get {foo} command syntax work */
+ /*
+ * Alias expansion when parsing command substitution means that
+ * the case for raw lexical analysis may not be the same.
+ * (Just go with it, OK?)
+ */
+ int lar = lex_add_raw;
+ lex_add_raw = lexbuf_raw.len > 0 && lexbuf_raw.ptr[-1] == '}';
lexbuf.ptr--;
lexbuf.len--;
lexstop = 0;
hungetc('}');
+ lex_add_raw = lar;
}
*lexbuf.ptr = '\0';
DPUTS(cmdsp != ocmdsp, "BUG: gettok: cmdstack changed.");
diff --git a/Test/D08cmdsubst.ztst b/Test/D08cmdsubst.ztst
index 04bf698aa..8b6bcb469 100644
--- a/Test/D08cmdsubst.ztst
+++ b/Test/D08cmdsubst.ztst
@@ -177,3 +177,11 @@
0:Alias expansion needed in parsing substitutions
>hi
>bye
+
+# This should silently print a blank line; the original problem was
+# a parse error as the last character of the unexpanded alias
+# was erased, symptom: "command not found: W"
+ alias WI='while {false}'
+ eval 'echo $(WI blah)'
+0:Aliases with braces in command substitution can cause havoc
+>
Messages sorted by:
Reverse Date,
Date,
Thread,
Author