1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

[[ ... ]]: fix '!' to negate another '!'

Bug: [[ ! ! 1 -eq 1 ]] returns false, but should return true.

This bug was reported for bash, but ksh has it too:
https://lists.gnu.org/archive/html/bug-bash/2021-06/msg00006.html

Op 24-05-21 om 17:47 schreef Chet Ramey:
> On 5/22/21 2:45 PM, Vincent Menegaux wrote:
>> Previously, these commands:
>>
>>    [[ ! 1 -eq 1 ]]; echo $?
>>    [[ ! ! 1 -eq 1 ]]; echo $?
>>
>> would both result in `1', since parsing `!' set CMD_INVERT_RETURN
>> instead of toggling it.
>
> Interestingly, ksh93 produces the same result as bash. I agree
> that it's more intuitive to toggle it.

Also interesting is that '!' as an argument to the simple
'test'/'[' command does work as expected (on both bash and ksh93):
'test ! ! 1 -eq 1' and '[ ! ! 1 -eq 1 ]' return 0/true.

Even the man page for [[ is identical for bash and ksh93:

|               ! expression
|                      True if expression is false.

This suggests it's supposed to be a logical negation operator, i.e.
'!' is implicitly documented to negate another '!'. Bolsky & Korn's
1995 ksh book, p. 167, is slightly more explicit about it:
"! test-expression. Logical negation of test-expression."

I also note that multiple '!' negators in '[[' work as expected on
mksh, yash and zsh.

src/cmd/ksh93/sh/parse.c: test_primary():
- Fix bitwise logic for '!': xor the TNEGATE bit into tretyp
  instead of or'ing it, which has the effect of toggling it.
This commit is contained in:
Martijn Dekker 2021-06-03 15:47:25 +02:00
parent eca92ea48c
commit d25dbcc1ef
5 changed files with 24 additions and 2 deletions

6
NEWS
View file

@ -3,6 +3,12 @@ For full details, see the git log at: https://github.com/ksh93/ksh
Any uppercase BUG_* names are modernish shell bug IDs.
2021-06-03:
- Fixed a bug in the [[ compound command: the '!' logical negation operator
now correctly negates another '!', e.g., [[ ! ! 1 -eq 1 ]] now returns
0/true. Note that this has always been the case for 'test'/'['.
2021-05-18:
- Fixed SHLVL so that replacing ksh by itself (exec ksh) will not increase it.

View file

@ -147,6 +147,10 @@ For more details, see the NEWS file and for complete details, see the git log.
zero instead of negative infinity. Previously, int() was an alias to
floor(), but now it behaves like trunc().
27. The '!' logical negation operator in the '[[' compound command now
correctly negates another '!', e.g., [[ ! ! 1 -eq 1 ]] now returns
0/true. Note that this has always been the case for 'test'/'['.
____________________________________________________________________________
KSH-93 VS. KSH-88

View file

@ -21,7 +21,7 @@
#define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */
#define SH_RELEASE_SVER "1.0.0-beta.2" /* semantic version number: https://semver.org */
#define SH_RELEASE_DATE "2021-05-18" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_DATE "2021-06-03" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_CPYR "(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK
/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */

View file

@ -1916,7 +1916,7 @@ static Shnode_t *test_primary(Lex_t *lexp)
case '!':
if(!(t = test_primary(lexp)))
sh_syntax(lexp);
t->tre.tretyp |= TNEGATE;
t->tre.tretyp ^= TNEGATE; /* xor it, so that a '!' negates another '!' */
return(t);
case TESTUNOP:
if(sh_lex(lexp))

View file

@ -411,5 +411,17 @@ unset foo
foo=10
([[ foo -eq 10 ]]) || err_exit 'foo -eq 10 fails in [[ ... ]] with foo=10'
# ======
# The negator should negate the negator
# This bug was shared with bash:
# https://lists.gnu.org/archive/html/bug-bash/2021-06/msg00006.html
[[ ! ! -n x ]] && ! [[ ! ! ! -n x ]] && [[ ! ! ! ! -n x ]] && ! [[ ! ! ! ! ! -n x ]] \
&& [[ ! ! -n x && ! ! ! ! -n x && ! ! ! ! ! ! -n x ]] \
|| err_exit '! does not negate ! in [[ ... ]]'
# The bug did not exist in 'test'/'[', but check for it anyway
[ ! ! -n x ] && ! [ ! ! ! -n x ] && [ ! ! ! ! -n x ] && ! [ ! ! ! ! ! -n x ] \
&& [ ! ! -n x -a ! ! ! ! -n x -a ! ! ! ! ! ! -n x ] \
|| err_exit '! does not negate ! in [ ... ]'
# ======
exit $((Errors<125?Errors:125))