|
| 1 | +/* SPDX-License-Identifier: MIT */ |
| 2 | +/* SPDX-FileCopyrightText: 2026 sp00ktober */ |
| 3 | +/* mhfu.addr: an entry of addresses.toml becomes a Lua value the first time a script reads it, so |
| 4 | + * the slab holds only the entries scripts use. */ |
| 5 | +#include <string.h> |
| 6 | + |
| 7 | +#include "mhfu/mhfu.h" |
| 8 | +#include "lua_host.h" |
| 9 | +#include "addresses_table.gen.inc" /* k_mhfu_addr */ |
| 10 | + |
| 11 | +static void push_entry(lua_State *L, const mhfu_addr_entry *e) |
| 12 | +{ |
| 13 | + int n = 0; |
| 14 | + if (e->fields) { |
| 15 | + while (e->fields[n].name) n++; |
| 16 | + lua_createtable(L, 0, n); |
| 17 | + for (int i = 0; i < n; i++) { |
| 18 | + lua_pushinteger(L, (lua_Integer)e->fields[i].value); |
| 19 | + lua_setfield(L, -2, e->fields[i].name); |
| 20 | + } |
| 21 | + } else if (e->names) { |
| 22 | + while (e->names[n]) n++; |
| 23 | + lua_createtable(L, n, 0); |
| 24 | + for (int i = 0; i < n; i++) { |
| 25 | + lua_pushstring(L, e->names[i]); |
| 26 | + lua_rawseti(L, -2, i + 1); |
| 27 | + } |
| 28 | + } else { |
| 29 | + lua_pushinteger(L, (lua_Integer)e->value); |
| 30 | + } |
| 31 | +} |
| 32 | + |
| 33 | +/* __index: builds the entry and keeps it in mhfu.addr. */ |
| 34 | +static int addr_index(lua_State *L) |
| 35 | +{ |
| 36 | + if (lua_type(L, 2) != LUA_TSTRING) return 0; |
| 37 | + const char *key = lua_tostring(L, 2); |
| 38 | + for (const mhfu_addr_entry *e = k_mhfu_addr; e->name; e++) { |
| 39 | + if (strcmp(e->name, key) != 0) continue; |
| 40 | + push_entry(L, e); |
| 41 | + lua_pushvalue(L, 2); |
| 42 | + lua_pushvalue(L, -2); |
| 43 | + lua_rawset(L, 1); |
| 44 | + return 1; |
| 45 | + } |
| 46 | + return 0; |
| 47 | +} |
| 48 | + |
| 49 | +/* __pairs: builds every entry, then iterates with the base library's next (upvalue 1). */ |
| 50 | +static int addr_pairs(lua_State *L) |
| 51 | +{ |
| 52 | + for (const mhfu_addr_entry *e = k_mhfu_addr; e->name; e++) { |
| 53 | + lua_getfield(L, 1, e->name); |
| 54 | + lua_pop(L, 1); |
| 55 | + } |
| 56 | + lua_pushvalue(L, lua_upvalueindex(1)); |
| 57 | + lua_pushvalue(L, 1); |
| 58 | + lua_pushnil(L); |
| 59 | + return 3; |
| 60 | +} |
| 61 | + |
| 62 | +void mhfu_lua_addr_install(lua_State *L) |
| 63 | +{ |
| 64 | + lua_newtable(L); |
| 65 | + lua_createtable(L, 0, 2); |
| 66 | + lua_pushcfunction(L, addr_index); |
| 67 | + lua_setfield(L, -2, "__index"); |
| 68 | + lua_getglobal(L, "next"); |
| 69 | + lua_pushcclosure(L, addr_pairs, 1); |
| 70 | + lua_setfield(L, -2, "__pairs"); |
| 71 | + lua_setmetatable(L, -2); |
| 72 | + lua_setfield(L, -2, "addr"); |
| 73 | +} |
0 commit comments