command negation in modern hush parser

Rasmus Villemoes ravi at prevas.dk
Wed Mar 11 13:01:19 CET 2026


Hi

Today, I was bitten by u-boot shell not supporting the negating
operator, as in

  if ! some_command args ... ; then ... ; fi

So at first I thought about implementing a simple '!' command which,
similar to the the 'time' command, would just run the rest of the
arguments, but then negate the return code.

But then I looked at the modern hush parser code, which did seem to have
support for that in the shell itself. At least the "! command ..." gets
parsed, and there is code for rejecting "! ! command" which does seem to
be active, but unfortunately, the "! command" form doesn't actually work
as expected:

=> cli set modern

=> ! false
=> echo $?
1
=> ! true
=> echo $?
0
=> if ! false ; then echo "This should be printed" ; fi
=> if ! true ; then echo "This should _not_ be printed" ; fi
This should _not_ be printed
=> if ! echo "echoing always succeeds, so... " ; then echo "this should _not_ be printed" ; fi
echoing always succeeds, so... 
this should _not_ be printed
=> version
U-Boot 2026.04-rc3-00079-gb008b86fd180-dirty (Mar 11 2026 - 12:44:08 +0100)

gcc (GCC) 15.2.1 20260209
GNU ld (GNU Binutils) 2.46

I don't really grok the whole parser code, but just injecting a simple
printf at the start of done_pipe, it seems that that gets called twice
for each command, and the flag indicating inversion gets reset on the
first call, after which it doesn't affect the actual return code of the
command:

=> ! echo hi
done_pipe entered, followup 0, ctx->inverted = 1
done_pipe entered, followup 0, ctx->inverted = 0
hi

Any ideas?

Rasmus


More information about the U-Boot mailing list