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

Re: globbing in the repeat-count word gives "illegal character"



On 3/23/20, Daniel Shahaf <d.s@xxxxxxxxxxxxxxxxxx> wrote:
> Mikael Magnusson wrote on Tue, 17 Mar 2020 19:37 +0100:
>> On 3/17/20, Daniel Shahaf <d.s@xxxxxxxxxxxxxxxxxx> wrote:
>> > [[[
>> > $ Src/zsh -f
>> > % cd "$(mktemp -d)"
>> > % repeat ? true
>> > zsh: bad math expression: illegal character: \M-W
>> > %
>> > ]]]
>> >
>> > [[[
>> > frame #1: 0x0000000000487eac zsh`matheval(s="\x97") at math.c:1479
>> >    1476     x = mathevall(s, MPREC_TOP, &junk);
>> >    1477     mtok = xmtok;
>> >    1478     if (*junk)
>> > -> 1479         zerr("bad math expression: illegal character: %c",
>> > *junk);
>> >    1480     return x;
>> >    1481 }
>> >    1482
>> > (lldb) p *junk
>> > (char) $0 = '\x97'
>> > ]]]
>> >
>> > [[[
>> > % ag 0x97 | cat
>> > Src/zsh.h:191:#define Quest             ((char) 0x97)
>> > %
>> > ]]]
>>
>> Not limited to globbing characters,
>>
>> % repeat { false
>> zsh: bad math expression: illegal character: \M-O
>
> And what about this one? —
> .
>     % repeat 2*2 pwd
>     zsh: bad math expression: illegal character: \M-G
>
> What's the expected behaviour on this one?  Should it report a different
> error, or perform globbing, or take «2*2» as a valid arithmetic
> expression and run 4 iterations of the loop body?

Same as for return, I feel, ie,

% () { return 2*2 }
(anon): no matches found: 2*2
% () { return 2\*2 }; echo $?
4

But if, due to hysterical raisins, globbing never runs for repeat
here, I guess we may as well just have it do arithmetic unquoted
there... but#2 it's probably confusing wrt spaces around the * in that
case... So yeah, I guess I'm not too sure :).

My brain isn't in zsh-code-mode so I can't comment on the rest...

> Code-wise, execrepeat() calls singsub() when the "has tokens" flag is set:
>
>    487	int
>    487	execrepeat(Estate state, UNUSED(int do_exec))
>    488	{
>    ⋮
>    500	    lastval = 0;
>    501	    tmp = ecgetstr(state, EC_DUPTOK, &htok);
>    502	    if (htok)
>    503		singsub(&tmp);
>    504	    count = mathevali(tmp);
>    505	    if (errflag)
>    506		return 1;
>
> When singsub() returns, there are still tokens in the string (Quest,
> Inbrace, or Star, respectively).  Is that expected, or should singsub()
> have converted those tokens to their ASCII equivalents?
>
> Is the fix just to call untokenize() after singsub()?  Some singsub()
> callers do this, but some don't, and I haven't figured out the rule (if
> there is one).  I tried this and it seemed to work, but…
>
> Cheers,
>
> Daniel
>


-- 
Mikael Magnusson



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