dcl_dehacktivate() actually left a bit of inconsistent state beyond
the current line because it did not clear the dummy builtins tree.
This caused assignments to variables of types whose definitions
were parsed but not executed to throw a "not found" error instead
of a syntax error, even beyond the current line.
There is also an opportunity for an optimisation. We do not need to
initialise and maintain the dummy builtins tree if we're never
going to use it. So move that to the check_typedef() function right
before the sh_addbuiltin() call: check there if the tree exists and
if not create it and open a view. If no 'typeset -T' or 'enum'
type definition command is executed, the tree is never created.
dcl_hacktivate() now basically does nothing until the tree is
needed, but it does still count the recursion level and install the
error_info.exit hook because we need this to dcl_dehacktivate() at
the correct time when the tree does exist.
dcl_dehacktivate() is amended to clear the tree -- except if we're
running shcomp, as shcomp parses the script line by line without
executing anything, so we need the dummies to persist beyond the
sh_parse() invocation for the entire script. (Note that we do not
need this workaround for dot scripts or noexec mode, as the script
is entirely parsed in a single sh_parse() call in those cases.)