[Toybox] toysh "local"builtin.

Rob Landley rob at landley.net
Tue May 9 21:19:24 PDT 2023


Github's being weird at the moment (I can't wait for it to forbid me from ever
logging in again when I refuse to give it my phone number, that's apparently
coming later this year)...

So in https://github.com/landley/toybox/issues/426 the most recent bug is:

> sh: local: No such file or directory

Huh. I implemented local_main(), but didn't have a NEWTOY(local) line hooking it
up to the function dispatch table. I _thought_ I'd tested this? Why did...

Because the bash help says [options] for local but does not appear to TAKE any
options. And I never tracked that down or asked Chet "wha...?"

I remember I did a lot of work in various branches over the pandemic and had
long walks working out lifetime rule corner cases. Variables can be exported,
unexported, and local to a function context but inherited by _other_ function
contexts they call, also "source" is KIND of like a function context but not
exactly, so when you source a file that calls a function that sources another
file... anyway, there's a context stack which includes a variable table at each
level and you have to traverse them in order, although sometimes the "root" one
at the base of the stack is special, which is why it's nice it's a doubly-linked
list and I can just go head->prev to get that. :)

Yes, you can export a local variable. This came as a surprise to me, but
lifetime != visibility...

Oh, and the way "unset" interacts with "local" is basically union mount logic
that requires whiteouts. Declaring a local hides any existing variable in the
enclosing scope until the function returns, and if you then unset the variable
you declared local you do NOT get the global back, nor is the global unset.
Instead the local scope gains an "unset" entry that still prevents it from
seeing the variable declared in the enclosing scope until you return, but you
can re-set it and the new one is still local. (Plus there's ${NAME:-default} and
so on that distinguishes between "unset" and "set to blank", so ${NAME-default}
has to trigger only on a locally _unset_ variable, and ${NAME:-default} would
trigger on one that was locally set to "".

ALL of this needs tests in sh.test. And I have to revisit all this to to add
array support anyway...

I can hook up what's there and see what it does...?

Rob


More information about the Toybox mailing list