Re: [PATCH] Use realparamtab and don't dereference special parameters in zle code

Philippe Altherr <[email protected]> Fri, 19 Jun 2026 14:09:40 +0200
Newsgroups gmane.comp.shells.zsh.devel
Message-ID <CAGdYchueecXN0ou+e9acCkUM5Otg6oLdtQiPsrBO4wHAJiU9+Q@mail.gmail.com>
>
> Normally you would explain a change like this with motivations of some
> sort. Why is this correct? When is paramtab possibly some other
> parameter table than realparamtab? Is this change making things less
> flexible? Are you solving an actual problem? These are things you've
> presumably already investigated, so you should tell us about it so we
> don't have to duplicate the work.


The patch does more of the same as workers/54475
<http://zsh.org/workers/54475>, which was already committed. That's why I
didn't elaborate.

The patch does two things:

   - Replace some calls to getnode() with calls to getnode2(). The main
   difference between the two is that the latter returns the parameter found
   in the table as is, while the former dereferences any named reference it
   finds. In some places, you only need the latter. Sometimes the former is
   not just unnecessary but problematic, see workers/54475
   <http://zsh.org/workers/54475> for an example.


   - Replace paramtab with realparamtab in places that intend to refer to
   the parameter table. More on this below.

The two changes are in principle independent of each other but because they
often touch the same lines of code it's easier to do it at the same time.
If I need to understand a piece of code for one then it's not much more
work to also understand it for the other. Doing the changes in the same
patch avoids merge conflicts.

*realparamtab vs paramtab*

The two global variables are defined in params.c
<https://github.com/paltherr/zsh/blob/cef9382944fdb19fe11ca1345b5b4fe2e0f48440/Src/params.c#L534>.
Originally there was only paramtab, which contained the parameter table.
When associative tables were added to Zsh, it turned out that many
functions that worked on the parameter table could also be useful
for associative tables. In order to reuse them instead of duplicating them,
the global variable realparamtab was added to contain the parameter table
and the global paramtab was repurposed to either contain the parameter
table or an associative table. Thus, one can reuse a function originally
designed for the parameter table to work on an associative table
by initializing paramtab with that associative table before calling the
function and then restoring paramtab to its previous value after the call.
At startup, paramtab is initialized with realparamtab.

This (imo horrible) hack had the great advantage that it enabled the reuse
of many functions with very little code changes. An unfortunate consequence
is that it instantly turned a lot of code into code that seemingly works
both for the parameter table and for associative tables, while in reality
it only makes sense for the former. Replacing paramtab with realparamtab
makes that clear.

The vast majority of functions that actually make sense for both usages are
in params.c. Ultimately paramtab should only be used in these functions. My
secret hope is to even get rid of the paramtab global variable by adding an
extra parameter to these functions but that will depend on how many such
functions there are. If it's just a few, it would be a net win but if there
are many, it may not be worth it.

Philippe