zsh-workers
 help / color / mirror / code / Atom feed
* The big kre zsh bug report
       [not found] ` <b8851c3a50bd8bceba1961f2f764e1a6869481ac.camel@ntlworld.com>
@ 2018-12-20 22:25   ` Martijn Dekker
  2018-12-21  7:53     ` Bart Schaefer
  2018-12-21 11:30     ` The big kre zsh bug report Robert Elz
  2018-12-21  2:28   ` Robert Elz
  1 sibling, 2 replies; 31+ messages in thread
From: Martijn Dekker @ 2018-12-20 22:25 UTC (permalink / raw)
  To: zsh-workers; +Cc: Robert Elz

Robert Elz a.k.a. kre (author of NetBSD sh) ran "zsh-5.6.2 --emulate sh" 
against his NetBSD sh test suite and came up with a laundry list of test 
failures which he wanted to filter through me. Here are the ones I could 
reproduce in zsh-5.6.2-test-2 and which seemed like bugs to me.

I've ommitted test failures that clearly represent legit zsh extensions, 
such as empty command lists, arithmetic expressions in lieu of numeric 
arguments to builtins, or zsh-specific parameter expansions. At least I 
don't *think* it is the aim of sh/ksh/bash emulation mode to disable all 
zsh extensions -- just those that would cause incompatibilities.

_____________________
First, kre noted that things like $(( x )), $(( x+=1 )), and the like 
don't error out if 'set -u' (-o nounset) is active. I don't think that's 
technically a bug, because 'set -u' is specified to apply to parameter 
expansion and not arithmetic expansion. (Note that $(( $x )) contains a 
parameter expansion and 'set -u' works as expected.)

However, I think having 'set -u' apply to $(( x )) is "obvious" and 
useful behaviour. Bash, ksh93, dash, FreeBSD sh and NetBSD sh already do 
it (mksh and yash don't). I can't think of any downside so this 
behaviour. So perhaps this could be considered a feature request.

All further quoted text below is from kre... (Note his test suite output 
doesn't quote the '-c' option argument, but the tests are executed as if 
it were quoted with single quotes.)

Op 07-12-18 om 11:39 schreef Robert Elz:
> Next, for something different:
> 
> tc-so:Executing command [ zsh --emulate sh -c sleep 1 & P=$!; jobs; wait ]
> tc-se:Fail: regexp Running not in stdout
> tc-se:[1]  + running    sleep 1
> 
> Posix says of the "jobs" command that the status is Running (with a capital R)
> not "running" with a lower case 'r'.    (Same with Done, ...)

Confirmed. (Note this applies to the POSIX locale.)
Ref.: 
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/jobs.html#tag_20_62_10

_____________________
> Next:
> 
> tc-so:Executing command [ zsh --emulate sh -c for op in + - \* / %
> tc-so:            do
> tc-so:                echo $(( $( echo 9 ) $( echo "${op}" ) $( echo 2 ) ))
> tc-so:            done ]
> tc-se:Fail: incorrect exit status: 1, expected: 0
> tc-se:stdout:
> tc-se:11
> tc-se:
> tc-se:stderr:
> tc-se:zsh:3: bad math expression: operator expected at `2 '
> tc-se:
> 
> I am not sure what happened with that one.   zsh did do...
> 
> tc-so:Executing command [ zsh --emulate sh -c echo $(( $( echo 3 ) $( echo + ) $
> ( echo 4 ) )) ]
> 
> correctly, so it can handle expansions inside a $(( )) - perhaps the "${op}"
> being quoted confused it, but those quotes are inside $( ) and will not survive
> the result of that expansion (they are removed before echo runs), so should
> be invisible to the arith code.   They are needed so the '*' is not subject to
> filename expansion in the case when op=\*

Yes, I don't think the "${op}" being quoted has anything to do with it. 
It fails only at the second loop iteration, so with '-' as the operator.

So it doesn't like this:

$ zsh --emulate sh -c 'echo $(( $(echo 9) $(echo -) $(echo 2) ))'
zsh:1: bad math expression: operator expected at `2 '
$ zsh --emulate sh -c 'echo $(( 9 `echo -` 2 ))'
zsh:1: bad math expression: operator expected at `2 '

Whereas these works fine:

$ zsh --emulate sh -c 'echo $(( $(echo 9) - $(echo 2) ))'
7
$ zsh --emulate sh -c 'echo $(( 9 $(echo +) 2 ))'
11
$ zsh --emulate sh -c 'echo $(( 9 $(echo \*) 2 ))'
18
$ zsh --emulate sh -c 'echo $(( 9 `echo /` 2 ))'
4

So yes, that's a bug; the '-' operator is somehow handled differently 
from the rest.

_____________________
> This next one is (smilar to) the one you (Martijn) reported wrt
> the NetBSD shell just recently (one of the new tests I added
> when I fixed it...)
> 
> tc-so:Executing command [ zsh --emulate sh -c . ./h-f3; X=1; set -- ; delim_argv "${X+$@}" ]
> tc-se:Fail: stdout does not match expected value
> tc-se:--- /tmp/inline.Ph8gBl    2018-12-07 05:42:15.944365210 +0000
> tc-se:+++ /tmp/check.JvvNwL/stdout      2018-12-07 05:42:15.944098585 +0000
> tc-se:@@ -1 +1 @@
> tc-se:-
> tc-se:+><       
> 
> "h-f3" just contains the definition of the delim_argv function, which
> is simply...
> 
> delim_argv() {
>         str=
>         for Arg; do
>                 str="${str:+${str} }>${Arg}<"
>         done
>         printf '%s\n' "${str}"
> } 
> 
> ie: stick ><  (angle quotes, except in the backwards
> order, so they are more obvious) around each arg.
> 
> This indicates that zsh is parsing that the same way we did I
> think, and not producing nothing when there are no args from
> the (enclosed) quoted $@
> 
> The output is a diff -u with the first arg ('-' lines in output) being what
> was expected (the file with "inline" in its name) and the 2nd arg ('+'
> lines in the output) being the output from the command.

Hmm... to make this a little easier to understand and reproduce:

zsh --emulate sh -c 'delim_argv() { str=;
		for Arg do str="${str:+${str} }>${Arg}<"; done;
		printf "%s\n" "${str}"; };
	X=1; set -- ; delim_argv "${X+$@}"'

zsh, bash, dash, ksh93, mksh >= R50e, FreeBSD sh output:
 ><

yash, mksh <= R50 output nothing.

So the issue is that "${X+$@}" should be removed completely and not 
leave an empty quoted string if X is set, but there are no positional 
parameters.

Looks logical to me: in that the ${X+$@} parameter substitution 
substitutes $@, within quotes, leaving "$@", which is definitely removed 
completely if there are no positional parameters.

But if this is a bug, it's certainly a widespread one!

_____________________
> tc-se:dollar_hash[7]: Test of 'set -- a b c; echo ${\#}' failed.
> tc-se:[7] expected exit code 2, got 0
> tc-se:[7] Expected messages on stderr, nothing produced
> tc-se:[7] Expected output '', received '3' 
> tc-se:[7] Full command: <<set -- a b c; echo ${\#}>>
> 
> The \ is not removed before var expansion, ${\#} is not ${#}
> and \# is not a valid var name, nor is \ if this is being parsed
> as a substring match on ${\}  
> so this should be a syntax error
> (at least in sh emulation mode).
> 
> There is another test which fails in a similar way for the same
> reason ...
> 
> tc-se:dollar_hash[8]: Test of 'set -- a b c; echo ${\#:-foo}' failed.

Confirmed. ${\#} or ${\#:-foo} should be syntax errors, but aren't.

Same with other special parameters: ${\?}, ${\!}, etc. and even normal 
variables: ${\foo}.

_____________________
> And something different, but related, perhaps:
> 
> tc-se:dollar_hash[48]: Test of 'x=hello; set -- a b c; echo ${#x:-1}' failed.
> tc-se:[48] expected exit code 2, got 0
> tc-se:[48] Expected messages on stderr, nothing produced
> tc-se:[48] Expected output '', received '5'
> tc-se:[48] Full command: <<x=hello; set -- a b c; echo ${#x:-1}>>
> 
> Combining length and set/not set operators is not defined in sh,
> and makes no sense anyway, as ${#x} is always set (it is a number,
> 0 .. whatever, so cannot be unset or null - if 'x' is unset and -u
> is on, there might be an error, but returning the length of $x with
> this nonsense syntax is always incorrect).
> 
> And more like that one ...
> 
> tc-se:dollar_hash[49]: Test of 'x=hello; set -- a b c; echo ${#x-1}' failed.
> tc-se:dollar_hash[50]: Test of 'x=hello; set -- a b c; echo ${#x:+1}' failed.
> tc-se:dollar_hash[51]: Test of 'x=hello; set -- a b c; echo ${#x+1}' failed.
> tc-se:dollar_hash[52]: Test of 'x=hello; set -- a b c; echo ${#x+1}' failed.
> tc-se:dollar_hash[53]: Test of 'x=hello; set -- a b c; echo ${#x:?msg}' failed.
> tc-se:dollar_hash[54]: Test of 'x=hello; set -- a b c; echo ${#x?msg}' failed.
> tc-se:dollar_hash[55]: Test of 'x=hello; set -- a b c; echo ${#x:=val}' failed.
> tc-se:dollar_hash[56]: Test of 'x=hello; set -- a b c; echo ${#x=val}' failed.
> tc-se:dollar_hash[57]: Test of 'x=hello; set -- a b c; echo ${#x#h}' failed.
> tc-se:dollar_hash[58]: Test of 'x=hello; set -- a b c; echo ${#x#*l}' failed.
> tc-se:dollar_hash[59]: Test of 'x=hello; set -- a b c; echo ${#x##*l}' failed.
> tc-se:dollar_hash[60]: Test of 'x=hello; set -- a b c; echo ${#x%o}' failed.
> tc-se:dollar_hash[61]: Test of 'x=hello; set -- a b c; echo ${#x%l*}' failed.
> tc-se:dollar_hash[62]: Test of 'x=hello; set -- a b c; echo ${#x%%l*}' failed.

I'll leave this for the zsh developers to consider, but personally I 
think we can legitimately consider this an artefact of a zsh extension.

Zsh has always allowed combining things in parameter substitutions that 
other shells don't, and allowing nonsensical combinations is simply a 
side effect of allowing other, sensible ones. Zsh accepting something 
other POSIX shells don't, even in emulation mode, will not cause any 
compatibility problems as long as POSIX syntax is followed.

As far as I know, no shell except yash aims to prohibit everything not 
allowed by POSIX in its POSIX compatibility mode. (IOW, for a strict 
POSIX compatibility test, I'd highly recommend 'yash -o posix'!)

_____________________
> Next we get similar tests, but this time we are testing $# rather than the
> length of a var operator...
> 
> tc-se:dollar_hash[79]: Test of 'set -- a b c; echo ${#:-99}' failed.
> tc-se:[79] Expected output '3', received '2'
> tc-se:[79] Full command: <<set -- a b c; echo ${#:-99}>>
> 
> For $# I am not sure posix requires handling the tests for set/unset
> (as $# is always set) so I would understand an error here, but not
> the wrong answer, there are 3 args $# should be 3, it is never unset
> or null, so the :-99 part should just be noise (or an error).

Confirmed:

$ zsh --emulate sh -c 'set -- a b c; echo ${#:-99}'
2

That should be 3, so this is a bug.

Hmmm...

$ zsh --emulate sh -c 'set -- a b c; echo ${#}'
3
$ zsh --emulate sh -c 'set -- a b c; echo ${#:-}'
0
$ zsh --emulate sh -c 'set -- a b c; echo ${#:-3}'
1
$ zsh --emulate sh -c 'set -- a b c; echo ${#:-3000}'
4
$ zsh --emulate sh -c 'set -- a b c; echo ${#:-10chstring}'
10
$ zsh --emulate sh -c 'bar=10chstring; set -- a b c; echo ${#:-$bar}'
10

So what happens is that ${#:-foo} measures the length of whatever 
follows ':-'. Interesting behaviour, but not correct, at least not for 
POSIX mode.

_____________________
> This next one does generate an error from zsh, which is not
> unreasonable:
> 
> tc-se:dollar_hash[80]: Test of 'set -- a b c; echo ${#-99}' failed.
> tc-se:[80] expected exit code 0, got 1
> tc-se:[80] Messages produced on stderr unexpected...
> tc-se:zsh:1: bad substitution
> tc-se:[80] Expected output '3', received ''
> tc-se:[80] Full command: <<set -- a b c; echo ${#-99}>>
> 
> so why it acted differently when the ':' was there is hard to explain.

I think it's a (minor) bug. Since $# is always set, ${#-foo} should be 
accepted as equivalent to $#.

> I see them same (not really incorrect, this is in "unspecified" territory
> I think ... our tests test NetBSD sh behaviour)...
> 
> tc-se:dollar_hash[84]: Test of 'set -- a b c; echo ${#?bogus}' failed.
> tc-se:[84] expected exit code 0, got 1
> tc-se:[84] Messages produced on stderr unexpected...
> tc-se:zsh:1: bad substitution
> tc-se:[84] Expected output '3', received ''
> tc-se:[84] Full command: <<set -- a b c; echo ${#?bogus}>>

IMHO, same as above: $# is always set, so ${#?bogus} should be accepted 
as equivalent to $#.

_____________________
> This next one is an obvious, and common, problem ...
> 
> tc-se:shell_params[13]: Test of 'set -- a b c d; echo ${4294967297}' failed.
> tc-se:[13] Expected output '', received 'a'
> tc-se:[13] Full command: <<set -- a b c d; echo ${4294967297}>>
> 
> (4294967297 & 0xFFFFFFFF) == 1
> 
> This indicates that 32 bit arith overflow occurred, and wasn't detected.

Confirmed (also on ksh93 and dash).

_____________________
> This next one indicates that \newline line joining is not working correctly
> I think ...
> 
> tc-so:Executing command [ zsh --emulate sh -c line='#define bindir "/usr/bin" /* comment */'; echo :"$\
> tc-so:{li\
> tc-so:ne%\
> tc-so:'/*'*}": ] 
> tc-se:Fail: stdout does not match expected value
> tc-se:--- /tmp/inline.FL7wVx    2018-12-07 05:42:17.365040418 +0000
> tc-se:+++ /tmp/check.5PcEmx/stdout      2018-12-07 05:42:17.364785460 +0000
> tc-se:@@ -1 +1 @@
> tc-se:-:#define bindir "/usr/bin" :
> tc-se:+:{line%'/*'*}:   
> 
> Since the previous test ...
> 
> tc-so:Executing command [ zsh --emulate sh -c line='#define bindir "/usr/bin" /* comment */'; echo :${line\
> tc-so:%\
> tc-so:'/*'*}: ]  
> 
> does work, and it should end up being the exact same thing, my guess is
> that the ${ with a \newline between the $ and { is not working as it should.

Confirmed. A bit more experimenting shows that it breaks between '$' and 
'{' and nowhere else. Very unlikely for line continuation to be used 
there in real-life scripts, but still a bug.

$ zsh --emulate sh -c 'foo=bar; echo $\
foo'
bar
$ zsh --emulate sh -c 'foo=bar; echo $\
{foo}'
{foo}
$ zsh -c 'line='\''#define bindir "/usr/bin" /* comment */'\''; echo 
:"${\
l\
i\
n\
e\
%\
'\''\
/\
*\
'\''\
*\
}\
"\
:'
:#define bindir "/usr/bin" :

_____________________
> Next ...
> 
> 	check 't=" x";     IFS=" x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '1'
> 
> The first arg to "check" is evaluated using ${SHELL} -c the 2nd arg is the
> expected output....    This one is test 2 of the IFS tests (test 1 
> passed).
> 
> tc-end: 1544161337.630429, ifs, failed, Test 2 't=" x";     ...': expected [1], found [2 :]
> 
> (unfortunately here, when it fails, the "check" in question truncates the
> command in the message, it is expected you will look at the test source
> to see what it really was.... so I am including the ones that fail.   I should
> improve the output from this "check" function - this was an early version...
> 
> The data enclosed in [] is what should have been output. and what
> actually was.
> 
> I think this means that zsh is not treating non-whitespace IFS characters
> as field terminators, but as field separators, which is not the way it is
> supposed to be.  A later failure is because of the same thing I believe.

Confirmed. Modernish identifies this as a shell quirk (QRK_IFSFINAL) 
because the POSIX spec is quite ambiguous on this, so I was unable to 
confirm that it is actually a bug and not a legitimate behaviour variant.

However, yash's author, magicant, has since decided it's a bug, and 
fixed it, adding a shell option to restore the old behaviour. See 
discussion here:
https://osdn.net/projects/yash/ticket/35283

He refers to this clarification:
http://www.open-std.org/JTC1/SC22/WG15/docs/rr/9945-2/9945-2-98.html

So this should probably be fixed, at least for sh emulation mode.

_____________________
> Next, with IFS containing a digit...
> 
>         check 'IFS=5; echo $(( 123456789 ))'    '1234 6789'
> 
> tc-end: 1544161337.819973, split_arith, failed, Test 1 'IFS=5; echo ...': expect
> ed [1234 6789], found [123456789]

This has come up before on zsh-workers. It's known that artihmetic 
expansion is not subject to field splitting in zsh and they've declined 
to fix it on the grounds that field splitting arithmetic expansions is 
nonsensical. I would prefer consistent field splitting of all dollar 
expansions as the standard requires, but was outgunned by Stéphane 
Chazelas. (IMHO, a more sensible use case would be to split on the 
decimal point.)

_____________________
> The next test is also perhaps dubious, and bizarre, but ...
> 
>         check 'cat <<  echo'"${nl}"'\'"${nl}echo${nl}echo${nl}" 'echo' 0
> 
> ($nl is a single newline character).
> 
> tc-se:lineends[2]: test of 'cat <<  echo
> tc-se:\
> tc-se:echo
> tc-se:echo
> tc-se:' failed
> 
> The point here is that the here doc delimiter
> is unqoted "echo", then in the here doc, the \
> on the first line joins the 2nd line to it, which
> as I read the spec, means it cannot be the
> terminator of the here doc, no matter what it
> ends up containing, as that is required to be
> on a line containing nothing else (after leading
> tabs are stripped if appropriate, which isn't the
> case here, and there aren't any anyway).  If
> a line has been joined to a previous line, I interpret
> that as meaning it cannot be the terminator (and
> allowing it to be adds nothing useful to the shell,
> other than the potential for errors).
> 
> Hence, I believe in this that "echo" is the correct
> output.    But if the first "echo" terminates, we get
> no output (as trailing newlines get removed by
> the command substitution that "check" uses to
> capture the results, so the missing \n from the
> echo command that would follow makes sense).
> 
> But this is a view of how here docs work that is
> not necessarily agreed by all...

Your interpretation looks correct to me, but few real-life shells follow 
it (dash, recent yash, and ksh93 are the ones I can quickly identify).

_____________________
> Next, zsh apparently does not implement the posix
> required -h option.   Nor do we, but we at least allow
> it to be set and cleared ....

I'm not sure that allowing it to be set and then not doing what it 
promises is better than not allowing it to be set at all.

_____________________
> Next onto pattern tests ...
> 
> tc-se:case_matching[51]: Test of 'case "[a-c]" in ([a-c\]) printf M;; (*) printf X;; esac' failed.
> tc-se:[51] Messages produced on stderr unexpected...
> tc-se:zsh:1: bad pattern: [a-c]
> tc-se:[51] Expected output 'M', received ''
> tc-se:[51] Full command: <<case "[a-c]" in ([a-c\]) printf M;; (*) printf X;; esac>>
> 
> There is no such thing as a "bad pattern" in sh - there is no
> [xyz] expression there, because of the quoted ']' (so there is
> no terminator) which means the '[' is just a character, so this
> pattern is effectively just "[a-c]" which should match the word
> which is the same thing.
> 
> It works when the [ is quoted ( \[a-c] ), or when the whole thing is ( "[a-c]" ).

[...and, moved up here from later in the original email...]
> tc-se:var_substring_matching[94]: Test of 'var='[a-c]d-f';printf '%s\n' ${var#[a-c\]}' failed.
> tc-se:[94] expected exit code 0, got 1
> tc-se:[94] Messages produced on stderr unexpected...
> tc-se:zsh:1: bad pattern: [a-c]
> tc-se:[94] Expected output 'd-f', received ''
> tc-se:[94] Full command: <<var='[a-c]d-f';printf '%s\n' ${var#[a-c\]}>>
> 
> This is the same issue as the earlier 'case' matching problem.
> There are no bad patterns in sh.   Ever.   The literal string
> '[a-c]' should be removed from the start of the value of var.

Properly quoted test cases:

$ zsh --emulate sh -c 'case "[a-c]" in ([a-c\]) printf M;;
	(*) printf X;; esac'
$ zsh --emulate sh -c "var='[a-c]d-f';printf '%s\\n' \${var#[a-c\\]}"

Confirmed. The first test case works on all shells except zsh. For the 
second, it works on all except zsh, ksh93 and mksh; the latter two don't 
throw an error, but fail to remove the '[a-c]'.

_____________________
> tc-se:case_matching[90]: Test of 'case a in ([[\:alpha:]]) printf M;; (*) printf X;; esac' failed.
> tc-se:[90] Expected output 'X', received 'M'
> tc-se:[90] Full command: <<case a in ([[\:alpha:]]) printf M;; (*) printf X;; esac>>
> 
> Here the quoted ':' means there is no char-class, so what is
> left is a simple [xyz] expression, where the xyz part is "[\:alpha:"
> the following ']' terminates that expression, and the ']' that
> follows it is just a character.   The 'a' matches the [...] (which
> contains an 'a') but there is nothing in the word to match that
> extra ']', so the match should fail.
> 
> tc-se:case_matching[96]: Test of 'var=":alpha:"; case B in ([["$var"]]) printf M;; (*) printf X;; esac' failed.
> tc-se:[96] Expected output 'X', received 'M'
> tc-se:[96] Full command: <<var=":alpha:"; case B in ([["$var"]]) printf M;; (*) printf X;; esac>>
> 
> This is similar. the : is quoted (via quoted $var) so there is no
> char class, 
> just a [] expression followed by a stray ']'
> 
> tc-se:case_matching[98]: Test of 'var=":alpha:"; case "[]" in ([["$var"]]) printf M;; (*) printf X;; esac' failed.
> tc-se:[98] Expected output 'M', received 'X'
> tc-se:[98] Full command: <<var=":alpha:"; case "[]" in ([["$var"]]) printf M;; (*) printf X;; esac>>
> 
> This is the same thing, buit in a "should match" scenario, the [
> in the word is matched by the [xyz] expression, which contains a '['
> (for the same reason as the last two) and the ] in the word matches
> the trailing ] that comes after the [xyz] expression, and we have a match.

Yes, that looks like three ways of testing the same thing.

Shells differ here. bash, dash, mksh<=R55 print X on the first and 
second, M on the third; yash, ksh93, mksh>=R56c, zsh print M on the 
first and second, X on the third.

_____________________
> tc-se:case_matching[147]: Test of 'var='\z'; case ${var} in (${var}) printf M;; (*) printf X;; esac' failed.
> tc-se:[147] Expected output 'X', received 'M'
> tc-se:[147] Full command: <<var='\z'; case ${var} in (${var}) printf M;; (*) printf X;; esac>>
> 
> The word to match is two chars, backslash and z, the pattern is
> a quoted 'z' (the backslash becomes a quoting character).   After
> that happens, there is nothing magic in the pattern, just one literal
> char, 2 chars can never match 1, so it should fail.

Properly quoted test case:

$ zsh --emulate sh -c 'var='\''\z'\'';
	case ${var} in (${var}) printf M;; (*) printf X;; esac'

This outputs X on bash, dash, ksh93, and M on yash, mksh, zsh.

This issue caused me headaches when implementing match() on modernish. I 
was given the impression that passing backslash-quoted characters 
through variables for use in 'case' patterns was one of those things 
that POSIX doesn't really specify one way or another. Of course I would 
much prefer the behaviour of bash, dash, and NetBSD sh.

_____________________
> tc-se:case_matching[265]: Test of 'var='\'; case '\' in ($var) printf M;; (*) printf X;; esac' failed.
> tc-se:[265] Expected output 'X', received 'M'
> tc-se:[265] Full command: <<var='\'; case '\' in ($var) printf M;; (*) printf X;; esac>>
> 
> This one is excusable, a \ followed by nothing in a pattern is an unspecified
> case, so anything is OK, and treating it as a literal \ is reasonable (it is
> just not what we do ... it is also not what bash does, so as this one also 
> fails in bash emulation, there probably is something that needs fixing.
> 
> tc-se:case_matching[267]: Test of 'set -- \\ \\; case $1 in ($2) printf M;; (*) printf X;; esac' failed.
> tc-se:[267] Expected output 'X', received 'M'
> tc-se:[267] Full command: <<set -- \\ \\; case $1 in ($2) printf M;; (*) printf X;; esac>>
> 
> This one is the same, both pattern and word are '\'  just created
> in a different way.
> 
> tc-se:case_matching[271]: Test of 'case '\' in ($( echo '\' )) printf M;; (*) printf X;; esac' failed.
> tc-se:[271] Expected output 'X', received 'M'
> tc-se:[271] Full command: <<case '\' in ($( echo '\' )) printf M;; (*) printf X;; esac>>
> 
> That one too.   Note all 3 of them work the same in bash as we expect,
> and all 3 still fail with zsh --emulate bash

I'm not sure the zsh authors aim to make emulation modes quite that 
exact, but I'll just leave this here for their consideration.

_____________________
> tc-se:var_substring_matching[47]: Test of 'var='abc';printf '%s\n' ${var%*}' failed.
> tc-se:[47] Expected output 'abc', received 'ab'
> tc-se:[47] Full command: <<var='abc';printf '%s\n' ${var%*}>>
> 
> This one is easy, * should start out matching nothing, that matches, so
> nothing should be removed from the value.   zsh is removing 'c'.
> (Yes, it is a stupid thing to do, or to expect to work, but it is how it
> is supposed to function.)
> 
> tc-se:var_substring_matching[48]: Test of 'var='abc';printf '%s\n' "${var%*}"' failed.
> tc-se:[48] Expected output 'abc', received 'ab'
> tc-se:[48] Full command: <<var='abc';printf '%s\n' "${var%*}">>
> 
> That is the same, just in a quoted expansion (should change nothing).

Properly quoted test cases:

$ zsh --emulate sh -c "var='abc';printf '%s\\n' \${var%*}"
$ zsh --emulate sh -c "var='abc';printf '%s\\n' \"\${var%*}\""

Bug confirmed; every shell except zsh prints 'abc'.

_____________________
Various other tests showed that zsh cannot handle file descriptors >9. 
Not really a bug as POSIX permits that limitation, but:

> And again, this test fails the same way with --emulate bash
> and bash certainly permits fds > 9!

So you could consider this a feature request.

_____________________
> tc-so:Executing command [ zsh --emulate sh -c  set -- a b c d; shift 1 1 ; echo FAILED  ]
> tc-se:Fail: incorrect exit status: 0, expected: anything else
> tc-se:stdout:
> tc-se:FAILED
> tc-se:
> tc-se:stderr:
> tc-se:
> 
> shift should only take 1 arg, not two ... but most shells do not check that,
> so this one is perhaps excusable.

I think builtins should always fail on excess arguments since, outside 
of test cases, that is a clear indication something has gone awry in the 
script.

_____________________
> In this one zsh is generating a syntax error, when there is none...
> 
> tc-so:Executing command [ zsh --emulate sh -c echo hello; true&false&:&cat</dev/null>/dev/null&x=3& echo world ]
> tc-se:Fail: incorrect exit status: 1, expected: 0
> tc-se:stdout:
> tc-se:
> tc-se:stderr:
> tc-se:zsh:1: parse error near `&'
> tc-se:
> 
> Which of the numerous '&' chars it does not like I have no idea.

Looks like zsh doesn't like a bare shell assignment as a background job.

$ zsh --emulate sh -c 'x=3 &'
zsh:1: parse error near `&'

Pointless or not, this is a bug. All other shells accept this.

_____________________
> tc-so:Executing command [ zsh --emulate sh -c case in in (esac|cat ]
> tc-se:Fail: incorrect exit status: 0, expected: anything else
> tc-se:stdout:
> tc-se:
> tc-se:stderr:
> tc-se:
> 
> I cannot even begin to imagine what that nonsense parsed as...
> (but once a case pattern is started with the optional '(' it requires
> the following ')' to complete it, always.

Probably related to zsh accepting empty command lists in all sorts of 
contexts where other shells don't. But it still seems strange that it 
accepts this:

$ zsh --emulate sh -c 'case in in (esac'
(no syntax error produced)

_____________________
> And another one that zsh cannot parse, though again, this one
> is legal...
> 
> tc-so:Executing command [ zsh --emulate sh -c if if :;then :;fi then :;fi ]
> tc-se:Fail: incorrect exit status: 1, expected: 0
> tc-se:stdout:
> tc-se:
> tc-se:stderr:
> tc-se:zsh:1: parse error near `then'
> tc-se:
> 
> I would guess it is the second "then" that follows "fi" with no ';'
> that is the problem, but that is OK syntax.

I would not have thought that to be correct syntax, but sure enough, 
every shell except zsh accepts it.

A similar case (with another reserved word, 'esac', directly preceding 
'then') works fine:

$ zsh --emulate sh -c 'if case a in a) ;; esac then :; fi'
(no syntax error produced)

However, this one fails on zsh and works on all other shells:

$ zsh --emulate sh -c 'if until :; do :; done then :; fi'
zsh:1: parse error near `then'

_____________________
> tc-so:Executing command [ zsh --emulate sh -c case x in (|| | ||) ;; esac ]
> tc-se:Fail: incorrect exit status: 0, expected: anything else
> tc-se:stdout:
> tc-se:
> tc-se:stderr:
> tc-se:
> 
> Not sure what I should say about that one... (but patterns are not
> allowed to be completely missing, there must be a word, and lots
> of alternative illegal missing patterns does not make it legal).

This was a syntax error in zsh until 5.4.1; 5.4.2 starts accepting it.

Strangely, dash accepts this.

_____________________
> There is a failure of a test testing %n notation for jobs in wait commands,
> but I need to check that one more carefully before complaining about it
> failing, it may be that the test is technically invalid (ie: that zsh is
> permitted to act as it does) but this next one ...
> 
> tc-so:Executing command [ zsh --emulate sh -c wait 1 ]
> tc-se:Fail: incorrect exit status: 1, expected: 127
> tc-se:stdout:
> tc-se:
> tc-se:stderr:
> tc-se:zsh:wait:1: pid 1 is not a child of this shell
> tc-se:
> 
> is clearly wrong.  The error message is maybe OK (it is
> correct, though I don't think "wait" is supposed to issue it)
> but the exit status is clearly wrong, wait is required to return
> status 127 when the given pid is not a child, not 1.

Bug confirmed:
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/wait.html#tag_20_153_14

ksh93 returns status 0, which is even more wrong! All other shells 
except zsh return status 127.

_____________________

That's it. Hope this is useful!

- M.

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

* Re: The big kre zsh bug report
       [not found] ` <b8851c3a50bd8bceba1961f2f764e1a6869481ac.camel@ntlworld.com>
  2018-12-20 22:25   ` The big kre zsh bug report Martijn Dekker
@ 2018-12-21  2:28   ` Robert Elz
  1 sibling, 0 replies; 31+ messages in thread
From: Robert Elz @ 2018-12-21  2:28 UTC (permalink / raw)
  To: Martijn Dekker; +Cc: zsh-workers

    Date:        Thu, 20 Dec 2018 22:25:12 +0000
    From:        Martijn Dekker <martijn@inlv.org>
    Message-ID:  <18f684a8-2fec-4ebe-a63e-cf6688ae519f@inlv.org>

  | Robert Elz a.k.a. kre (author of NetBSD sh)

definitely not author, but I am doing most of the current maintenance
(and a few upgrades).

  | All further quoted text below is from kre... (Note his test suite output 
  | doesn't quote the '-c' option argument, but the tests are executed as if 
  | it were quoted with single quotes.)

Yes, sorry about that, the tests are run by code that almost everyone would
like to replace, and which is mostly not maintained (but, aside from mostly
cosmetic issues like this, does work)...   That's where that output comes from.


  | Yes, I don't think the "${op}" being quoted has anything to do with it. 
  | It fails only at the second loop iteration, so with '-' as the operator.
  |
  | So it doesn't like this:
  |
  | $ zsh --emulate sh -c 'echo $(( $(echo 9) $(echo -) $(echo 2) ))'
  | zsh:1: bad math expression: operator expected at `2 '
  | $ zsh --emulate sh -c 'echo $(( 9 `echo -` 2 ))'
  | zsh:1: bad math expression: operator expected at `2 '

I thought I corrected this one, either later in the big message, or a 
subsequent one.   The issue there is the use of echo where the
first arg starts '-' which is definitely an undefined area (the AT&T
idiots who broke the original Bell Labs echo have a lot to answer
for!)    I am going to change my tests to use printf instead.  There
is no issue here with zsh.

  | $ zsh --emulate sh -c 'set -- a b c; echo ${#:-99}'
  | 2
  |
  | That should be 3, so this is a bug.

Dealing with # in parameter expansions is painful, as it has
so many possible meanings, which need to be figured out
by context (not all of which have defined results).

But where it can reasonably be ${#} (with perhaps some
extra modifiers) it really ought to be.

  | Confirmed. Modernish identifies this as a shell quirk (QRK_IFSFINAL) 
  | because the POSIX spec is quite ambiguous on this, so I was unable to 
  | confirm that it is actually a bug and not a legitimate behaviour variant.

It is not supposed to be ambiguous any more - it used to be once.

In XCU 2.6.5:

The shell shall treat each character of the IFS as a delimiter and use the delimiters as field
terminators to split the results of parameter expansion, command substitution, and arithmetic |
expansion into fields.
[...]
b. Each occurrence in the input of an IFS character that is not IFS white space, along
     with any adjacent IFS white space, shall delimit a field, as described previously.

The std (consistently) uses "delimit" to mean "terminate" not "separate" but 
some readers misunderstand, and assume it means "separate" (as in, occurs 
between)

The intent is that when something is being collected (a field here, a
token in the lexer, ...) and the text says the next char "delimits the xxx"
it means that whatever was being collected is finished, what follows
depends upon what appears (if anything) - the delimiting character
does not, by itself, create anything following.

This is particularly confusing with field splitting, as "IFS" is used, and
the 'S' in that is "separator" which is preisely what it is not.   But the
name is historic.


  | _____________________
  | > Next, zsh apparently does not implement the posix
  | > required -h option.   Nor do we, but we at least allow
  | > it to be set and cleared ....
  |
  | I'm not sure that allowing it to be set and then not doing what it 
  | promises is better than not allowing it to be set at all.

If anything actually differs when that nonsense (implemented as
specified, which I am not sure anything does) is turned on, it would
be something of a surprise, and most likely break everything.

It is just that posix says that the option is supposed to exist, so
some script might turn it on.   Why I could not guess...


  | This issue caused me headaches when implementing match() on modernish. I 
  | was given the impression that passing backslash-quoted characters 
  | through variables for use in 'case' patterns was one of those things 
  | that POSIX doesn't really specify one way or another. Of course I would 
  | much prefer the behaviour of bash, dash, and NetBSD sh.

The pattern matching part of posix is due a rewrite (there is an open issue
with some potential fixes) - the intent is that it should work as you describe,
but it is hard (but not impossible) to read the current text to mean that.

  | _____________________
  | Various other tests showed that zsh cannot handle file descriptors >9. 
  | Not really a bug as POSIX permits that limitation, but:
  |
  | > And again, this test fails the same way with --emulate bash
  | > and bash certainly permits fds > 9!
  |
  | So you could consider this a feature request.

The '9' limit was created when the per-process file descriptor limit
was 16...   The shell needs a few fds for itself, so ...   These days
programs have access to lots more fds, so should sh scripts.


kre


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

* Re: The big kre zsh bug report
  2018-12-20 22:25   ` The big kre zsh bug report Martijn Dekker
@ 2018-12-21  7:53     ` Bart Schaefer
  2018-12-21  8:11       ` Fix for ${\var} oddity Bart Schaefer
                         ` (3 more replies)
  2018-12-21 11:30     ` The big kre zsh bug report Robert Elz
  1 sibling, 4 replies; 31+ messages in thread
From: Bart Schaefer @ 2018-12-21  7:53 UTC (permalink / raw)
  To: Martijn Dekker; +Cc: zsh-workers, Robert Elz

On Thu, Dec 20, 2018 at 2:48 PM Martijn Dekker <martijn@inlv.org> wrote:
>
> However, I think having 'set -u' apply to $(( x )) is "obvious" and
> useful behaviour.

Reasonable.

> > Posix says of the "jobs" command that the status is Running (with a capital R)
> > not "running" with a lower case 'r'.    (Same with Done, ...)

In this instance, I really don't give a damn what Posix says about it.
Zsh follows csh here, and this seems way too trivial to special-case.

> $ zsh --emulate sh -c 'echo $(( $(echo 9) $(echo -) $(echo 2) ))'
> zsh:1: bad math expression: operator expected at `2 '

"echo -" is a special case handled like "echo --" so it echoes nothing
and the operator disappears.  This has nothing to do with math or the
"-" operator.  (Elz has clarified this in his own reply.)

> > tc-so:Executing command [ zsh --emulate sh -c . ./h-f3; X=1; set -- ; delim_argv "${X+$@}" ]
>
> So the issue is that "${X+$@}" should be removed completely and not
> leave an empty quoted string if X is set, but there are no positional
> parameters.
>
> Looks logical to me: in that the ${X+$@} parameter substitution
> substitutes $@, within quotes, leaving "$@", which is definitely removed
> completely if there are no positional parameters.
>
> But if this is a bug, it's certainly a widespread one!

I'd prefer that this continue to act like bash and ksh than to follow
the abstract spec.

> > The \ is not removed before var expansion, ${\#} is not ${#}
> > and \# is not a valid var name, nor is \ if this is being parsed
> > as a substring match on ${\}
> > so this should be a syntax error
> > (at least in sh emulation mode).

This one surprised me.  Seems to come down to this code in params.c:

2341        } else if (inbrace && inull(*s)) {
2342            /*
2343             * Handles things like ${(f)"$(<file)"} by skipping
2344             * the double quotes.  We don't need to know what was
2345             * actually there; the presence of a String or Qstring
2346             * is good enough.
2347             */
2348            s++;

inull() is expected to match a quote there, but it happens to also
match backslash.  Fix in another thread.

> > Combining length and set/not set operators is not defined in sh,
> > and makes no sense anyway, as ${#x} is always set
>
> I'll leave this for the zsh developers to consider, but personally I
> think we can legitimately consider this an artefact of a zsh extension.

Agree, I'm strongly inclined to ignore this.

> > Next we get similar tests, but this time we are testing $# rather than the
> > length of a var operator...
> >
> > tc-se:dollar_hash[79]: Test of 'set -- a b c; echo ${#:-99}' failed.
> > tc-se:[79] Expected output '3', received '2'
> > tc-se:[79] Full command: <<set -- a b c; echo ${#:-99}>>
> >
> > For $# I am not sure posix requires handling the tests for set/unset
> > (as $# is always set) so I would understand an error here, but not
> > the wrong answer, there are 3 args $# should be 3, it is never unset
> > or null, so the :-99 part should just be noise (or an error).
>
> So what happens is that ${#:-foo} measures the length of whatever
> follows ':-'. Interesting behaviour, but not correct, at least not for
> POSIX mode.

Zsh allows an empty parameter name before ":-" and it is handling that
case before doing the length calculation.

That also explains this one:

> > tc-se:dollar_hash[80]: Test of 'set -- a b c; echo ${#-99}' failed.
> > tc-se:[80] expected exit code 0, got 1

% echo ${-99}
zsh: bad substitution

There was quite a lot of discussion of this on zsh-workers a while
back, as I recall, and it was decided at that time that ${#anything}
always means ${#${anything}} never ${${#}anything}.

I'm not expecting this to be up for debate again now.

Same for this one:

> > tc-se:dollar_hash[84]: Test of 'set -- a b c; echo ${#?bogus}' failed.
> > tc-se:[84] expected exit code 0, got 1

This is being treated as ${#${?bogus}}.

> > tc-se:shell_params[13]: Test of 'set -- a b c d; echo ${4294967297}' failed.
> > tc-se:[13] Expected output '', received 'a'
> >
> > This indicates that 32 bit arith overflow occurred, and wasn't detected.
>
> Confirmed (also on ksh93 and dash).

Checking for overflow here seems like a lot of computational expense
for a case that probably only happens in test suites.  Since zsh
implements arrays as actual non-sparse C arrays, memory is going to
explode long before anything manages to assign that many positional
parameters.

> > [...] my guess is
> > that the ${ with a \newline between the $ and { is not working as it should.
>
> Confirmed. A bit more experimenting shows that it breaks between '$' and
> '{' and nowhere else. Very unlikely for line continuation to be used
> there in real-life scripts, but still a bug.

Not going to argue with that one.  I suspect it's because the parser
is treating "{" as beginning a brace expansion (e.g., {a,b,c}) at that
point and so encodes it differently.

> > Next ...
> >
> >       check 't=" x";     IFS=" x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r' '1'
> >
> > I think this means that zsh is not treating non-whitespace IFS characters
> > as field terminators, but as field separators, which is not the way it is
> > supposed to be.  A later failure is because of the same thing I believe.
>
> Confirmed. Modernish identifies this as a shell quirk (QRK_IFSFINAL)
> because the POSIX spec is quite ambiguous on this, so I was unable to
> confirm that it is actually a bug and not a legitimate behaviour variant.

It seems to me that changing this for $=t in zsh native mode might
break a lot of things, so I'll leave it open for discussion as to
whether it's feasible to change it only for emulation mode.  However,
it does differ from the most recent version of bash I have handy.

> > Next, zsh apparently does not implement the posix
> > required -h option.   Nor do we, but we at least allow
> > it to be set and cleared ....

For the lazy or very busy reader:

-h  Locate and remember utilities invoked by functions as those
functions are defined (the utilities are normally located when the
function is executed).

This basically means doing path search at function definition time;
there's some dependence here on the formal definition of "utilities",
as I recall there are other cases where zsh differs from posix on
using builtins or functions to replace utilities.

> > There are no bad patterns in sh.   Ever.   The literal string
> > '[a-c]' should be removed from the start of the value of var.

This one is going to be very tricky to deal with.  Zsh does not
convert "invalid" patterns into plain strings and then match against
the plain strings; a pattern is either valid, or it is never used for
matching in the first place.  Thus in globbing:

% zsh --emulate sh
$ touch "[a-c]"
$ echo *[a-c\]
*[a-c]
$ bash
bash-4.1$ echo *[a-c\]
[a-c]

I think all the related cases cascade from this.

> > tc-se:case_matching[147]: Test of 'var='\z'; case ${var} in (${var}) printf M;; (*) printf X;; esac' failed.
> >
> > The word to match is two chars, backslash and z, the pattern is
> > a quoted 'z' (the backslash becomes a quoting character).

I don't think this is going to get fixed.  I went looking for this
test case but didn't find it:

var='"z"'; case ${var} in (${var}) printf M;; (*) printf X;; esac

This also prints M.  If backslash-z should become a quoted z,
shouldn't the above case also become a quoted z?  So that means in
case statements all variable references have to be treated as if they
were ${(Q)var} (to use zsh-speke)?  What if the quotes aren't
balanced?

> > This one is excusable, a \ followed by nothing in a pattern is an unspecified
> > case [...]
> > That one too.   Note all 3 of them work the same in bash as we expect,
> > and all 3 still fail with zsh --emulate bash
>
> I'm not sure the zsh authors aim to make emulation modes quite that
> exact, but I'll just leave this here for their consideration.

There isn't any --emulate bash, really, it's merly a synonym for
--emulate sh.  And therefore no, it's not intended to be perfect.
(Neither is --emulate ksh, although that has some distinctions from
sh.)

> > tc-se:var_substring_matching[47]: Test of 'var='abc';printf '%s\n' ${var%*}' failed.
> > tc-se:[47] Expected output 'abc', received 'ab'

This one has crept in along the way somewhere, zsh 3.0 and zsh 4.2
both work correctly, zsh 5.3 does not (I don't presently have access
to anything earlier in 5.x to try).

> Various other tests showed that zsh cannot handle file descriptors >9.

That's not true, it just doesn't handle redirection to descriptors >9
without the use of variant syntax.

> > tc-so:Executing command [ zsh --emulate sh -c  set -- a b c d; shift 1 1 ; echo FAILED  ]
> > tc-se:Fail: incorrect exit status: 0, expected: anything else
> > tc-se:stdout:
> > tc-se:FAILED
> > tc-se:
> > tc-se:stderr:
> > tc-se:
> >
> > shift should only take 1 arg, not two ... but most shells do not check that,
> > so this one is perhaps excusable.
>
> I think builtins should always fail on excess arguments since, outside
> of test cases, that is a clear indication something has gone awry in the
> script.

This isn't a bug.  "shift 1 1" means to shift the array $1 by one
position.  Zsh "shift" can even work on multiple arrays at once,
"shift 3 foo bar" means to shift both foo and bar by three.

You could argue that "shift thingthatisnotanarray" should complain,
but it's not about the number of arguments.

> Looks like zsh doesn't like a bare shell assignment as a background job.

This is a bug in native mode too.  Been that way forever.

> > tc-so:Executing command [ zsh --emulate sh -c case in in (esac|cat ]
> >
> > I cannot even begin to imagine what that nonsense parsed as...
> > (but once a case pattern is started with the optional '(' it requires
> > the following ')' to complete it, always.

This is an issue with "-c" and maybe also with a script file input.
If passed to an interactive shell, it's an incomplete parse (the PS2
prompt is printed and the shell waits for more input to finish the
case statement).  So it's not parsing as nonsense, it's parsing as
what it should, and then exiting zero when it hits end-of-file even
though it's still in the middle of a statement.  If I EOF the
interactive shell:

% case in in (esac|cat
case> zsh: parse error near `(esac|cat'

So this has apparently been special-cased to be silent when the shell
is not interactive.

> > tc-so:Executing command [ zsh --emulate sh -c if if :;then :;fi then :;fi ]

Another one that works up through 4.2 but breaks sometime at or before 5.3.

> $ zsh --emulate sh -c 'if until :; do :; done then :; fi'

This, too.

> > tc-so:Executing command [ zsh --emulate sh -c case x in (|| | ||) ;; esac ]
>
> This was a syntax error in zsh until 5.4.1; 5.4.2 starts accepting it.

I get this accepted by every version of zsh that I test.  It matches
the empty string:

% case '' in (|| | ||) print ok;; esac
ok

> > tc-so:Executing command [ zsh --emulate sh -c wait 1 ]
> > tc-se:Fail: incorrect exit status: 1, expected: 127

Probably easily fixed.

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

* Fix for ${\var} oddity
  2018-12-21  7:53     ` Bart Schaefer
@ 2018-12-21  8:11       ` Bart Schaefer
  2018-12-25 17:18       ` [PATCH] honour NO_UNSET when reading values in arithmetic expansion/commands Martijn Dekker
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 31+ messages in thread
From: Bart Schaefer @ 2018-12-21  8:11 UTC (permalink / raw)
  To: zsh-workers

On Thu, Dec 20, 2018 at 11:53 PM Bart Schaefer
<schaefer@brasslantern.com> wrote:
>
> > > The \ is not removed before var expansion, ${\#} is not ${#}
> > > and \# is not a valid var name, nor is \ if this is being parsed
> > > as a substring match on ${\}
> > > so this should be a syntax error
> > > (at least in sh emulation mode).
>
> This one surprised me.  Seems to come down to this code in params.c:
>
> 2341        } else if (inbrace && inull(*s)) {
> 2342            /*
> 2343             * Handles things like ${(f)"$(<file)"} by skipping
> 2344             * the double quotes.  We don't need to know what was
> 2345             * actually there; the presence of a String or Qstring
> 2346             * is good enough.
> 2347             */
> 2348            s++;
>
> inull() is expected to match a quote there, but it happens to also
> match backslash.  Fix in another thread.

diff --git a/Src/subst.c b/Src/subst.c
index ff6750a..60eb333 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -2338,7 +2338,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int
                zerr("bad substitution");
                return NULL;
            }
-       } else if (inbrace && inull(*s)) {
+       } else if (inbrace && inull(*s) && *s != Bnull) {
            /*
             * Handles things like ${(f)"$(<file)"} by skipping
             * the double quotes.  We don't need to know what was

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

* Re: The big kre zsh bug report
  2018-12-20 22:25   ` The big kre zsh bug report Martijn Dekker
  2018-12-21  7:53     ` Bart Schaefer
@ 2018-12-21 11:30     ` Robert Elz
  2018-12-21 20:37       ` Bart Schaefer
  2018-12-22  0:13       ` Robert Elz
  1 sibling, 2 replies; 31+ messages in thread
From: Robert Elz @ 2018-12-21 11:30 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Martijn Dekker, zsh-workers

    Date:        Thu, 20 Dec 2018 23:53:52 -0800
    From:        Bart Schaefer <schaefer@brasslantern.com>
    Message-ID:  <CAH+w=7bthv3E3Lr3UC9FvroXFcS1W+fDRuS6CLPxy_eyX0szqw@mail.gmail.com>


  | > Looks logical to me: in that the ${X+$@} parameter substitution
  | > substitutes $@, within quotes, leaving "$@", which is definitely removed
  | > completely if there are no positional parameters.

  | I'd prefer that this continue to act like bash and ksh than to follow
  | the abstract spec.

This is a case where it can actually affect some real scripts, even
though it is rare.   That's why I changed what the NetBSD sh does.

  | It seems to me that changing this for $=t in zsh native mode might
  | break a lot of things, so I'll leave it open for discussion as to
  | whether it's feasible to change it only for emulation mode.  However,
  | it does differ from the most recent version of bash I have handy.

bash -c 't=" x";     IFS=" x"; set $t; IFS=":"; r="$*"; IFS=; echo $# $r'
1

That isn't even -o posix mode, nor is it the most recent bash available.
(ksh93 does the same, so does mksh/dash/...).

From the version in the prompt string where you illustrated bash
behaviour later, you seem to be testing against a very old bash
(though apparently bash 3 still exists in the wild).   bash has had
a lot of bugs fixed in the interim (and more keep getting fixed).

  | For the lazy or very busy reader:
  |
  | -h  Locate and remember utilities invoked by functions as those
  | functions are defined (the utilities are normally located when the
  | function is executed).

Yes, I know what it means.   I cannot think of a use for it, nor have
I ever seen any script that would ever use it, nor does anything I
know of implement it (though I have not tried ksh88 - ksh93 might
implement some variant, but not what is specified:

ksh93 -c 'X=$PATH; PATH=/no/such/place; set -h; g() { grep "$@";}; PATH=$X;  g fff /tmp/bbb'
grep: /tmp/bbb: No such file or directory

If the path lookups were done (only) during fn definition, then
that should not find grep rather than run it.   If -h is simply some
kind of optimisation, it is worthless (its purpose had to be as some
kind of way of guaranteeing what PATH would be used for
library functions, so they could be standalone, and work in any
environment, which standard sh "dynamic everything" does not
make easy).

[Aside: it is entirely possible -h will be removed from POSIX sometime,
I think a request for that has been lodged already, but that doesn't
mean that other shells will simply delete that current "support" for it,
ie: allowing it to be set/reset and otherwise ignoring it.]


  | > > tc-se:case_matching[147]: Test of 'var='\z'; case ${var} in (${var}) printf M;; (*) printf X;; esac' failed.
  | > >
  | > > The word to match is two chars, backslash and z, the pattern is
  | > > a quoted 'z' (the backslash becomes a quoting character).
  |
  | I don't think this is going to get fixed.  I went looking for this
  | test case but didn't find it:
  |
  | var='"z"'; case ${var} in (${var}) printf M;; (*) printf X;; esac
  |
  | This also prints M.  If backslash-z should become a quoted z,
  | shouldn't the above case also become a quoted z?

No.   It all comes from the use of RE's to define how glob works
(and the ancient implementation) - '\' quotes magic in an RE, other
forms of shell quoting do not.   So, for the string given to the matcher,
a \ is the one and only quote char.   Where it gets really messy is
that to remain consistent with itself, chars that the shell has already
quoted are never interpreted as magic, even when they would be
if (once the sh quoting is no longer there) they would be in an RE
(which is how in a literal pattern it is possible to use sh quoting
to quote the '-' in a [] match, whereas in a RE only putting the - first
or last removes its "range of chars" meaning).

All this flows from the way the original Bourne shell implemented
quoting ( ch |= 0x80 ) and that quote removal doesn't happen until
after glob or parameter expansion (for the ${var%pattern} etc stuff,
and never happens in case matching (not needed, as all that ever
wants is a match/no-match - no-one cares what matched).  Some of
it is hideous, but we are stuck with it...

In native zsh mode if you want to change that to be more like csh,
which did complain about invalid patterns, that's fine, but for emulating
sh it really isn't.

  | So that means in
  | case statements all variable references have to be treated as if they
  | were ${(Q)var} (to use zsh-speke)?  What if the quotes aren't
  | balanced?

I don't speak zsh, so this is hard, but I can guess, but no, I don't think
that is correct, and as quotes are just chars (the same as they are any
other time a variable is expanded), they don't need to be balanced.
\ is only special because it is defined to be that way for matching (and
because something needs to be for uses of glob matching in other
utilities, like find, which don't do anything like sh quoting, but need to
be able to distinguish a literal '*' from "match anything" somehow, and \
is the way it is done there too.)

  | > I'm not sure the zsh authors aim to make emulation modes quite that
  | > exact, but I'll just leave this here for their consideration.
  |
  | There isn't any --emulate bash, really, it's merly a synonym for
  | --emulate sh.

In that case, I would suggest deleting it.   It gives a false impression.
bash has lots of stuff that sh does not have, how close some of that
is to zsh native mode I have no idea.

  | And therefore no, it's not intended to be perfect.

It depends what you're aiming for with --emulate ... if it is just so you
can run native sh scripts, then most of this does not matter.  But an
alternative use is to allow zsh users to check if their scripts will
work when run with some other sh (ie: if they are portable scripts or
not) and for that, while perfection is not required, allowing too many
variations would render the --emulate stuff useless.

  | That's not true, it just doesn't handle redirection to descriptors >9
  | without the use of variant syntax.

OK.  That's better -- but again, in sh/bash mode, it really should
use sh/bash syntax (again, otherwise the emulation isn't very
useful).


  | % case in in (esac|cat
  | case> zsh: parse error near `(esac|cat'
  |
  | So this has apparently been special-cased to be silent when the shell
  | is not interactive.

I have no knowledge of zsh internals - but in many other shells when
this kind of thing happens, it is more the interactive mode that is
special cased - normally when the shell reads EOF it simply exits
(after running any EDIT trap) and the logic to do that is buried deep
in the input routines.   That is why in a lot of shells all kinds of missing
termination is ignored (which doesn't really affect any valid script,
naturally).


And somehow in all of that I managed to just delete the one case that
caused me to start to reply, so here it is again out of order ...

[Sorry about ugly formatting, it is a side effect of the way I got
this text back into this message...]

  | > > tc-se:shell_params[13]: Test of 'set -- a b c d; echo ${4294967297}'
  | failed. > > tc-se:[13] Expected output '', received 'a' > > > > This
  | indicates that 32 bit arith overflow occurred, and wasn't detected. > >
  | Confirmed (also on ksh93 and dash).

  | Checking for overflow here seems like a lot of computational expense for a
  | case that probably only happens in test suites.  Since zsh implements arrays
  | as actual non-sparse C arrays, memory is going to explode long before
  | anything manages to assign that many positional parameters. 

Don't bet on it.   An array with 2^32 unset elements, followed by one set
(assuming it is implemented in a rational way) is just 8 * (2^32 + 1) bytes,
plus noise, which is just 32 GiB (plus change) - my laptop has 32GiB today
- so we are already very very close to average consumer systems being
able to do that, lots of desktop/server type systems can install 128GiB
(or more) which would be plenty to allow this to work - especially in zsh
which apparently allows
	4294967297=hello
which other shells do not...

jinx$ zsh --emulate sh -c '1=hello; echo ${1}'
hello
jinx$ zsh --emulate sh -c '4294967297=hello; echo ${4294967297}'
hello
jinx$ zsh --emulate sh -c '4294967297=hello; echo ${1}'
hello

But even with other shells:
	set -- '' '' '' '' [repeat 2^32 times] hello
is going to be feasible (if not fast) quite soon now.   Similarly the
even slower, but feasible to write:

	set -- ''
	for i in $(seq 1 32)
	do
		set -- "$@" "$@"
	done
	set -- "$@" hello

[aside: not sure if the args to seq are correct there, didn't atually test 
that... there may be an off by 1], and I know these versions need more
space to store all the empty strings .. but that should be less than
another factor of 2.

On the NetBSD lists (because we cannot currently handle it - in the
kernel) there was recent mention of a HP system, available today, with
48TiB of ram.  For a system like that, a few tens of GiB's of memory
per process is in the noise ...  (handling processes that big is why
systems that big are designed, built, and desired).

The overflow test has negligible cost -- strtoxxx() is not really any more
expensive than atoi() and really ought to be used everywhere, it is
future proof against all kinds of bugs that "cannot happen in real life"
today, but will tomorrow.  The few extra nano-secs the test takes is in
the noise when compared with everything else that is happening.

I am not suggesting there is any need to make being able to set that
many args actually work (we certainly don't) just to detect the overflow.

When that happens here, we just treat the positional parameter as unset
and continue, other places (like as the arg to shift) we treat it just the
same as any other time the value is too big (shift count exceeds $# in
that case), and in some other places it simply becomes an error (sh
cannot handle that, so error("Number out of range") or something.)
Anything but silent truncation of the value.

kre


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

* Re: The big kre zsh bug report
  2018-12-21 11:30     ` The big kre zsh bug report Robert Elz
@ 2018-12-21 20:37       ` Bart Schaefer
  2018-12-22  0:13       ` Robert Elz
  1 sibling, 0 replies; 31+ messages in thread
From: Bart Schaefer @ 2018-12-21 20:37 UTC (permalink / raw)
  To: Robert Elz; +Cc: Martijn Dekker, zsh-workers

(For some reason gmail put your reply in spam, I only found it by accident.)

On Fri, Dec 21, 2018 at 3:31 AM Robert Elz <kre@munnari.oz.au> wrote:
>
>   | It seems to me that changing this for $=t in zsh native mode might
>   | break a lot of things, so I'll leave it open for discussion as to
>   | whether it's feasible to change it only for emulation mode.  However,
>   | it does differ from the most recent version of bash I have handy.

By this I meant zsh's current behavior differs from bash, so we ought
to at least consider changing it in emulation.

> From the version in the prompt string where you illustrated bash
> behaviour later, you seem to be testing against a very old bash

It's what's on CentOS 6.10.

> (though apparently bash 3 still exists in the wild).

MacOS 10.13 appears to have bash3, at least based on the prompt.

>   | For the lazy or very busy reader:
>   |
>   | -h  Locate and remember utilities invoked by functions as those
>   | functions are defined (the utilities are normally located when the
>   | function is executed).
>
> Yes, I know what it means.

Obviously you do, but I didn't until it was mentioned here, so I
assume the rest of the zsh-workers audience might not either.

>  I cannot think of a use for it, nor have
> I ever seen any script that would ever use it, nor does anything I
> know of implement it

It doesn't even seem possible to implement sanely, unless perhaps by
freezing $PATH and putting the shell in a virtual chroot jail.

var=grep
$var "$@"

would seem to be enough to thwart it without some really elaborate
"compile time" analysis of what $var was going to yeild.

>   | var='"z"'; case ${var} in (${var}) printf M;; (*) printf X;; esac
>   |
>   | This also prints M.  If backslash-z should become a quoted z,
>   | shouldn't the above case also become a quoted z?
>
> No.   It all comes from the use of RE's to define how glob works
> (and the ancient implementation) - '\' quotes magic in an RE, other
> forms of shell quoting do not.

OK, that's understandable.  Any situation in which given (just for
example) var='[a-z]' we interpret $var as a character class, we ought
to also when given var='\z' treat $var as a literal z.

As mentioned above about $=t for splitting, I'm not sure we can safely
apply this to $~var without changing some expected behavior, so it'll
require careful consideration.

> In native zsh mode if you want to change that to be more like csh,
> which did complain about invalid patterns, that's fine, but for emulating
> sh it really isn't.

None of the discussion of $var interpolation of '\z' in pattern
context has any relationship to the discussion about treatment of bad
patterns.

>   | There isn't any --emulate bash, really, it's merly a synonym for
>   | --emulate sh.
>
> In that case, I would suggest deleting it.   It gives a false impression.
> bash has lots of stuff that sh does not have, how close some of that
> is to zsh native mode I have no idea.
>
>   | And therefore no, it's not intended to be perfect.
>
> It depends what you're aiming for with --emulate ... if it is just so you
> can run native sh scripts, then most of this does not matter.

It's just so you can run native sh scripts.  It's not intended to turn
zsh into a portability test platform.  Really it's so that you can do

ln -s /bin/zsh bash

The --emulation option is just a way to talk zsh into behaving as if
$0 were changed.  --emulate csh is even farther from accurate.

>   | Checking for overflow here seems like a lot of computational expense for a
>   | case that probably only happens in test suites.  Since zsh implements arrays
>   | as actual non-sparse C arrays, memory is going to explode long before
>   | anything manages to assign that many positional parameters.
>
> Don't bet on it.   An array with 2^32 unset elements, followed by one set
> (assuming it is implemented in a rational way) is just 8 * (2^32 + 1) bytes,

I don't recall exactly but it's probably more like double that (2^32
pointers to things representing unset elements, not 2^32 null
pointers).

Nevertheless, point taken.

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

* Re: The big kre zsh bug report
  2018-12-21 11:30     ` The big kre zsh bug report Robert Elz
  2018-12-21 20:37       ` Bart Schaefer
@ 2018-12-22  0:13       ` Robert Elz
  1 sibling, 0 replies; 31+ messages in thread
From: Robert Elz @ 2018-12-22  0:13 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Martijn Dekker, zsh-workers

    Date:        Fri, 21 Dec 2018 12:37:08 -0800
    From:        Bart Schaefer <schaefer@brasslantern.com>
    Message-ID:  <CAH+w=7ajDgcRHg6A+LXSCExq6k3sexx7aeM8U-XErV_QcbbZMg@mail.gmail.com>

  | (For some reason gmail put your reply in spam, I only found it by accident.)

Google (in general) tends to not like munnari, as I don't believe that
ip6.arpa or in-addr.arpa have any remaining relevance, and refuse to
bother populating tje relevant zones (though whoever it is who runs the
v4 network I have access to a piece of, has the in-addr.arpa version
filled in).   If you had an @gmail.com address there's a 50-50 chance the
mail would simply have been bounced.

[-h]
  | > Yes, I know what it means.
  |
  | Obviously you do, but I didn't until it was mentioned here, so I
  | assume the rest of the zsh-workers audience might not either.

There are times I forget that some of these messages are going to a list.,
particularly when it is one I am not on.


  | OK, that's understandable.  Any situation in which given (just for
  | example) var='[a-z]' we interpret $var as a character class, we ought
  | to also when given var='\z' treat $var as a literal z.

Unless it is "$var" in which case the quotes should quote everything
in the value.    This stuff is all just ugly.

  | None of the discussion of $var interpolation of '\z' in pattern
  | context has any relationship to the discussion about treatment of bad
  | patterns.

Agreed, those are two different issues.   Though, once again, there
are no bad patterns in sh, the definition doesn't allow for that possibility.
A '[' only introduces a "one-of-a-set" if there is a closing unquoted ]
(which is not a terminator of one of the internal newly invented i18n objects)
(and not immediately after the [, ignoring any intervening ! (or ^)).
otherwise the '[' is just a '['.

Inside a [ ] when one is found, a [: only introduces a character class
if followed by a legitimate name (as in correct syntax), and :] (if the
name is invalid, or the : is quoted, then that ] would end the []
Even something as seemingly stupid as [b-a] is not invalid.

  | It's just so you can run native sh scripts.

OK, if that is all you need.

  | The --emulation option is just a way to talk zsh into behaving as if
  | $0 were changed.  --emulate csh is even farther from accurate.

I'm not sure why you'd bother with the latter,  while the csh UI was good,
the way it was developed meant its syntax was horrid, why anyone would
ever write anything in csh has always baffled me - a typical csh script tends
to be about twice as long as the same thing written in sh (and that's basic
sh, as it was in 1980, with no functions, arith,  ...)

  | I don't recall exactly but it's probably more like double that (2^32
  | pointers to things representing unset elements,

Yes, I was assuming that a truly unset element (one never mentioned
anywhere at all) would just be a null pointer (what else would that mean?)
- but I knew I could be off by a bit (an array element might be more than
just a pointer to its data).

But I also don't really believe that arrays are needed in sh - they tend
to be wanted by people who want to write sh as if it were C (or whatever
else similar) - rather than its own language type.   Without those and with
the positional params being more akinn to special params than variables,
their implementation gets much simpler than it would be otherwise.  Our
positional prams are an (internal, C) array of pointers to strings.   That's
all that is needed (well, plus an int type to hold $#).

kre


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

* Re: zsh 5.6.2-test-2
       [not found] <d7b0451f90bdfe61f48cc1361690180e07158900.camel@ntlworld.com>
       [not found] ` <b8851c3a50bd8bceba1961f2f764e1a6869481ac.camel@ntlworld.com>
@ 2018-12-24  5:40 ` Axel Beckert
  2018-12-24  7:14   ` Axel Beckert
       [not found] ` <CAKc7PVDUjo8HAdwqgRAKcgQHOzThM+hYnjX+2FKzUZB+pfmC-Q@mail.gmail.com>
  2 siblings, 1 reply; 31+ messages in thread
From: Axel Beckert @ 2018-12-24  5:40 UTC (permalink / raw)
  To: Zsh workers

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

Hi Peter,

On Wed, Dec 19, 2018 at 08:54:12PM +0000, Peter Stephenson wrote:
> I've uploaded a test version of zsh to
> 
> http://www.zsh.org/pub/development/
> 
> Not much particularly likely to be amiss.  However, unless everyone is
> prepared to swear blind within a day or so that it's OK it'll probably
> be the new year before I get a chance to make a release.

I at least got a test suite failure on Debian Unstable x86 32bit
("i386" in Debian slang) while it built fine on x86_64 ("amd64" in
Debian slang).

The relevant build log excerpt as far as I can see:

../../Test/V09datetime.ztst: starting.
Running test: basic format specifiers
Test successful.
Running test: zsh extensions
Test successful.
Running test: alternate format extensions
Test case skipped: Japanese UTF-8 locale not supported
Running test: various extensions
Test successful.
Running test: Embedded nulls
Test successful.
Running test: bad format specifier
Test successful.
Running test: epochtime optional
Test successful.
Running test: optional nanoseconds
Test ../../Test/V09datetime.ztst failed: bad status 1, expected 0 from:
  strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322
  strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 0
  strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 2
  strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 $(( 222 * (10 ** 9) ))
Error output:
(eval):strftime:4: 222000000000: invalid nanosecond value
Was testing: optional nanoseconds
../../Test/V09datetime.ztst: test failed.

This was from a test build inside a Jenkins CI environment. Full build
log at
https://jenkins.grml.org/view/Debian/job/zsh-binaries/architecture=i386/341/consoleText

Will upload it to Debian experimental nevertheless to possibly catch
further issues.

		Kind regards, Axel
-- 
PGP: 2FF9CD59612616B5      /~\  Plain Text Ribbon Campaign, http://arc.pasp.de/
Mail: abe@deuxchevaux.org  \ /  Say No to HTML in E-Mail and Usenet
Mail+Jabber: abe@noone.org  X
https://axel.beckert.ch/   / \  I love long mails: https://email.is-not-s.ms/

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: zsh 5.6.2-test-2
  2018-12-24  5:40 ` zsh 5.6.2-test-2 Axel Beckert
@ 2018-12-24  7:14   ` Axel Beckert
  2018-12-24  7:38     ` dana
  0 siblings, 1 reply; 31+ messages in thread
From: Axel Beckert @ 2018-12-24  7:14 UTC (permalink / raw)
  To: zsh-workers

Hi,

On Mon, Dec 24, 2018 at 06:40:22AM +0100, Axel Beckert wrote:
> I at least got a test suite failure on Debian Unstable x86 32bit
> ("i386" in Debian slang) while it built fine on x86_64 ("amd64" in
> Debian slang).

It seems as if all 32-bit archtectures where a build was done, failed
so far and all 64-bit archtectures where a build was done, succeeded:

https://buildd.debian.org/status/package.php?p=zsh&suite=experimental

And I suspect 5ad76492af8931added1ae9600309d915d1427a5 (43800: Add
nanosecond support to strftime built-in) to be the cause as the
nanosecond test is the one which fails (on i386 at least).

		Kind regards, Axel
-- 
PGP: 2FF9CD59612616B5      /~\  Plain Text Ribbon Campaign, http://arc.pasp.de/
Mail: abe@deuxchevaux.org  \ /  Say No to HTML in E-Mail and Usenet
Mail+Jabber: abe@noone.org  X
https://axel.beckert.ch/   / \  I love long mails: https://email.is-not-s.ms/

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

* Re: zsh 5.6.2-test-2
  2018-12-24  7:14   ` Axel Beckert
@ 2018-12-24  7:38     ` dana
  2018-12-24  9:16       ` [PATCH] ztrftime(): Fix truncation for % dana
  0 siblings, 1 reply; 31+ messages in thread
From: dana @ 2018-12-24  7:38 UTC (permalink / raw)
  To: Axel Beckert; +Cc: zsh-workers

On Mon, Dec 24, 2018 at 06:40:22AM +0100, Axel Beckert wrote:
>And I suspect 5ad76492af8931added1ae9600309d915d1427a5 (43800: Add
>nanosecond support to strftime built-in) to be the cause as the
>nanosecond test is the one which fails (on i386 at least).

Yes, it's my fault, i'm sorry.

The test is wrong — 10 ** 9 is too many nanoseconds. I must not have been
paying attention, and just went with it because the built-in took it anyway.
I think it should probably not do that, to account for clever people like me

dana


diff --git a/Src/Modules/datetime.c b/Src/Modules/datetime.c
index 18c7fb58e..521c15a5b 100644
--- a/Src/Modules/datetime.c
+++ b/Src/Modules/datetime.c
@@ -148,7 +148,7 @@ output_strftime(char *nam, char **argv, Options ops, UNUSED(int func))
 	    } else if (*argv[2] == '\0' || *endptr != '\0') {
 		zwarnnam(nam, "%s: invalid decimal number", argv[2]);
 		return 1;
-	    } else if (ts.tv_nsec < 0) {
+	    } else if (ts.tv_nsec < 0 || ts.tv_nsec > 999999999) {
 		zwarnnam(nam, "%s: invalid nanosecond value", argv[2]);
 		return 1;
 	    }
diff --git a/Test/V09datetime.ztst b/Test/V09datetime.ztst
index 22d560750..da4dd4442 100644
--- a/Test/V09datetime.ztst
+++ b/Test/V09datetime.ztst
@@ -90,7 +90,7 @@
   strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322
   strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 0
   strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 2
-  strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 $(( 222 * (10 ** 9) ))
+  strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 $(( 222 * (10 ** 6) ))
 0:optional nanoseconds
 >2002-02-02 02:02:02.000
 >2002-02-02 02:02:02.000
@@ -103,6 +103,9 @@
   strftime '%Y' 1012615322 '' 2> /dev/null
 1:empty nanoseconds not allowed
 
+  strftime '%N' 1012615322 $(( 222 * (10 ** 9) )) 2> /dev/null
+1:too-large nanoseconds not allowed
+
   strftime '%N' 1012615322 ${(l<64><9>):-} 2> /dev/null
 1:overflowed nanoseconds not allowed
 


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

* [PATCH] ztrftime(): Fix truncation for %.
  2018-12-24  7:38     ` dana
@ 2018-12-24  9:16       ` dana
  2018-12-24 12:45         ` Daniel Shahaf
  2018-12-24 23:30         ` Joey Pabalinas
  0 siblings, 2 replies; 31+ messages in thread
From: dana @ 2018-12-24  9:16 UTC (permalink / raw)
  To: Zsh workers

Not directly related, but in reviewing workers/43932 further i found that the
way ztrftime() handles truncation for %. is problematic:

  % strftime '%s.%9.' $EPOCHSECONDS $(( 999_999_999 ))
  1545638724.999999999
  % strftime '%s.%6.' $EPOCHSECONDS $(( 999_999_000 ))
  1545638984.999999
  % strftime '%s.%6.' $EPOCHSECONDS $(( 999_999_999 ))
  1545638724.100000

I'm pretty sure it's always been like this, it was just hard to see before
because there was no way to control the (at the time) microsecond input from
'user land'.

I'm not very good at maths — is there a reason it shouldn't just be a straight
power-of-ten division like this?

dana


diff --git a/Src/utils.c b/Src/utils.c
index e43a3cdb4..c3badcf77 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3340,9 +3340,8 @@ morefmt:
 		    digs = 9;
 		if (digs < 9) {
 		    int trunc;
-		    for (trunc = 8 - digs; trunc; trunc--)
+		    for (trunc = 9 - digs; trunc; trunc--)
 			nsec /= 10;
-		    nsec = (nsec + 8) / 10;
 		}
 		sprintf(buf, "%0*ld", digs, nsec);
 		buf += digs;
diff --git a/Test/V09datetime.ztst b/Test/V09datetime.ztst
index 2041d9b40..ed2d99b2f 100644
--- a/Test/V09datetime.ztst
+++ b/Test/V09datetime.ztst
@@ -114,3 +114,15 @@
 
   strftime -r '%Y' 2> /dev/null
 1:-r timestring not optional
+
+  for 1 in %. %1. %3. %6. %9. %12.; do
+    print -rn - "$1 "
+    strftime "%Y-%m-%d %H:%M:%S.$1" 1012615322 $(( 999_999_999 ))
+  done
+0:%. truncation
+>%. 2002-02-02 02:02:02.999
+>%1. 2002-02-02 02:02:02.9
+>%3. 2002-02-02 02:02:02.999
+>%6. 2002-02-02 02:02:02.999999
+>%9. 2002-02-02 02:02:02.999999999
+>%12. 2002-02-02 02:02:02.999999999


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

* Re: [PATCH] ztrftime(): Fix truncation for %.
  2018-12-24  9:16       ` [PATCH] ztrftime(): Fix truncation for % dana
@ 2018-12-24 12:45         ` Daniel Shahaf
  2018-12-24 16:24           ` dana
  2018-12-24 23:35           ` Joey Pabalinas
  2018-12-24 23:30         ` Joey Pabalinas
  1 sibling, 2 replies; 31+ messages in thread
From: Daniel Shahaf @ 2018-12-24 12:45 UTC (permalink / raw)
  To: dana, Zsh workers

dana wrote on Mon, 24 Dec 2018 03:16 -0600:
> Not directly related, but in reviewing workers/43932 further i found that the
> way ztrftime() handles truncation for %. is problematic:
> 
>   % strftime '%s.%9.' $EPOCHSECONDS $(( 999_999_999 ))
>   1545638724.999999999
>   % strftime '%s.%6.' $EPOCHSECONDS $(( 999_999_000 ))
>   1545638984.999999
>   % strftime '%s.%6.' $EPOCHSECONDS $(( 999_999_999 ))
>   1545638724.100000

That's a very odd sequence of $EPOCHSECONDS values. :P

Also, in (unpatched) master:

% strftime '[%3.]' 123456789
[000]
% strftime '[%s][%3.]' 0 123456789
[0][124]
% 

Shouldn't the former print [124]?

> I'm not very good at maths — is there a reason it shouldn't just be a straight
> power-of-ten division like this?

Using straight division likes this makes it do truncation; in the code
before this patch, the +8 makes it so nsec=11152 would print '1116'
but nsec=11151 would print '1115'.  (The +8 should probably be +5 ---
half the radix.)  999999999 is an edge case since it rounds up "to the
next second".

> +++ b/Src/utils.c
> @@ -3340,9 +3340,8 @@ morefmt:
>  		    digs = 9;
>  		if (digs < 9) {
>  		    int trunc;
> -		    for (trunc = 8 - digs; trunc; trunc--)
> +		    for (trunc = 9 - digs; trunc; trunc--)
>  			nsec /= 10;
> -		    nsec = (nsec + 8) / 10;
>  		}
>  		sprintf(buf, "%0*ld", digs, nsec);
>  		buf += digs;

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

* Re: [PATCH] ztrftime(): Fix truncation for %.
  2018-12-24 12:45         ` Daniel Shahaf
@ 2018-12-24 16:24           ` dana
  2018-12-24 17:06             ` Daniel Shahaf
  2018-12-24 23:35           ` Joey Pabalinas
  1 sibling, 1 reply; 31+ messages in thread
From: dana @ 2018-12-24 16:24 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh workers

On 24 Dec 2018, at 06:45, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>Also, in (unpatched) master:
>
>% strftime '[%3.]' 123456789
>[000]
>% strftime '[%s][%3.]' 0 123456789
>[0][124]
>% 
>
>Shouldn't the former print [124]?

No, %. only uses the nanoseconds value given to ztrftime(), which is
implicitly 0 in the former case. It's not substituting an arbitrary series of
inputs in the style of printf, it only takes those two time arguments to
ztrftime().

On 24 Dec 2018, at 06:45, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>but nsec=11151 would print '1115'.  (The +8 should probably be +5 ---
>half the radix.)

Oh, wow. That's... extremely obvious in hind sight. Apparently i had changed
the +5 to +8 in the ztrftime() patch that originally added nanosecond support,
i guess mindlessly associating it with the 5 that used to be in the loop.
Embarrassing.

... How about this, then? This also fixes an issue where you can't use %. more
than once in the format string because it overwrites the original value.

dana


diff --git a/Src/utils.c b/Src/utils.c
index e43a3cdb4..70ac7ac8d 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3334,19 +3334,22 @@ morefmt:
 #endif
 	    switch (*fmt++) {
 	    case '.':
-		if (ztrftimebuf(&bufsize, digs))
-		    return -1;
+	    {
 		if (digs > 9)
 		    digs = 9;
+		if (ztrftimebuf(&bufsize, digs))
+		    return -1;
+		long fnsec = nsec;
 		if (digs < 9) {
 		    int trunc;
 		    for (trunc = 8 - digs; trunc; trunc--)
-			nsec /= 10;
-		    nsec = (nsec + 8) / 10;
+			fnsec /= 10;
+		    fnsec = (nsec < 999999500 ? (fnsec + 5) : fnsec) / 10;
 		}
-		sprintf(buf, "%0*ld", digs, nsec);
+		sprintf(buf, "%0*ld", digs, fnsec);
 		buf += digs;
 		break;
+	    }
 	    case '\0':
 		/* Guard against premature end of string */
 		*buf++ = '%';
diff --git a/Test/V09datetime.ztst b/Test/V09datetime.ztst
index 2041d9b40..3fee49e1d 100644
--- a/Test/V09datetime.ztst
+++ b/Test/V09datetime.ztst
@@ -114,3 +114,17 @@
 
   strftime -r '%Y' 2> /dev/null
 1:-r timestring not optional
+
+  strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 $(( 999_999 ))
+  for 1 in %. %1. %3. %6. %9. %12.; do
+    print -rn - "$1 "
+    strftime "%Y-%m-%d %H:%M:%S.$1" 1012615322 $(( 999_999_999 ))
+  done
+0:%. truncation
+>2002-02-02 02:02:02.001
+>%. 2002-02-02 02:02:02.999
+>%1. 2002-02-02 02:02:02.9
+>%3. 2002-02-02 02:02:02.999
+>%6. 2002-02-02 02:02:02.999999
+>%9. 2002-02-02 02:02:02.999999999
+>%12. 2002-02-02 02:02:02.999999999


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

* Re: [PATCH] ztrftime(): Fix truncation for %.
  2018-12-24 16:24           ` dana
@ 2018-12-24 17:06             ` Daniel Shahaf
  2018-12-24 17:31               ` dana
  0 siblings, 1 reply; 31+ messages in thread
From: Daniel Shahaf @ 2018-12-24 17:06 UTC (permalink / raw)
  To: dana; +Cc: Zsh workers

dana wrote on Mon, Dec 24, 2018 at 10:24:16 -0600:
> On 24 Dec 2018, at 06:45, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
> >Shouldn't the former print [124]?
> 
> No, %. only uses the nanoseconds value given to ztrftime(), which is
> implicitly 0 in the former case. It's not substituting an arbitrary series of
> inputs in the style of printf, it only takes those two time arguments to
> ztrftime().

D'oh, thanks.

> +++ b/Src/utils.c
> @@ -3334,19 +3334,22 @@ morefmt:
>  #endif
>  	    switch (*fmt++) {
>  	    case '.':
> +	    {
>  		if (digs > 9)
>  		    digs = 9;
> +		if (ztrftimebuf(&bufsize, digs))
> +		    return -1;
> +		long fnsec = nsec;
>  		if (digs < 9) {
>  		    int trunc;
>  		    for (trunc = 8 - digs; trunc; trunc--)
> +			fnsec /= 10;
> +		    fnsec = (nsec < 999999500 ? (fnsec + 5) : fnsec) / 10;
>  		}

Why the magic number 999999500?  Why not 999999950 or 999995000 or
99950?  And why would it a problem to add 5 when nsec=999999500?

> +		sprintf(buf, "%0*ld", digs, fnsec);
>  		buf += digs;
>  		break;
> +	    }
>  	    case '\0':
>  		/* Guard against premature end of string */
>  		*buf++ = '%';

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

* Re: [PATCH] ztrftime(): Fix truncation for %.
  2018-12-24 17:06             ` Daniel Shahaf
@ 2018-12-24 17:31               ` dana
  2018-12-28 22:16                 ` dana
  0 siblings, 1 reply; 31+ messages in thread
From: dana @ 2018-12-24 17:31 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: Zsh workers

On 24 Dec 2018, at 11:06, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>Why the magic number 999999500?  Why not 999999950 or 999995000 or
>99950?  And why would it a problem to add 5 when nsec=999999500?

I hastily decided that that was the point at which it could be prevented
from 'overflowing', but... that's not how it works. I'm just posting absolute
nonsense now, sorry. Think i'll revisit it after Christmas :/

dana


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

* Re: [PATCH] ztrftime(): Fix truncation for %.
  2018-12-24  9:16       ` [PATCH] ztrftime(): Fix truncation for % dana
  2018-12-24 12:45         ` Daniel Shahaf
@ 2018-12-24 23:30         ` Joey Pabalinas
  1 sibling, 0 replies; 31+ messages in thread
From: Joey Pabalinas @ 2018-12-24 23:30 UTC (permalink / raw)
  To: dana; +Cc: Zsh workers, Joey Pabalinas

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

On Mon, Dec 24, 2018 at 03:16:22AM -0600, dana wrote:
> Not directly related, but in reviewing workers/43932 further i found that the
> way ztrftime() handles truncation for %. is problematic:
> 
>   % strftime '%s.%9.' $EPOCHSECONDS $(( 999_999_999 ))
>   1545638724.999999999
>   % strftime '%s.%6.' $EPOCHSECONDS $(( 999_999_000 ))
>   1545638984.999999
>   % strftime '%s.%6.' $EPOCHSECONDS $(( 999_999_999 ))
>   1545638724.100000
> 
> I'm pretty sure it's always been like this, it was just hard to see before
> because there was no way to control the (at the time) microsecond input from
> 'user land'.
> 
> I'm not very good at maths — is there a reason it shouldn't just be a straight
> power-of-ten division like this?
> 
> dana

The reason is because truncation in C just discards the fractional part
of the result. This is not how it works in maths, so If you do it this
way instead of just straight division by 10, the truncation of a number
like 0.999999995 to 8 digits rounds up correctly to 1, whereas he naive
way would just truncate it to 0.99999999:

> hobbes% print -rf '%.9f\n' - 0.999999995
> 0.999999995
> hobbes% print -rf '%.8f\n' - 0.999999995
> 1.00000000
> hobbes% print -rf '%.9f\n' - 0.999999994
> 0.999999994
> hobbes% print -rf '%.8f\n' - 0.999999994
> 0.99999999

Happy snow day!

> diff --git a/Src/utils.c b/Src/utils.c
> index e43a3cdb4..c3badcf77 100644
> --- a/Src/utils.c
> +++ b/Src/utils.c
> @@ -3340,9 +3340,8 @@ morefmt:
>  		    digs = 9;
>  		if (digs < 9) {
>  		    int trunc;
> -		    for (trunc = 8 - digs; trunc; trunc--)
> +		    for (trunc = 9 - digs; trunc; trunc--)
>  			nsec /= 10;
> -		    nsec = (nsec + 8) / 10;
>  		}
>  		sprintf(buf, "%0*ld", digs, nsec);
>  		buf += digs;
> diff --git a/Test/V09datetime.ztst b/Test/V09datetime.ztst
> index 2041d9b40..ed2d99b2f 100644
> --- a/Test/V09datetime.ztst
> +++ b/Test/V09datetime.ztst
> @@ -114,3 +114,15 @@
>  
>    strftime -r '%Y' 2> /dev/null
>  1:-r timestring not optional
> +
> +  for 1 in %. %1. %3. %6. %9. %12.; do
> +    print -rn - "$1 "
> +    strftime "%Y-%m-%d %H:%M:%S.$1" 1012615322 $(( 999_999_999 ))
> +  done
> +0:%. truncation
> +>%. 2002-02-02 02:02:02.999
> +>%1. 2002-02-02 02:02:02.9
> +>%3. 2002-02-02 02:02:02.999
> +>%6. 2002-02-02 02:02:02.999999
> +>%9. 2002-02-02 02:02:02.999999999
> +>%12. 2002-02-02 02:02:02.999999999
> 

-- 
Cheers,
Joey Pabalinas

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH] ztrftime(): Fix truncation for %.
  2018-12-24 12:45         ` Daniel Shahaf
  2018-12-24 16:24           ` dana
@ 2018-12-24 23:35           ` Joey Pabalinas
  1 sibling, 0 replies; 31+ messages in thread
From: Joey Pabalinas @ 2018-12-24 23:35 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: dana, Zsh workers, Joey Pabalinas

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

On Mon, Dec 24, 2018 at 12:45:45PM +0000, Daniel Shahaf wrote:
> Using straight division likes this makes it do truncation; in the code
> before this patch, the +8 makes it so nsec=11152 would print '1116'
> but nsec=11151 would print '1115'.  (The +8 should probably be +5 ---
> half the radix.)  999999999 is an edge case since it rounds up "to the
> next second".

Looks like Daniel beat me to the punch, eggnog must be slowing me down
today...
-- 
Cheers,
Joey Pabalinas

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* [PATCH] honour NO_UNSET when reading values in arithmetic expansion/commands
  2018-12-21  7:53     ` Bart Schaefer
  2018-12-21  8:11       ` Fix for ${\var} oddity Bart Schaefer
@ 2018-12-25 17:18       ` Martijn Dekker
  2018-12-25 20:44       ` 'wait' exit status and warnings [was: The big kre zsh bug report] Martijn Dekker
  2018-12-31  2:08       ` Line continuation between $ and { " Martijn Dekker
  3 siblings, 0 replies; 31+ messages in thread
From: Martijn Dekker @ 2018-12-25 17:18 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-workers

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

Op 21-12-18 om 07:53 schreef Bart Schaefer:
> On Thu, Dec 20, 2018 at 2:48 PM Martijn Dekker <martijn@inlv.org> wrote:
>>
>> However, I think having 'set -u' apply to $(( x )) is "obvious" and
>> useful behaviour.
> 
> Reasonable.

This should make that happen, if I did it right. All the regression 
tests pass, including three added ones.

With this patch, zsh throws an error but does not exit on an unset 
variable in the ((arithmetic command)) or in 'let'. But it doesn't exit 
on a syntax error either, so that is consistent. It exits as expected on 
an unset variable in $((arithmetic expansion)).

- M.


[-- Attachment #2: arith-nounset.patch --]
[-- Type: text/plain, Size: 2180 bytes --]

diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index 25b3d57..bc182eb 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -753,7 +753,9 @@ pindex(NOUNSET)
 cindex(parameters, substituting unset)
 cindex(unset parameters, substituting)
 item(tt(UNSET) (tt(PLUS()u), ksh: tt(PLUS()u)) <K> <S> <Z>)(
-Treat unset parameters as if they were empty when substituting.
+Treat unset parameters as if they were empty when substituting, and as if
+they were zero when reading their values in arithmetic expansion and
+arithmetic commands.
 Otherwise they are treated as an error.
 )
 pindex(WARN_CREATE_GLOBAL)
diff --git a/README b/README
index aaaee50..0002104 100644
--- a/README
+++ b/README
@@ -42,6 +42,10 @@ array.
 The gen-applied-string hook is unaffected; it still receives the patches in
 reverse order, from last applied to first applied.
 
+2) The option NO_UNSET now also applies when reading values from
+variables without a preceding '$' sign in shell arithmetic expansion
+and in the double-parentheses and 'let' arithmetic commands.
+
 Incompatibilities between 5.5.1 and 5.6.2
 ------------------------------------------
 
diff --git a/Src/math.c b/Src/math.c
index b08e05c..a387700 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -342,6 +342,8 @@ getmathparam(struct mathvalue *mptr)
 	mptr->pval = (Value)zhalloc(sizeof(struct value));
 	if (!getvalue(mptr->pval, &s, 1))
 	{
+	    if (unset(UNSET))
+		zerr("%s: parameter not set", mptr->lval);
 	    mptr->pval = NULL;
 	    if (isset(FORCEFLOAT)) {
 		result.type = MN_FLOAT;
diff --git a/Test/C01arith.ztst b/Test/C01arith.ztst
index f1364ab..9dfc065 100644
--- a/Test/C01arith.ztst
+++ b/Test/C01arith.ztst
@@ -471,3 +471,19 @@
   print $(( -2#101-16#f ))
 0: Unary minus doesn't apply to base but to number as a whole.
 >-20
+
+  ( set -o nounset
+  true $(( noexist + 1 ))
+  echo 'should never get here' )
+1:Arithmetic, NO_UNSET part 1
+?(eval):2: noexist: parameter not set
+
+  ( setopt nounset
+  (( noexist++ )) )
+2:Arithmetic, NO_UNSET part 2
+?(eval):2: noexist: parameter not set
+
+  ( unsetopt unset
+  let noexist==0 )
+1:Arithmetic, NO_UNSET part 3
+?(eval):2: noexist: parameter not set

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

* 'wait' exit status and warnings [was: The big kre zsh bug report]
  2018-12-21  7:53     ` Bart Schaefer
  2018-12-21  8:11       ` Fix for ${\var} oddity Bart Schaefer
  2018-12-25 17:18       ` [PATCH] honour NO_UNSET when reading values in arithmetic expansion/commands Martijn Dekker
@ 2018-12-25 20:44       ` Martijn Dekker
  2018-12-30 18:13         ` Peter Stephenson
  2018-12-31  2:08       ` Line continuation between $ and { " Martijn Dekker
  3 siblings, 1 reply; 31+ messages in thread
From: Martijn Dekker @ 2018-12-25 20:44 UTC (permalink / raw)
  To: Bart Schaefer, Zsh hackers list

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

Op 21-12-18 om 07:53 schreef Bart Schaefer:
> On Thu, Dec 20, 2018 at 2:48 PM Martijn Dekker <martijn@inlv.org> wrote:
>>> tc-so:Executing command [ zsh --emulate sh -c wait 1 ]
>>> tc-se:Fail: incorrect exit status: 1, expected: 127
> 
> Probably easily fixed.

Well, kind of.

I got as far as the attached patch, but it turns out there is another 
bug with 'wait': '(wait %1)' in a subshell quietly returns status 0 even 
if there is no such job. ('(wait %2)' and up are ok.)

I can't figure out how to solve that bug, and perhaps that's for another 
patch anyway, so there is one regression test failure in the attached 
patch (in the second test, where 'wait' is run in a subshell with 
POSIX_BUILTINS set).

I also suppressed the warnings for POSIX_BUILTINS. As Robert Elz already 
suspected, POSIX says: "If one or more pid operands are specified that 
represent unknown process IDs, wait shall treat them as if they were 
known process IDs that exited with exit status 127."[*] (note that 'pid 
operands' include job specs like %1). That means no warnings. (bash 
prints warnings in posix mode too, but, according to my testing, no 
other shell does.)

Thanks,

- M.

[*] http://pubs.opengroup.org/onlinepubs/9699919799/utilities/wait.html

[-- Attachment #2: waitstatus-preliminary.patch --]
[-- Type: text/plain, Size: 4434 bytes --]

diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index fd29ca3..cc98323 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -2362,6 +2362,8 @@ then all currently active child processes are waited for.
 Each var(job) can be either a job specification or the process ID
 of a job in the job table.
 The exit status from this command is that of the job waited for.
+If var(job) represents an unknown job or process ID, a warning is printed
+(unless the tt(POSIX_BUILTINS) option is set) and the exit status is 127.
 
 It is possible to wait for recent processes (specified by process ID,
 not by job) that were running in the background even if the process has
diff --git a/Src/jobs.c b/Src/jobs.c
index ed9f81f..73d7f26 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -1910,7 +1910,7 @@ getjob(const char *s, const char *prog)
     /* "%%", "%+" and "%" all represent the current job */
     if (*s == '%' || *s == '+' || !*s) {
 	if (curjob == -1) {
-	    if (prog)
+	    if (prog && !isset(POSIXBUILTINS))
 		zwarnnam(prog, "no current job");
 	    returnval = -1;
 	    goto done;
@@ -1921,7 +1921,7 @@ getjob(const char *s, const char *prog)
     /* "%-" represents the previous job */
     if (*s == '-') {
 	if (prevjob == -1) {
-	    if (prog)
+	    if (prog && !isset(POSIXBUILTINS))
 		zwarnnam(prog, "no previous job");
 	    returnval = -1;
 	    goto done;
@@ -1944,7 +1944,7 @@ getjob(const char *s, const char *prog)
 	    returnval = jobnum;
 	    goto done;
 	}
-	if (prog)
+	if (prog && !isset(POSIXBUILTINS))
 	    zwarnnam(prog, "%%%s: no such job", s);
 	returnval = -1;
 	goto done;
@@ -1962,7 +1962,7 @@ getjob(const char *s, const char *prog)
 			returnval = jobnum;
 			goto done;
 		    }
-	if (prog)
+	if (prog && !isset(POSIXBUILTINS))
 	    zwarnnam(prog, "job not found: %s", s);
 	returnval = -1;
 	goto done;
@@ -1976,7 +1976,8 @@ getjob(const char *s, const char *prog)
     }
     /* if we get here, it is because none of the above succeeded and went
     to done */
-    zwarnnam(prog, "job not found: %s", s);
+    if (!isset(POSIXBUILTINS))
+	zwarnnam(prog, "job not found: %s", s);
     returnval = -1;
   done:
     return returnval;
@@ -2375,9 +2376,10 @@ bin_fg(char *name, char **argv, Options ops, int func)
 		    }
 		}
 	    } else if ((retval = getbgstatus(pid)) < 0) {
-		zwarnnam(name, "pid %d is not a child of this shell", pid);
+		if (!isset(POSIXBUILTINS))
+		    zwarnnam(name, "pid %d is not a child of this shell", pid);
 		/* presumably lastval2 doesn't tell us a heck of a lot? */
-		retval = 1;
+		retval = 127;
 	    }
 	    thisjob = ocj;
 	    continue;
@@ -2391,15 +2393,16 @@ bin_fg(char *name, char **argv, Options ops, int func)
 	job = (*argv) ? getjob(*argv, name) : firstjob;
 	firstjob = -1;
 	if (job == -1) {
-	    retval = 1;
+	    retval = 127;
 	    break;
 	}
 	jstat = oldjobtab ? oldjobtab[job].stat : jobtab[job].stat;
 	if (!(jstat & STAT_INUSE) ||
 	    (jstat & STAT_NOPRINT)) {
-	    zwarnnam(name, "%s: no such job", *argv);
+	    if (!isset(POSIXBUILTINS))
+		zwarnnam(name, "%s: no such job", *argv);
 	    unqueue_signals();
-	    return 1;
+	    return 127;
 	}
         /* If AUTO_CONTINUE is set (automatically make stopped jobs running
          * on disown), we actually do a bg and then delete the job table entry. */
diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst
index 5d3d460..2df3602 100644
--- a/Test/A05execution.ztst
+++ b/Test/A05execution.ztst
@@ -341,3 +341,54 @@ F:anonymous function, and a descriptor leak when backgrounding a pipeline
 >17
 >19
 
+# Test 'wait' for unknown job/process ID.
+  wait 1
+  echo $?
+  wait %%
+  echo $?
+  wait %+
+  echo $?
+  wait %-
+  echo $?
+  wait %1
+  echo $?
+  wait %foo
+  echo $?
+  wait %\?bar
+127:'wait' exit status and warning for unknown ID
+>127
+>127
+>127
+>127
+>127
+>127
+?(eval):wait:1: pid 1 is not a child of this shell
+?(eval):wait:3: %%: no such job
+?(eval):wait:5: %+: no such job
+?(eval):wait:7: %-: no such job
+?(eval):wait:9: %1: no such job
+?(eval):wait:11: job not found: foo
+?(eval):wait:13: job not found: ?bar
+
+# Test 'wait' for unknown job/process ID (POSIX mode).
+  (setopt POSIX_BUILTINS
+  wait 1
+  echo $?
+  wait %%
+  echo $?
+  wait %+
+  echo $?
+  wait %-
+  echo $?
+  wait %1
+  echo $?
+  wait %foo
+  echo $?
+  wait %\?bar)
+127:'wait' exit status for unknown ID (POSIX mode)
+>127
+>127
+>127
+>127
+>127
+>127

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

* Re: [PATCH] ztrftime(): Fix truncation for %.
  2018-12-24 17:31               ` dana
@ 2018-12-28 22:16                 ` dana
  2018-12-29  9:55                   ` Daniel Shahaf
  0 siblings, 1 reply; 31+ messages in thread
From: dana @ 2018-12-28 22:16 UTC (permalink / raw)
  To: Zsh workers

On 24 Dec 2018, at 11:31, dana <dana@dana.is> wrote:
>Think i'll revisit it after Christmas :/

Maybe this is more reasonable...?

dana


diff --git a/Src/utils.c b/Src/utils.c
index e43a3cdb4..6e70def81 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3334,19 +3334,27 @@ morefmt:
 #endif
 	    switch (*fmt++) {
 	    case '.':
-		if (ztrftimebuf(&bufsize, digs))
-		    return -1;
+	    {
 		if (digs > 9)
 		    digs = 9;
+		if (ztrftimebuf(&bufsize, digs))
+		    return -1;
+		long fnsec = nsec;
 		if (digs < 9) {
-		    int trunc;
+		    int trunc, max = 10;
+		    for (trunc = 1; trunc < digs; trunc++)
+			max *= 10;
+		    max -= 1;
 		    for (trunc = 8 - digs; trunc; trunc--)
-			nsec /= 10;
-		    nsec = (nsec + 8) / 10;
+			fnsec /= 10;
+		    fnsec = (fnsec + 5) / 10;
+		    if (fnsec > max)
+			fnsec = max;
 		}
-		sprintf(buf, "%0*ld", digs, nsec);
+		sprintf(buf, "%0*ld", digs, fnsec);
 		buf += digs;
 		break;
+	    }
 	    case '\0':
 		/* Guard against premature end of string */
 		*buf++ = '%';
diff --git a/Test/V09datetime.ztst b/Test/V09datetime.ztst
index 2041d9b40..3fee49e1d 100644
--- a/Test/V09datetime.ztst
+++ b/Test/V09datetime.ztst
@@ -114,3 +114,17 @@
 
   strftime -r '%Y' 2> /dev/null
 1:-r timestring not optional
+
+  strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 $(( 999_999 ))
+  for 1 in %. %1. %3. %6. %9. %12.; do
+    print -rn - "$1 "
+    strftime "%Y-%m-%d %H:%M:%S.$1" 1012615322 $(( 999_999_999 ))
+  done
+0:%. truncation
+>2002-02-02 02:02:02.001
+>%. 2002-02-02 02:02:02.999
+>%1. 2002-02-02 02:02:02.9
+>%3. 2002-02-02 02:02:02.999
+>%6. 2002-02-02 02:02:02.999999
+>%9. 2002-02-02 02:02:02.999999999
+>%12. 2002-02-02 02:02:02.999999999


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

* Re: [PATCH] ztrftime(): Fix truncation for %.
  2018-12-28 22:16                 ` dana
@ 2018-12-29  9:55                   ` Daniel Shahaf
  2018-12-29 10:27                     ` Daniel Shahaf
  0 siblings, 1 reply; 31+ messages in thread
From: Daniel Shahaf @ 2018-12-29  9:55 UTC (permalink / raw)
  To: Zsh workers

dana wrote on Fri, Dec 28, 2018 at 16:16:03 -0600:
> On 24 Dec 2018, at 11:31, dana <dana@dana.is> wrote:
> >Think i'll revisit it after Christmas :/
> 
> Maybe this is more reasonable...?

It's 0.100 correct.

(Sorry, I meant to say "99%", but I printed that line with unpatched
master ☺)

> +++ b/Src/utils.c
> @@ -3334,19 +3334,27 @@ morefmt:
>  #endif
>  	    switch (*fmt++) {
>  	    case '.':
> -		if (ztrftimebuf(&bufsize, digs))
> -		    return -1;
> +	    {
>  		if (digs > 9)
>  		    digs = 9;
> +		if (ztrftimebuf(&bufsize, digs))
> +		    return -1;
> +		long fnsec = nsec;
>  		if (digs < 9) {
> -		    int trunc;
> +		    int trunc, max = 10;
> +		    for (trunc = 1; trunc < digs; trunc++)
> +			max *= 10;
> +		    max -= 1;

As a matter of idiom, it would be clearer to initialize max to 1 (the
multiplicative identity) and trunc to 0 (so the loop body is run 'digs'
times).

Next, when «digs == 8», max will be multiplied by ten eight times (or
initialized to 10 and multiplied by ten seven times); however,
10⁸ > INT32_MAX, so when 'int' is a 32-bit type (as on x86 in Axel's
original report) max will overflow, wrap around, and not have the
intended value.

Using a 64-bit type (probably zlong) would address this — in that case
don't forget to adjust the sprintf() format string.

>  		    for (trunc = 8 - digs; trunc; trunc--)
> -			nsec /= 10;
> -		    nsec = (nsec + 8) / 10;
> +			fnsec /= 10;
> +		    fnsec = (fnsec + 5) / 10;
> +		    if (fnsec > max)
> +			fnsec = max;

With the int size change, this should be correct; however, since 'fnsec'
and 'max' are initialized separately, they could easily (after a future
code change) end up being out of sync by an order of magnitude.  That
is: it's correct, but perhaps not as robust as it could be.  As an
alternative, you could initialize 'max' to «1000000000ull» and divide it
by 10 in each iteration of the 'nsec' loop.  (There are other ways but
this one seems straightforward and doesn't run into wraparound edge cases.)

>  		}
> -		sprintf(buf, "%0*ld", digs, nsec);
> +		sprintf(buf, "%0*ld", digs, fnsec);
>  		buf += digs;
>  		break;
> +	    }

> +++ b/Test/V09datetime.ztst
> @@ -114,3 +114,17 @@
> +  strftime '%Y-%m-%d %H:%M:%S.%3.' 1012615322 $(( 999_999 ))
> +  for 1 in %. %1. %3. %6. %9. %12.; do
> +    print -rn - "$1 "
> +    strftime "%Y-%m-%d %H:%M:%S.$1" 1012615322 $(( 999_999_999 ))
> +  done
> +0:%. truncation

You mentioned upthread that this fixes a bug related to %. occurring
twice in the format string; add a test for that?

Bottom line, just change the int type and this'll be good to go. ☺

Cheers,

Daniel

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

* Re: [PATCH] ztrftime(): Fix truncation for %.
  2018-12-29  9:55                   ` Daniel Shahaf
@ 2018-12-29 10:27                     ` Daniel Shahaf
  2018-12-29 11:02                       ` dana
  0 siblings, 1 reply; 31+ messages in thread
From: Daniel Shahaf @ 2018-12-29 10:27 UTC (permalink / raw)
  To: zsh-workers

Daniel Shahaf wrote on Sat, 29 Dec 2018 09:55 +0000:
> Next, when «digs == 8», max will be multiplied by ten eight times (or
> initialized to 10 and multiplied by ten seven times); however,
> 10⁸ > INT32_MAX,

That's patently untrue.  Thanks dana for catching that.

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

* Re: [PATCH] ztrftime(): Fix truncation for %.
  2018-12-29 10:27                     ` Daniel Shahaf
@ 2018-12-29 11:02                       ` dana
  2018-12-29 11:08                         ` Daniel Shahaf
  0 siblings, 1 reply; 31+ messages in thread
From: dana @ 2018-12-29 11:02 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: zsh-workers

On 29 Dec 2018, at 04:27, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>That's patently untrue.  Thanks dana for catching that.

I was pretty worried for a minute :|

OK, that aside, i think i did address all of your feedback. Hopefully this is
the final chapter in the saga of me adding a ceiling on a number

dana


diff --git a/Src/utils.c b/Src/utils.c
index e43a3cdb4..42a860b1d 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3334,19 +3334,28 @@ morefmt:
 #endif
 	    switch (*fmt++) {
 	    case '.':
-		if (ztrftimebuf(&bufsize, digs))
-		    return -1;
+	    {
 		if (digs > 9)
 		    digs = 9;
+		if (ztrftimebuf(&bufsize, digs))
+		    return -1;
+		long fnsec = nsec;
 		if (digs < 9) {
 		    int trunc;
-		    for (trunc = 8 - digs; trunc; trunc--)
-			nsec /= 10;
-		    nsec = (nsec + 8) / 10;
+		    long max = 100000000;
+		    for (trunc = 8 - digs; trunc; trunc--) {
+			max /= 10;
+			fnsec /= 10;
+		    }
+		    max -= 1;
+		    fnsec = (fnsec + 5) / 10;
+		    if (fnsec > max)
+			fnsec = max;
 		}
-		sprintf(buf, "%0*ld", digs, nsec);
+		sprintf(buf, "%0*ld", digs, fnsec);
 		buf += digs;
 		break;
+	    }
 	    case '\0':
 		/* Guard against premature end of string */
 		*buf++ = '%';
diff --git a/Test/V09datetime.ztst b/Test/V09datetime.ztst
index 2041d9b40..9f67ecec3 100644
--- a/Test/V09datetime.ztst
+++ b/Test/V09datetime.ztst
@@ -114,3 +114,19 @@
 
   strftime -r '%Y' 2> /dev/null
 1:-r timestring not optional
+
+  # This tests rounding up and the use of repeated %.s
+  strftime '%Y-%m-%d %H:%M:%S.%3..%3.' 1012615322 $(( 999_999 ))
+  # These test the ceiling on rounding up
+  for 1 in %. %1. %3. %6. %9. %12.; do
+    print -rn - "$1 "
+    strftime "%Y-%m-%d %H:%M:%S.$1" 1012615322 $(( 999_999_999 ))
+  done
+0:%. truncation
+>2002-02-02 02:02:02.001.001
+>%. 2002-02-02 02:02:02.999
+>%1. 2002-02-02 02:02:02.9
+>%3. 2002-02-02 02:02:02.999
+>%6. 2002-02-02 02:02:02.999999
+>%9. 2002-02-02 02:02:02.999999999
+>%12. 2002-02-02 02:02:02.999999999


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

* Re: [PATCH] ztrftime(): Fix truncation for %.
  2018-12-29 11:02                       ` dana
@ 2018-12-29 11:08                         ` Daniel Shahaf
  2018-12-29 11:30                           ` dana
  0 siblings, 1 reply; 31+ messages in thread
From: Daniel Shahaf @ 2018-12-29 11:08 UTC (permalink / raw)
  To: dana; +Cc: zsh-workers

dana wrote on Sat, 29 Dec 2018 05:02 -0600:
> +++ b/Src/utils.c
> @@ -3334,19 +3334,28 @@ morefmt:
>  #endif
>  	    switch (*fmt++) {
>  	    case '.':
> -		if (ztrftimebuf(&bufsize, digs))
> -		    return -1;
> +	    {
>  		if (digs > 9)
>  		    digs = 9;
> +		if (ztrftimebuf(&bufsize, digs))
> +		    return -1;
> +		long fnsec = nsec;

C89 does not allow defining variables in the middle of a block, so
you'll need to move the definition of 'fnsec' to immediately after the
opening braces.

With that changed, +1.

Cheers,

Daniel

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

* Re: [PATCH] ztrftime(): Fix truncation for %.
  2018-12-29 11:08                         ` Daniel Shahaf
@ 2018-12-29 11:30                           ` dana
  2018-12-29 11:34                             ` Daniel Shahaf
  0 siblings, 1 reply; 31+ messages in thread
From: dana @ 2018-12-29 11:30 UTC (permalink / raw)
  To: Daniel Shahaf; +Cc: zsh-workers

On 29 Dec 2018, at 05:08, Daniel Shahaf <d.s@daniel.shahaf.name> wrote:
>With that changed, +1.

(It was not the final chapter)

Fixed and committed. I'll try to figure out why i'm not getting C89 compiler
warnings later. Thanks for looking at it

dana


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

* Re: [PATCH] ztrftime(): Fix truncation for %.
  2018-12-29 11:30                           ` dana
@ 2018-12-29 11:34                             ` Daniel Shahaf
  0 siblings, 0 replies; 31+ messages in thread
From: Daniel Shahaf @ 2018-12-29 11:34 UTC (permalink / raw)
  To: zsh-workers

dana wrote on Sat, 29 Dec 2018 05:30 -0600:
> Fixed and committed. I'll try to figure out why i'm not getting C89 compiler
> warnings later. Thanks for looking at it

Thanks for the patch!

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

* Re: 'wait' exit status and warnings [was: The big kre zsh bug report]
  2018-12-25 20:44       ` 'wait' exit status and warnings [was: The big kre zsh bug report] Martijn Dekker
@ 2018-12-30 18:13         ` Peter Stephenson
  2019-01-21 22:53           ` Martijn Dekker
  0 siblings, 1 reply; 31+ messages in thread
From: Peter Stephenson @ 2018-12-30 18:13 UTC (permalink / raw)
  To: Zsh hackers list

On Tue, 2018-12-25 at 20:44 +0000, Martijn Dekker wrote:
> Op 21-12-18 om 07:53 schreef Bart Schaefer:
> > On Thu, Dec 20, 2018 at 2:48 PM Martijn Dekker <martijn@inlv.org> wrote:
> > > > tc-so:Executing command [ zsh --emulate sh -c wait 1 ]
> > > > tc-se:Fail: incorrect exit status: 1, expected: 127
> > 
> > Probably easily fixed.
> 
> Well, kind of.
> 
> I got as far as the attached patch, but it turns out there is another 
> bug with 'wait': '(wait %1)' in a subshell quietly returns status 0 even 
> if there is no such job. ('(wait %2)' and up are ok.)

Thanks --- for now I've committed this with the test doctored and a note
in the test file.

pws


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

* Line continuation between $ and { [was: The big kre zsh bug report]
  2018-12-21  7:53     ` Bart Schaefer
                         ` (2 preceding siblings ...)
  2018-12-25 20:44       ` 'wait' exit status and warnings [was: The big kre zsh bug report] Martijn Dekker
@ 2018-12-31  2:08       ` Martijn Dekker
  3 siblings, 0 replies; 31+ messages in thread
From: Martijn Dekker @ 2018-12-31  2:08 UTC (permalink / raw)
  To: Bart Schaefer, Zsh hackers list

Op 21-12-18 om 08:53 schreef Bart Schaefer:
> On Thu, Dec 20, 2018 at 2:48 PM Martijn Dekker <martijn@inlv.org> wrote:
>> Robert Elz wrote:
>>> [...] my guess is
>>> that the ${ with a \newline between the $ and { is not working as it should.
>> Confirmed. A bit more experimenting shows that it breaks between '$' and
>> '{' and nowhere else. Very unlikely for line continuation to be used
>> there in real-life scripts, but still a bug.
> Not going to argue with that one.  I suspect it's because the parser
> is treating "{" as beginning a brace expansion (e.g., {a,b,c}) at that
> point and so encodes it differently.

Sure enough, when turning on brace expansion:

$ zsh --emulate sh -o braceexpand -c 'foo=bar; echo $\
{foo}'
bar

it works correctly all of a sudden.

- M.

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

* Re: zsh 4.6.2-test-2
       [not found]     ` <06228a6975b91f7066d0046bf912dd69fa5993a2.camel@ntlworld.com>
@ 2018-12-31 13:44       ` dana
  2018-12-31 15:19         ` Sebastian Gniazdowski
  0 siblings, 1 reply; 31+ messages in thread
From: dana @ 2018-12-31 13:44 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: Zsh workers, Sebastian Gniazdowski

(I guess this should go to workers)

On 30 Dec 2018, at 12:20, Peter Stephenson <p.w.stephenson@ntlworld.com> wrote:
>I've certainly no objection to working round termcap, so I've committed
>this and the tests, but I probably wouldn't be sensitive to problems
>here, so I'm relying on others to let me know.

The new test fails on my machine (macOS, standard build settings AFAIK):

  --- /tmp/zsh.ztst.83116/ztst.out	2018-12-31 07:14:52.000000000 -0600
  +++ /tmp/zsh.ztst.83116/ztst.tout	2018-12-31 07:14:52.000000000 -0600
  @@ -1 +1,2 @@
  -0m27m24mtr7mu27me word2 word3
  +zsh: failed to load module `zsh/zle': dlopen(/usr/local/lib/zsh/5.6.2-test-2/zsh/zle.so, 9): image not found
  +builtin.c:266: Missing builtin detected too latezsh: failed to load module `zsh/zle'...

I assume it's because the zsh instance it's bringing up isn't managed by the
test harness, so it doesn't know how to find stuff in the repo.

This fixes it for me, but i'm not sure if it's the right thing...?

dana


diff --git a/Test/X04zlehighlight.ztst b/Test/X04zlehighlight.ztst
index 23ad14bd6..9f00b4697 100644
--- a/Test/X04zlehighlight.ztst
+++ b/Test/X04zlehighlight.ztst
@@ -12,6 +12,7 @@
       export PS1= PS2=
       zpty -d
       zpty zsh "${(q)ZTST_testdir}/../Src/zsh -fiV +Z"
+      zpty -w zsh "module_path=( ${(@q-)module_path} \$module_path )"
       zpty -w zsh 'zle_highlight=( fg_start_code:"CDE|3" fg_end_code:"|" bg_start_code:"BCDE|4" bg_end_code:"|" )'
     }
     zpty_input() {


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

* Re: zsh 4.6.2-test-2
  2018-12-31 13:44       ` zsh 4.6.2-test-2 dana
@ 2018-12-31 15:19         ` Sebastian Gniazdowski
  0 siblings, 0 replies; 31+ messages in thread
From: Sebastian Gniazdowski @ 2018-12-31 15:19 UTC (permalink / raw)
  To: dana; +Cc: Peter Stephenson, Zsh workers

On Mon, 31 Dec 2018 at 14:41, dana <dana@dana.is> wrote:
>
> (I guess this should go to workers)
>
> This fixes it for me, but i'm not sure if it's the right thing...?
>
> dana

I confirm that there's such problem. I was using standard
module-utilizing test support of the Test sub-directory, and I've
missed that the zpty's Zsh needs to know about custom module_path. The
fix is good IMO.

>
> diff --git a/Test/X04zlehighlight.ztst b/Test/X04zlehighlight.ztst
> index 23ad14bd6..9f00b4697 100644
> --- a/Test/X04zlehighlight.ztst
> +++ b/Test/X04zlehighlight.ztst
> @@ -12,6 +12,7 @@
>        export PS1= PS2=
>        zpty -d
>        zpty zsh "${(q)ZTST_testdir}/../Src/zsh -fiV +Z"
> +      zpty -w zsh "module_path=( ${(@q-)module_path} \$module_path )"
>        zpty -w zsh 'zle_highlight=( fg_start_code:"CDE|3" fg_end_code:"|" bg_start_code:"BCDE|4" bg_end_code:"|" )'
>      }
>      zpty_input() {
>


-- 
Sebastian Gniazdowski
News: https://twitter.com/ZdharmaI
IRC: https://kiwiirc.com/client/chat.freenode.net:+6697/#zplugin
Blog: http://zdharma.org

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

* Re: 'wait' exit status and warnings [was: The big kre zsh bug report]
  2018-12-30 18:13         ` Peter Stephenson
@ 2019-01-21 22:53           ` Martijn Dekker
  0 siblings, 0 replies; 31+ messages in thread
From: Martijn Dekker @ 2019-01-21 22:53 UTC (permalink / raw)
  To: zsh-workers

Op 30-12-18 om 18:13 schreef Peter Stephenson:
> On Tue, 2018-12-25 at 20:44 +0000, Martijn Dekker wrote:
>> Op 21-12-18 om 07:53 schreef Bart Schaefer:
>>> On Thu, Dec 20, 2018 at 2:48 PM Martijn Dekker <martijn@inlv.org> wrote:
>>>>> tc-so:Executing command [ zsh --emulate sh -c wait 1 ]
>>>>> tc-se:Fail: incorrect exit status: 1, expected: 127
>>>
>>> Probably easily fixed.
>>
>> Well, kind of.
>>
>> I got as far as the attached patch, but it turns out there is another 
>> bug with 'wait': '(wait %1)' in a subshell quietly returns status 0 even 
>> if there is no such job. ('(wait %2)' and up are ok.)
> 
> Thanks --- for now I've committed this with the test doctored and a note
> in the test file.

I think my patch is wrong -- now 'fc' in POSIX mode doesn't give
warnings either, though it should. They should only be suppressed for
'wait'.

- M.

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

end of thread, other threads:[~2019-01-21 23:05 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <d7b0451f90bdfe61f48cc1361690180e07158900.camel@ntlworld.com>
     [not found] ` <b8851c3a50bd8bceba1961f2f764e1a6869481ac.camel@ntlworld.com>
2018-12-20 22:25   ` The big kre zsh bug report Martijn Dekker
2018-12-21  7:53     ` Bart Schaefer
2018-12-21  8:11       ` Fix for ${\var} oddity Bart Schaefer
2018-12-25 17:18       ` [PATCH] honour NO_UNSET when reading values in arithmetic expansion/commands Martijn Dekker
2018-12-25 20:44       ` 'wait' exit status and warnings [was: The big kre zsh bug report] Martijn Dekker
2018-12-30 18:13         ` Peter Stephenson
2019-01-21 22:53           ` Martijn Dekker
2018-12-31  2:08       ` Line continuation between $ and { " Martijn Dekker
2018-12-21 11:30     ` The big kre zsh bug report Robert Elz
2018-12-21 20:37       ` Bart Schaefer
2018-12-22  0:13       ` Robert Elz
2018-12-21  2:28   ` Robert Elz
2018-12-24  5:40 ` zsh 5.6.2-test-2 Axel Beckert
2018-12-24  7:14   ` Axel Beckert
2018-12-24  7:38     ` dana
2018-12-24  9:16       ` [PATCH] ztrftime(): Fix truncation for % dana
2018-12-24 12:45         ` Daniel Shahaf
2018-12-24 16:24           ` dana
2018-12-24 17:06             ` Daniel Shahaf
2018-12-24 17:31               ` dana
2018-12-28 22:16                 ` dana
2018-12-29  9:55                   ` Daniel Shahaf
2018-12-29 10:27                     ` Daniel Shahaf
2018-12-29 11:02                       ` dana
2018-12-29 11:08                         ` Daniel Shahaf
2018-12-29 11:30                           ` dana
2018-12-29 11:34                             ` Daniel Shahaf
2018-12-24 23:35           ` Joey Pabalinas
2018-12-24 23:30         ` Joey Pabalinas
     [not found] ` <CAKc7PVDUjo8HAdwqgRAKcgQHOzThM+hYnjX+2FKzUZB+pfmC-Q@mail.gmail.com>
     [not found]   ` <CAKc7PVB-agFUarJ=LqC2QNDFta1O5D_o4v-gt7LiobVDohNGVQ@mail.gmail.com>
     [not found]     ` <06228a6975b91f7066d0046bf912dd69fa5993a2.camel@ntlworld.com>
2018-12-31 13:44       ` zsh 4.6.2-test-2 dana
2018-12-31 15:19         ` Sebastian Gniazdowski

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