From 0d2f598c3e9ad20fe4dc2f77f42ce78cfad71fe7 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 31 Mar 2023 14:36:16 +0100 Subject: [PATCH 1/2] Hardcode assist, part 1 - Add read-only `string` field to several info table metatables already available in Lua. - mobjinfo[i].name - states[i].name - sfxinfo[i].string --- src/lua_infolib.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 71eff8784..b14802230 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -43,7 +43,8 @@ enum sfxinfo_read { sfxinfor_flags, // "pitch" sfxinfor_volume, sfxinfor_caption, - sfxinfor_skinsound + sfxinfor_skinsound, + sfxinfor_string, }; const char *const sfxinfo_ropt[] = { "name", @@ -53,6 +54,7 @@ const char *const sfxinfo_ropt[] = { "volume", "caption", "skinsound", + "string", NULL}; enum sfxinfo_write { @@ -948,6 +950,24 @@ static int state_get(lua_State *L) number = st->var2; else if (fastcmp(field,"nextstate")) number = st->nextstate; + else if (fastcmp(field,"string")) + { + statenum_t id = st-states; + if (id < S_FIRSTFREESLOT) + { + lua_pushstring(L, STATE_LIST[id]+2); + return 1; + } + + id -= S_FIRSTFREESLOT; + if (id < NUMSTATEFREESLOTS && FREE_STATES[id]) + { + lua_pushstring(L, FREE_STATES[id]); + return 1; + } + + return 0; + } else if (devparm) return luaL_error(L, LUA_QL("state_t") " has no field named " LUA_QS, field); else @@ -1213,6 +1233,23 @@ static int mobjinfo_get(lua_State *L) lua_pushinteger(L, info->flags); else if (fastcmp(field,"raisestate")) lua_pushinteger(L, info->raisestate); + else if (fastcmp(field,"string")) { + mobjtype_t id = info-mobjinfo; + if (id < MT_FIRSTFREESLOT) + { + lua_pushstring(L, MOBJTYPE_LIST[id]+3); + return 1; + } + + id -= MT_FIRSTFREESLOT; + if (id < NUMMOBJFREESLOTS && FREE_MOBJS[id]) + { + lua_pushstring(L, FREE_MOBJS[id]); + return 1; + } + + return 0; + } else { lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); @@ -1436,6 +1473,10 @@ static int sfxinfo_get(lua_State *L) case sfxinfor_skinsound: lua_pushinteger(L, sfx->skinsound); return 1; + case sfxinfor_string: { + lua_pushstring(L, sfx->name); + return 1; + } default: return luaL_error(L, "Field does not exist in sfxinfo_t"); } From faccea62070c161c29601240106e1f3e0d0901d7 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 1 Apr 2023 05:44:59 -0700 Subject: [PATCH 2/2] Hardcode assist, part J (jartha) - Add read-only `actionname` field to Lua states. - Resolves to function name definition of global Lua functions. - Resolves to all-uppercase name for C actions. - Resolves to "NULL" string if nil. --- src/blua/ldebug.c | 20 ++++++++++++++++++++ src/blua/lfunc.c | 3 +++ src/blua/lobject.h | 3 +++ src/blua/lparser.c | 34 +++++++++++++++++++++++----------- src/lua_infolib.c | 22 ++++++++++++++++++++++ 5 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/blua/ldebug.c b/src/blua/ldebug.c index 542e209a1..143d5d614 100644 --- a/src/blua/ldebug.c +++ b/src/blua/ldebug.c @@ -31,6 +31,9 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); +#ifdef DEVELOP +static const char *getcanonicalfuncname (Closure *f, const char **name); +#endif static int currentpc (lua_State *L, CallInfo *ci) { @@ -212,7 +215,11 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, break; } case 'n': { +#ifdef DEVELOP + ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : getcanonicalfuncname(f, &ar->name); +#else ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; +#endif if (ar->namewhat == NULL) { ar->namewhat = ""; /* not found */ ar->name = NULL; @@ -555,6 +562,19 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { } +#ifdef DEVELOP +static const char *getcanonicalfuncname (Closure *cl, const char **name) { + if (!cl->c.isC && cl->l.p->canonicalname) + { + *name = cl->l.p->canonicalname; + return "global"; + } + else + return NULL; +} +#endif + + /* only ANSI way to check whether a pointer points to an array */ static int isinstack (CallInfo *ci, const TValue *o) { StkId p; diff --git a/src/blua/lfunc.c b/src/blua/lfunc.c index 22f670e67..a07824c44 100644 --- a/src/blua/lfunc.c +++ b/src/blua/lfunc.c @@ -134,6 +134,9 @@ Proto *luaF_newproto (lua_State *L) { f->linedefined = 0; f->lastlinedefined = 0; f->source = NULL; +#ifdef DEVELOP + f->canonicalname = NULL; +#endif return f; } diff --git a/src/blua/lobject.h b/src/blua/lobject.h index 24309a1ec..6484e0e8c 100644 --- a/src/blua/lobject.h +++ b/src/blua/lobject.h @@ -237,6 +237,9 @@ typedef struct Proto { struct LocVar *locvars; /* information about local variables */ TString **upvalues; /* upvalue names */ TString *source; +#ifdef DEVELOP + const char *canonicalname; /* function name, only for globals right now */ +#endif int sizeupvalues; int sizek; /* size of `k' */ int sizecode; diff --git a/src/blua/lparser.c b/src/blua/lparser.c index 3f392ae7b..aeed307ec 100644 --- a/src/blua/lparser.c +++ b/src/blua/lparser.c @@ -246,8 +246,7 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { } -static void singlevar (LexState *ls, expdesc *var) { - TString *varname = str_checkname(ls); +static void singlevar (LexState *ls, expdesc *var, TString *varname) { FuncState *fs = ls->fs; if (singlevaraux(fs, varname, var, 1) == VGLOBAL) var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ @@ -603,11 +602,16 @@ static void body_noparms (LexState *ls, expdesc *e, int line) { close_func(ls); pushclosure(ls, &new_fs, e); } -static void body (LexState *ls, expdesc *e, int needself, int line) { +static void body (LexState *ls, expdesc *e, int needself, int line, const char *name) { /* body -> `(' parlist `)' chunk END */ FuncState new_fs; open_func(ls, &new_fs); new_fs.f->linedefined = line; +#ifdef DEVELOP + new_fs.f->canonicalname = name; +#else + (void)name; +#endif checknext(ls, '('); if (needself) { new_localvarliteral(ls, "self", 0); @@ -706,7 +710,7 @@ static void prefixexp (LexState *ls, expdesc *v) { return; } case TK_NAME: { - singlevar(ls, v); + singlevar(ls, v, str_checkname(ls)); return; } case '$': { @@ -826,7 +830,7 @@ static void simpleexp (LexState *ls, expdesc *v) { } case TK_FUNCTION: { luaX_next(ls); - body(ls, v, 0, ls->linenumber); + body(ls, v, 0, ls->linenumber, NULL); return; } default: { @@ -1315,11 +1319,12 @@ static void ifstat (LexState *ls, int line) { static void localfunc (LexState *ls) { expdesc v, b; FuncState *fs = ls->fs; - new_localvar(ls, str_checkname(ls), 0); + TString *name = str_checkname(ls); + new_localvar(ls, name, 0); init_exp(&v, VLOCAL, fs->freereg); luaK_reserveregs(fs, 1); adjustlocalvars(ls, 1); - body(ls, &b, 0, ls->linenumber); + body(ls, &b, 0, ls->linenumber, NULL); luaK_storevar(fs, &v, &b); /* debug information will only see the variable after this point! */ getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; @@ -1345,10 +1350,10 @@ static void localstat (LexState *ls) { } -static int funcname (LexState *ls, expdesc *v) { +static int funcname (LexState *ls, expdesc *v, TString *varname) { /* funcname -> NAME {field} [`:' NAME] */ int needself = 0; - singlevar(ls, v); + singlevar(ls, v, varname); while (ls->t.token == '.') field(ls, v); if (ls->t.token == ':') { @@ -1363,9 +1368,16 @@ static void funcstat (LexState *ls, int line) { /* funcstat -> FUNCTION funcname body */ int needself; expdesc v, b; + TString *name; luaX_next(ls); /* skip FUNCTION */ - needself = funcname(ls, &v); - body(ls, &b, needself, line); + name = str_checkname(ls); + needself = funcname(ls, &v, name); +#ifdef DEVELOP + /* just strdup this because I couldn't figure out gc */ + body(ls, &b, needself, line, name ? strdup(getstr(name)) : NULL); +#else + body(ls, &b, needself, line, NULL); +#endif luaK_storevar(ls->fs, &v, &b); luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ } diff --git a/src/lua_infolib.c b/src/lua_infolib.c index b14802230..df55de66e 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -944,6 +944,28 @@ static int state_get(lua_State *L) // because the metatable will trigger. lua_getglobal(L, name); // actually gets from LREG_ACTIONS if applicable, and pushes a META_ACTION userdata if not. return 1; // return just the function +#ifdef DEVELOP + } else if (fastcmp(field,"actionname")) { + if (!st->action.acp1) { // Action is NULL. + lua_pushstring(L, "NULL"); + } else if (st->action.acp1 == (actionf_p1)A_Lua) { // This is a Lua function? + lua_Debug ar; + lua_getfield(L, LUA_REGISTRYINDEX, LREG_STATEACTION); + I_Assert(lua_istable(L, -1)); + lua_pushlightuserdata(L, st); // Push the state pointer and + lua_rawget(L, -2); // use it to get the actual Lua function. + lua_remove(L, -2); // pop LREG_STATEACTION + // This normally doesn't get a function's name because the same Lua function can have many names. + // It only works because of a hack called 'canonicalname' in blua/lparser.c, which records the + // name a GLOBAL function was defined with. This does not work for local functions! (Lua actions + // are almost always global functions though.) + lua_getinfo(L, ">n", &ar); + lua_pushstring(L, ar.name); + } else { + lua_pushstring(L, LUA_GetActionName(&st->action)); // find a hardcoded function name + } + return 1; +#endif } else if (fastcmp(field,"var1")) number = st->var1; else if (fastcmp(field,"var2"))