[Toybox] test flakiness sitrep

Rob Landley rob at landley.net
Thu Aug 15 03:36:11 PDT 2019



On 8/14/19 11:58 PM, enh wrote:
> On Mon, Aug 12, 2019 at 8:52 PM Rob Landley <rob at landley.net> wrote:
>>
>> On 8/12/19 3:33 PM, enh via Toybox wrote:
>>> last week i turned on the toybox tests in presubmit for changes to
>>> toybox in AOSP, and postsubmit otherwise. so we have a fair bit of
>>> data now (sadly no statistics because non-gtest tests aren't that well
>>> integrated yet).
>>
>> Yay! Thanks for improving the test suite.
>>
>>> bad news:
>>> * i can't merge my own find(1) fix because the test i added is so
>>> flaky i can't get it in. (but really, that's a feature, and should
>>> count as good news.)
>>
>> Which find fix?
> 
> the dangling symlinks one. you already merged the test fix, but i just
> sent you another fix now i've run it on Android, not just my laptop
> :-/

I just looked and replied to that. See my concerns about internationalization in
libc...

>>> good news:
>>> * very little flakiness so far. i've only seen a couple of tests (one
>>> cpio, one tar) failing, and both make me suspicious that there's still
>>> some bad behavior in dd somewhere.
>>
>> It's in pending for a reason. :)
> 
> yeah, i learned my lesson though --- nothing in pending is used for
> the build :-)

I need to clean up dd. I'm reaching the end of my 6 months off (probably flying
straight from ELC to a job site for work) and the big things I got done were tar
(still need to add xattr support) and about the first 1/3 of toysh. (Trying to
make toysh at least usable before the talk on the 22nd, but it doesn't expand
environment variables yet, and for the past ~3 days I went down the rathole of
rewriting the parsing logic to handle (()) because for ((;;)) is a syntax I
while filling out the flow control logic. I hadn't noticed busybox ash doesn't
support it before now...)

Working as fast as I can. Hobby time is finite. :(

(Did you know busybox hush is 11000 lines and busybox ash is 14000? I thought
they were smaller. Hadn't looked at either in years, did a wc on both yesterday
filling out my talk outline, and was surprised. I'm still trying to keep toysh
under 3000 lines, but we'll see...)

>> BUT cursor up and hit enter, and you get infinite hello.

Don't get me started on bash's command history not producing the command you
typed in. I wrote this in yesterday's blog entry:

  Dear bash: if I end a line with a #comment but there's a continuation, and I
  then cursor up in the history? Don't glue the later lines after the #comment
  so they get eaten.

    $ burble() #comment
    > { hello;};burble
    hello
    $ burble() #command { hello;};burble

  The two are not equivalent. (You can do multiline history! Really!)

(I've now got blog entries edited and posted up through the end of March! Given
that "catch up on my blog" was my lowest tier patreon goal and it got met a
while ago, I feel _really_ guilty about that. Working on it, but also making
sure to regularly-ish write _new_ blog entries with enough detail I can turn
them into something coherent later, so it's a moving target...)

>> Oh, and ;; is a special token but AGAIN, in this special case:
>>
>>   $ for((;;));do echo hello;done
>>
>> It turns into two separate ; (presumably retroactively again).

OR you could rewrite the parsing logic to treat (( like $( as a form of quoting
context, and thus the whole thing is one big token so the ; and < recognizing
logic doesn't trigger because it's not a seperate token but instead in the
middle of a larger word (which then gets broken down by math recognition logic
and variable expansion logic, respectively).

I have to add a hack to run_function() to recognize a command starting with ((
and ending with )) but that's fine. (I need to add _another_ one to the
for/select control flow logic anyway, because for ((;;)) has two semicolons in
it and standalone ((math)) doesn't understand semicolons. The "parse this math
expression string and give me back the value" function is the same, but each has
to call it separately after parsing, )

Except in MY run_function() I'm putting the ((math) recognizer _after_ the local
variable assignment logic, and bash put it before:

  $ X=4 ((X<5)) && echo true
  bash: syntax error near unexpected token `('

It works if you put a semicolon after the 4 but there's no obvious reason you'd
NEED to. :P (And WHY does bash use backquote and quote? Why is it trying to do
Microsoft Smart Quotes in ASCII? Seriously, can someone convince the gnu/dammit
guys to just stop please?)

Oh, and any variable that's waiting for a closed parentheses as its end quote
has to count quote depth:

  $ echo $( ( )
  >

It's a line continuation. But:

  $ echo $( "(" )
  bash: (: command not found

isn't. So I spent a large chunk of yesterday teaching parse_word() how to handle
all that, which is only TANGENTIALLY related to implementing for/select. (Which
has its own fun. Did you know "for name do echo hello; done" only needs one
semicolon? for name in; do echo hello; done" needs a semicolon. The for/select
syntax is actually:

  for {((;;))|name [in...]} do

So you can have:

  $ for ((i=0;i<1;i++)) do echo $i;done
  0

(You can have a semicolon or newline before/after the do, but not after the for.
The one before done is required.) Or you can have:

  $ boingy() { for i do echo $i; done }; boingy uno dos desqview
  uno
  dos
  desqview

because a for with a variable name but no in list

Or you can have an in list, which can be on the next line after the for. (The
variable name can't be: you either have a ((;;) block with exactly two
semicolons or you have a variable name which can't have an = in it...

Ok, there's a whole "what constitutes a valid shell variable" thing I'm unhappy
about. Did I already rant here about bash filtering out variable names it
doesn't like at startup? Or was that just in my blog you haven't seen yet
because the web's still months behind? Bash only allows a-zA-z0-9 and _ and the
first letter can't be a digit, but you can set _way_ more variables than that
with env, up to and including a zero length variable name. (env =hello env |
grep hello). And bash just drops 'em. That's insane, it means you can't have
utf8 variable names! It's based on a misreading (I.E. conservative reading) of
posix and I'm not putting up with it. BUT I can't have a variable called ((;;))
accepted by for as an assignment target either, can I?

Oh, and this:

  ((1+2)) > frog

works for some reason. It seems to be the same post-block redirection context as

  if true; then for i in 1 2 3; do echo $i; done > frog; fi < walrus

Except I'm unaware of any circumstances under which it can produce or consume
output? Oh well, at least I can work out where to stick it...

P.S. At some point I need to go reread the posix spec on what THEY think the
shell is supposed to do, but honestly it would just be a distraction right now.
I intend to implement what bash DOES based on reading the bash man page and help
output, and then sticking bash in the comfy chair and poking it with the soft
cushions until it confesses and writing down Too Many Tests (see attached, not
REMOTELY done and I need to turn them all into machine runnable tests)...

And then maybe compare it with what posix says _afterwards_, but they're behind
the curve here. I blame Jorg Schilling.

>> I am adding tests to the giant test file and grimly implementing. Alas since the
>> syntax checking pass and the running pass are different (I'm sharing as much
>> code as I can between them but they fundamentally do different things), I have a
>> lot more syntax parsing than executing yet. :)
> 
> i don't know how you have the stomach for the shell... just thinking

Never underestimate the motivational power of spite:
https://www.youtube.com/watch?v=2t-hyB8ibgk

(Hmmm, maybe I should cover that in my talk on the 22nd?)

> about it makes me miss
> [rc](http://doc.cat-v.org/plan_9/4th_edition/papers/rc) which -- like
> so much of Plan 9 -- sadly wasn't better _enough_ to make a
> difference. utf8 being the obvious exception.

And /proc, and kvm's virtfs is the 9p.linux protocol under the covers, and bash
implements /dev/{tcp,udp}/address/port as a redirection target...

Plan 9 was great, the problem is it was proprietary. They charged money for the
binaries for pretty much its entire development history, and you couldn't even
BUY source until 1992 (when the cheapest academic price was $350). They didn't
open the source until 2002 (and then under the "lucent license" which couldn't
share code with anything else), by which point that ship had sailed.

It doesn't matter what your OS does: staying closed source binary only a decade
after Linux came out was not interesting. IBM couldn't make that work with OS/2.
And by the time Plan 9 DID open its source it was old news. It had been going
for 20 years and people said if it was going to make a splash it would have done
so before now, so they didn't look at it _then_. First it was closed source,
then it was old. Being payware prevented anybody from having a copy, and if
nobody has it and nobody can see there's nobody to tell anybody _else_ about it
and its community couldn't grow... and then the lack of community was taken as
evidence it was uninteresting. :(

Plan 9 failed for the same reason Unix succeeded. Unix was open source because
it couldn't NOT be: copyright wasn't extended to cover binaries until 1983, and
Ken Thompson took a year off from Bell Labs to teach at his alma mater (the
university of california at Berkeley) in 1975, including two semesters of a
class on "this OS I wrote", spawning BSD maintained by the students he taught.

> i had a look at escape characters at the weekend, thinking i'd clean
> up some of the duplication, mainly so i could remove the
> even-more-duplication in my hexedit patch that's the reason you
> haven't seen that yet.

I keep meaning to sit down and add a hd command, but I'm not sure where to put
it. (In hexedit? In od? I could make it standalone, but hd is really "hexdump
-C" and full hexdump is basically a different syntax for posix od, so that's
probably the logical place to stick it...)

> (but also so i could add \u without adding it
> multiple times) ... and all i ended up with was a bunch of tests
> showing how insane and different echo and printf are.

Sadly, there's a reason they don't share code. (Well, modulo the unescape()
function in lib/lib.c, but that's trivial.)

> the differences
> between printf's direct interpretation of escapes and its %b
> interpretation particularly made my day.

I made it #*%(&#( _work_. And added tests. And have a todo bug sitting here
about %b getting something wrong, which is related to this uncommitted patch in
my printf.c:

@@ -44,11 +44,14 @@ static int handle_slash(char **esc_val, int posix)
   // 0x12 hex escapes have 1-2 digits, \123 octal escapes have 1-3 digits.
   if (eat(&ptr, 'x')) base = 16;
   else {
-    if (posix && *ptr=='0') ptr++;
-    if (*ptr >= '0' && *ptr <= '7') base = 8;
+    if (*ptr!='0') posix = 0;
+    if (ptr[posix] >= '0' && ptr[posix] <= '7') {
+      base = 8;
+      ptr += posix;
+    }
   }
   len = (char []){0,3,2}[base/8];
-
+dprintf(2, "len=%u base=%u\n", len, base);

But unfortunately I don't remember what the actual _bug_ was. I thought I had a
failing test in tests/printf.test for it, but git diff shows that file is clean?
Maybe it was in an earlier tree? I'm pretty sure it's in the back mailing list
posts, but they're not easily searchable. Maybe a back blog entry...

> i'll come back to that at
> some point when my stomach's recovered...

Welcome to my world.

Rob
-------------- next part --------------
/*
  TOY_MAYFORK: echo test printf
    no memory allocations, filehandles open... if signaled, no cleanup.
    maybe: help ulimit

  .toysh_history file
  {abc,def}
  $LINENO $RANDOM
  "source" and "." check current dir after $PATH
  job control: CTRL-Z, CTRL-C, fg, bg, kill %jobspec, wait
  $(command)
  $((math))  # integer attribute for variables, assignment does that
    $((abc"def)) the " doesn't take effect so )) is recognized?
  if then elif else fi
  for while until do done
  case esac
  function () { commands ; }
    local variables in functions
  set -x (and -x command line option) to trace
  export -n (unexports)
  readonly
  read set unset umask
  time (whole pipeline)
  command trap type times getopts

  todo: echo | (cat) # as far as cat's concerned previous end was NULL

  What to do about builtin vs $PATH:
    check $PATH first _then_ builtin?
    config opt?

if files exist use 'em, otherwise:
  /dev/fd/fd stdin stdout stderr tcp/host/port udp/host/port
exec redirects in current shell

 n<word
 n>word
 n>>word (append)
 &>word  # stdout and stderr, same as >word 2>&1
 &>>word (append)
 >&word  # note: >&$BLAH when $BLAH is number or -
 n<&word # number = duplicate, - = close, number- = move 
 n>&word # special case: no n and word not number or -, redirect stderr & out.
 n<<word  # only quote removal, no expansion
         # unquoted: parameter ex, command subst, arith ex, \\ \$ \` \newline
 <<-word # strips leading tabs
 <<<word # all expansions _except_ pathname expansion and word splitting
 n<>word # open file word for reading & writing, create if necessary, n def 0

// &> or >& = >word 2>&1
// &>> append stdout & stderr == >> word 2>&1
// <&# copy input fd (error if # not open for read)
// >&# copy output fd (error if # not open for write)
// <&#- move fd# to n
// >&#- move fd# to n


What does this mean?
  env {abcdef}>&2 | grep abcdef

Instead of number, precede with {varname}?

brace  expansion,  tilde expansion,  parameter  and  variable  expansion,  command substitution,
       arithmetic expansion,  quote  removal,  pathname  expansion,  and  word
       splitting.
  << no path ex or word split

test should work as a nofork, handle [[
what does $(( ))
handle ( ( echo hello ) ) | cat and (echo)|cat

      if (then)
        else elif (then)
        fi
      for select while until (do)
      done
      case (esac)
      ( )
      { }
      [[ ]]
    }

// function
// HERE document
// ( ) - ) is always last argument of line
// | & && || |&

      // "if", "for", "while", "until", "select"
      // "do" : "then";
      // then else elif fi
      // continue break case esac return do done function
      // in time { } ]] ]]
      // ! coproc
      // function ()
      // . source [ test [[ ( { ((

      // [ pwd ulimit -- kill time
      // cd exit -- pushd popd logout umask getopts eval exec
      // fg bg jobs disown wait suspend
      // alias unalias set export unset let local readonly read shift trap



# Because of HERE documents we can't re-parse, have to retain state.
# -- either that or our caller has to know about here document servicing?
# -c input must be split into lines for HERE documents
< > >> <<< WORD
<< HERE [HERE] # eat lines until HERE as _only_ word on line
if [then]
for while until select [do]
case [esac]
( [)] # funky because ) not first word
{ [}]
[[ []]]
function NAME ( ) { # note expect { doesn't eat { be because need to expect }

*/

$ "AB"="CD" echo $AB
bash: AB=CD: command not found
landley at driftwood:~/toybox/toybox$ AB="CD" echo $AB
$ 'AB'="CD" echo $AB
bash: AB=CD: command not found
$ \AB="CD" echo $AB
bash: AB=CD: command not found
$ \AB="CD" echo $AB
$ if echo hello; then fi
bash: syntax error near unexpected token `fi'
$ echo )
bash: syntax error near unexpected token `)'
$ ( echo hello ) | cat
hello
$ if
> true
> then
> echo hello
> fi
hello
$ if true; then echo hello; fi
hello
$ if false; then echo hello; fi
$ false; X=47; echo $?
0
$ if;
bash: syntax error near unexpected token `;'
$ if
> true
> echo
> hello
> fi
bash: syntax error near unexpected token `fi'
$ echo )))
bash: syntax error near unexpected token `)'
$ echo &&&
bash: syntax error near unexpected token `&'
$ echo |||
bash: syntax error near unexpected token `|'
$ echo hello | if true; then read i; echo i=$i; fi
i=hello
$ if true && false; then echo hi; fi
while true ; do echo hello; done | tee blah
if { echo hello; }; then echo hi; fi
if if true; then true; fi; then echo hello; fi
boom(){ echo hello; }; boom
( ( echo; thingy ) ) | cat
$ echo hello | X=y env | grep -w X; echo $X
X=y
;|x
;x|
(echo)also
(echo)(echo)
$ if true esac; then echo hi; fi
hi
# note: exits top level shell anyway!
$ (exit walrus)
bash: exit: walrus: numeric argument required
$ echo $?
2
$ exit walrus 2>blah.txt
$ echo ${abc:?error m essage}
bash: abc: error m essage
$ if blah () { echo bang; true; }; blah; then echo hello; fi; blah
bang
hello
bang
$ meep() { echo hello; klarg () { echo helloier; }; klarg; }
$ meep
hello
helloier
  $ meep() { echo hello; klarg() { echo helloier; } ; }
  $ klarg
  bash: klarg: command not found
  $ meep
  hello
  $ klarg
  helloier
  $ 

landley at driftwood:~/toybox/toybox$ thingy ()
> ^C
landley at driftwood:~/toybox/toybox$ echo (
bash: syntax error near unexpected token `newline'
landley at driftwood:~/toybox/toybox$ function
bash: syntax error near unexpected token `newline'
landley at driftwood:~/toybox/toybox$ function name () {
> }
bash: syntax error near unexpected token `}'
landley at driftwood:~/toybox/toybox$ function name () { ;}
bash: syntax error near unexpected token `;'
landley at driftwood:~/toybox/toybox$ if ; then; echo hello; fi
bash: syntax error near unexpected token `;'
landley at driftwood:~/toybox/toybox$ func (); { echo hello; }
bash: syntax error near unexpected token `;'
$ if true |
> then
bash: syntax error
echo one && if true; then echo hello; fi
one
hello
$ echo one two \
> three
$ bash -c "$(echo -e 'cat << HERE\none two\nHERE')"
one two
$ cat << HERE; echo hello
> boing
> HERE
boing
hello
$ cat << one << two
> abc
$ ls > file 2>&1 #redirects both
$ ls 2>&1 >file # redirects only stdout, stderr goes to original stdout
$ echo hello < nowhere
bash: nowhere: No such file or directory
$ cat << E"O"F
> $PATH
> EOF
$PATH
$ cat << HERE filename
> HERE
cat: filename: No such file or directory
$ cat <<< here filename
cat: filename: No such file or directory


landley at driftwood:~/toybox/toybox$ bash -c "cat <<< HERE; echo hello; HERE"
HERE
hello
bash: HERE: command not found
landley at driftwood:~/toybox/toybox$ bash -c "cat << HERE; echo hello; HERE"
bash: warning: here-document at line 0 delimited by end-of-file (wanted `HERE')
hello
bash: HERE: command not found
landley at driftwood:~/toybox/toybox$ bash -c "$(echo 'cat << HERE\necho hello\nHERE')"
bash: warning: here-document at line 0 delimited by end-of-file (wanted `HEREnecho')
cat: hellonHERE: No such file or directory
landley at driftwood:~/toybox/toybox$ bash -c "$(echo -e 'cat << HERE\necho hello\nHERE')"
echo hello
landley at driftwood:~/toybox/toybox$ X=3; echo $((X))
3
landley at driftwood:~/toybox/toybox$ X=3; echo $((X))^C
landley at driftwood:~/toybox/toybox$ echo |
> 
> cat

landley at driftwood:~/toybox/toybox$ echo &&
> &&
bash: syntax error near unexpected token `&&'
landley at driftwood:~/toybox/toybox$ echo &&
> ;
bash: syntax error near unexpected token `;'
landley at driftwood:~/toybox/toybox$ if
> true
> then
> echo hello
> fi
hello
landley at driftwood:~/toybox/toybox$ << EOF
> echo hello
> EOF
$ echo &<2
[1] 17850

bash: 2: No such file or directory
landley at driftwood:~/toybox/toybox$ 
[1]+  Done                    echo
landley at driftwood:~/toybox/toybox$ { echo hello; }
hello
landley at driftwood:~/toybox/toybox$ { { echo hello; };}
hello
landley at driftwood:~/toybox/toybox$ {{ echo hello; };}
bash: syntax error near unexpected token `}'
landley at driftwood:~/toybox/toybox$ { {echo hello; };}
bash: syntax error near unexpected token `}'
landley at driftwood:~/toybox/toybox$ { { echo hello; };}
hello
landley at driftwood:~/toybox/toybox$ {
> {
> echo hello
> }
> }
hello
$ if cat << EOF ; then
> one two three
> EOF
> echo hello
> fi
one two three
hello
cat <(ls "$PWD"/a{b,c}*) &> /dev/tcp/127.0.0.1/80
$ while grep -q << EOF walrus; do
> walrus
> EOF
> echo hello; done | head -n 3
hello
hello
hello
$ if echo hello; then echo also; fi | tee and.txt # both get redirected
hello
also
$ cat - << EOF <(echo
> hello)
> boing
> EOF
bash: hello: command not found
boing

$ ( ( ( echo abc ) echo ) )
bash: syntax error near unexpected token `echo'
$ ( ( ( echo abc )
> echo also ) )
abc
also
$ ( ( echo one ) > file )
$ ( ( echo one ) > two ) > three
$ ( echo ) >> blah
$ if true; then echo; fi >> blah
$ cat - /proc/self/fd/3 << BOING 3<<MEEP
> one
> BOING
> aha
> MEEP
one
aha
$ cat - << BOING $(    
echo hello)
abc
BOING
abc
blah
$ ( cat << EOF
> hello
> EOF
> )
hello
$ if cat << EOF
> hello
> EOF
> then
> echo fi
> fi
hello
fi
$ echo 2>&1
$ echo 2 >&1
$ echo 2 >& 1
$ if while true; do echo hello; done; then echo hi; fi
$ (echo &&)
$ (echo ;)
$ if true; then echo $X; fi {X}</dev/null
10
$ ls /proc/$$/fd
$ exec 10<& -
# >&; ;&>
# prompts before echoing
$ echo hello; if
> echo two; then echo three
> fi
hello
two
three
$ echo )hello
bash: syntax error near unexpected token `)'
$ echo {abc
{abc
$ echo {abc</dev/null
{abc
# innermost redirect wins
$ if cat <<< moo ; then cat <<< also; fi <<< potato
moo
also
$ (echo &&)
bash: syntax error near unexpected token `)'
$ funkiness() { env ; }
$ POTATO=blah funkiness | grep POTATO
POTATO=blah
$ echo $POTATO
$ chicken() { echo hello; chicken() { echo also ;}; chicken;}
$ chicken
hello
also
$ chicken
also
$ thingy() { echo hello; } | cat
$ thingy
bash: thingy: command not found
$ echo hello > >(sed 's/.*/abc&def/') > >(sed 's/.*/ghi&jkl/')
abcghihellojkldef
$ echo hello > one > two
$ yes | head -n 3 > >(wc -l >two) > >(wc -l >one)
landley at driftwood:~$ cat one
3
landley at driftwood:~$ cat two
0
$ </dev/null echo hello
hello
$ echo {+}</dev/null
{+}
$ echo {}</dev/null
{}
$ echo <
bash: syntax error near unexpected token `newline'
$ murgle() { echo > "$@" ;}
$ murgle one two three
bash: "$@": ambiguous redirect
$ murgle one
$ cat << "   "
> abc
>    
abc
$ cat << \"
> boing
> "
boing
$ echo hello &>> blah.txt
$ potato() { echo "$@"; }; IFS=1234 potato one two three
one two three
$ cat <<< {one,two,three}
{one,two,three}
$ cat <<< one two three
$ echo hello >&2-x && ls 2-x
2-x
$ while true; do sleep 1; read a; echo $a; [ -z "$a" ] && break; done << EOF &
> one
> two
> three
> EOF
[1] 30590
$ (set -o noclobber; echo > /dev/null)
$ (ln -s /dev/null blah; set -o noclobber; echo > blah)
$ (touch walrus; ln -s walrus penguin; set -o noclobber; echo > penguin)
$ funky() { A="$@" ;}; funky one two three; echo $A
one two three
$ export "()=42"
bash: export: `()=42': not a valid identifier
$ set hello="$@" > walrus
$ X=$(false) || echo true
true
$ for((i=1;i<5;i++));do echo $i;done
1
2
3
4
# when is (( a token vs ( (?
$ ((echo a) | sed s/a/b/)
b
$ ((1
> +2<1)); echo $?
1
$ X=ii;for $X in a b c; do echo $ii; done
bash: `$X': not a valid identifier
$ for i in 1 2 3 & do echo hello; done
bash: syntax error near unexpected token `&'
$ if true; then false; else true; elif true; then false; fi
bash: syntax error near unexpected token `elif'
$ while false; true; do echo hello; done | head -n 3
hello
hello
hello
$ せ=42
bash: せ=42: command not found
$ function abc=def () {echo hello;} ; "abc=def"
hello
$ ((echo hello) )
hello
$ abc() { for name; do echo $name; done;}; abc X Y Z
X
Y
Z
# In a for loop ;; breaks down to ; ;
$ for((i=0;;i++)); do echo $i; done | head -n 30
1
2
$ (()); echo $?
1
$ ((x=12)); echo $x
12
$ (echo 123)  # redir prefix not used for non-redir end tokens
123
$ x=42; ! ((x<3)) && ((x<43)) && echo yes
yes
# redirects aren't in math
$ echo $((2<3))
1
$ echo $((2&3))
2
$ ((3<2)); echo $?
1
$ X=X; echo $((X+2))
bash: X: expression recursion level exceeded (error token is "X")
$ X=3 ((3<2)) || echo hello
bash: syntax error near unexpected token `('
$ echo $((`echo 1`))
1
$ X=3; (($X<3)) || echo no; (($X<4)) && echo yes
no
yes
$ cat <(echo "$(((1<2)) && echo "hello")")
hello
$ THINGY=whoami; echo "$("${THINGY}")"
landley
$ burble() #comment
> { echo hello;};burble
hello
$ for i=3
> do echo hello; done
bash: `i=3': not a valid identifier
$ ((1<2)) > blat
$ boing () { for name do echo $name; done }; boing one two three
one
two
three
$ cat <( "(" )
bash: (: command not found


More information about the Toybox mailing list