summaryrefslogtreecommitdiff
path: root/build/panto_lua_repl.c
blob: ce99cb15198f294d74f340bf6ba2d64ebcb71823 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/*
 * panto's hook into the upstream `lua.c` standalone interpreter.
 *
 * We need to call into `pmain` (the body of the standalone REPL/driver)
 * with a pre-configured `lua_State` — specifically, one where panto's
 * embedded-luarocks searcher and configured `package.path` have already
 * been installed. Upstream `pmain` is `static`, so we can't link to it
 * from Zig directly.
 *
 * Trick: include `lua.c` verbatim with `static` redefined to empty, so
 * every static gets external linkage. We rename `main` to a stub via
 * macro so it doesn't conflict with panto's own `main`. Then we expose
 * a single function, `panto_lua_pmain`, that runs `pmain` against a
 * caller-provided state.
 *
 * `lua.c` also defines its own signal handlers via `setsignal` /
 * `laction`. We leave those alone — they're useful in `panto lua` too,
 * giving Ctrl-C the same behavior it has in upstream `lua`.
 */

/* Remove `static` everywhere lua.c uses it so symbols are externally
 * accessible. We undef `static` back to default for any system headers
 * that follow, in case they care. */
#define static
#include "lua.c"
#undef static

/* Forward declarations of the (now non-static) symbols we use. */
extern int pmain(lua_State *L);

/*
 * Trampoline: push (argc, argv) onto `L` and run `pmain` in protected
 * mode, mirroring `lua.c::main`'s call pattern. Returns the exit code
 * appropriate for `lua` (0 on success, 1 on failure).
 *
 * The caller is responsible for state lifecycle (lua_close, etc.) —
 * we don't open or close `L` ourselves. This is what lets panto's
 * subcommand install the embedded-luarocks searcher into `L` *before*
 * calling us.
 */
int panto_lua_pmain(lua_State *L, int argc, char **argv) {
    lua_pushcfunction(L, &pmain);
    lua_pushinteger(L, argc);
    lua_pushlightuserdata(L, argv);
    int status = lua_pcall(L, 2, 1, 0);
    int result = lua_toboolean(L, -1);
    report(L, status);
    return (result && status == LUA_OK) ? 0 : 1;
}