pub fn runshfunc(prog: &eprog, wrap: Option<&funcwrap>, name: &str)Expand description
Port of void runshfunc(Eprog prog, FuncWrap wrap, char *name) from
Src/exec.c:6166. The inner shell-function executor — fires
module-registered wrapper handlers around the function body, with
$_ (zunderscore) save/restore and a paramscope push/pop around
the wordcode walk.
C control flow:
queue_signals();
ou = zalloc(ouu = underscoreused);
if (ou) memcpy(ou, zunderscore, underscoreused);
while (wrap) { // wrapper chain
wrap->module->wrapper++;
cont = wrap->handler(prog, wrap->next, name);
wrap->module->wrapper--;
if (!wrap->module->wrapper && (wrap->module->node.flags & MOD_UNLOAD))
unload_module(wrap->module);
if (!cont) { // wrapper handled it
if (ou) zfree(ou, ouu);
unqueue_signals();
return;
}
wrap = wrap->next;
}
startparamscope();
execode(prog, 1, 0, "shfunc");
if (ou) { setunderscore(ou); zfree(ou, ouu); }
endparamscope();
unqueue_signals();(a) wrap->module->wrapper++/-- (c:6178/6180) wired against
module::MODULESTAB.modules[name].wrapper (i32), looked up
by wrap.module.node.nam. Recursive unload during handler
defers correctly.
(b) unload_module(wrap->module) (c:6184) wired via
modulestab.unload_module(name) when wrapper hits 0 AND
MOD_UNLOAD flag is set on the module’s hashnode.
(c) execode(prog, 1, 0, "shfunc") (c:6195) ported at
exec.rs:6047. Body uses execode for the no-source
(compiled-wordcode) branch and fusevm for the
source-preserving (autoloaded) branch per cache coherence.
(d) startparamscope/endparamscope Rust signatures take
&mut HashTable (params.rs:7425/7435). We pass the global
paramtab handle via the params crate.