zsh-users
 help / color / mirror / code / Atom feed
* while alias
@ 2022-11-08  1:56 Pier Paolo Grassi
  2022-11-08  6:13 ` Bart Schaefer
  0 siblings, 1 reply; 4+ messages in thread
From: Pier Paolo Grassi @ 2022-11-08  1:56 UTC (permalink / raw)
  To: Zsh-Users List

[-- Attachment #1: Type: text/plain, Size: 504 bytes --]

Hello, I have the following alias defined:

WI='while {read -r it; ! [[ $? -ne 0 && -z $it ]]}'

that works fine except in command substitution:

a=$( echo 1 | WI { echo $it } )
zsh: parse error near `}'
zsh: parse error in command substitution

if I substitute the alias with the aliased code all works fine:

a=$( echo 1 | while {read -r it; ! [[ $? -ne 0 && -z $it ]]} { echo $it }
); echo $a
1

alias are normally correctly substituted inside command substitution, what
can it be?

Pier Paolo Grassi

[-- Attachment #2: Type: text/html, Size: 928 bytes --]

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

* Re: while alias
  2022-11-08  1:56 while alias Pier Paolo Grassi
@ 2022-11-08  6:13 ` Bart Schaefer
  2022-11-08 12:39   ` Peter Stephenson
  0 siblings, 1 reply; 4+ messages in thread
From: Bart Schaefer @ 2022-11-08  6:13 UTC (permalink / raw)
  To: Pier Paolo Grassi; +Cc: Zsh-Users List

On Mon, Nov 7, 2022 at 5:57 PM Pier Paolo Grassi <pierpaolog@gmail.com> 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.)


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

* Re: while alias
  2022-11-08  6:13 ` Bart Schaefer
@ 2022-11-08 12:39   ` Peter Stephenson
  2022-11-09 11:11     ` Pier Paolo Grassi
  0 siblings, 1 reply; 4+ messages in thread
From: Peter Stephenson @ 2022-11-08 12:39 UTC (permalink / raw)
  To: Zsh-Users List

(This is really for zsh-workers but in case anyone wants to see the result...)

> On 08/11/2022 06:13 Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Mon, Nov 7, 2022 at 5:57 PM Pier Paolo Grassi <pierpaolog@gmail.com> 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
+>


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

* Re: while alias
  2022-11-08 12:39   ` Peter Stephenson
@ 2022-11-09 11:11     ` Pier Paolo Grassi
  0 siblings, 0 replies; 4+ messages in thread
From: Pier Paolo Grassi @ 2022-11-09 11:11 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: Zsh-Users List

[-- Attachment #1: Type: text/plain, Size: 3500 bytes --]

thanks the space before the brace indeed solved it. good to know!

Pier Paolo Grassi


Il giorno mar 8 nov 2022 alle ore 13:40 Peter Stephenson <
p.w.stephenson@ntlworld.com> ha scritto:

> (This is really for zsh-workers but in case anyone wants to see the
> result...)
>
> > On 08/11/2022 06:13 Bart Schaefer <schaefer@brasslantern.com> wrote:
> > On Mon, Nov 7, 2022 at 5:57 PM Pier Paolo Grassi <pierpaolog@gmail.com>
> 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
> +>
>
>

[-- Attachment #2: Type: text/html, Size: 4716 bytes --]

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

end of thread, other threads:[~2022-11-09 11:13 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-08  1:56 while alias Pier Paolo Grassi
2022-11-08  6:13 ` Bart Schaefer
2022-11-08 12:39   ` Peter Stephenson
2022-11-09 11:11     ` Pier Paolo Grassi

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