Paweł Kołodziejski 690f9d2a5c GRIM,LUA: Janitorial
2022-01-06 18:26:30 +01:00

249 lines
6.2 KiB
C++

/*
** Tag methods
** See Copyright Notice in lua.h
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_setjmp
#define FORBIDDEN_SYMBOL_EXCEPTION_longjmp
#define FORBIDDEN_SYMBOL_EXCEPTION_fprintf
#define FORBIDDEN_SYMBOL_EXCEPTION_stderr
#include "engines/grim/lua/lauxlib.h"
#include "engines/grim/lua/lmem.h"
#include "engines/grim/lua/lobject.h"
#include "engines/grim/lua/lstate.h"
#include "engines/grim/lua/ltm.h"
#include "engines/grim/lua/lapi.h"
namespace Grim {
const char *luaT_eventname[] = { // ORDER IM
"gettable", "settable", "index", "getglobal", "setglobal", "add",
"sub", "mul", "div", "pow", "unm", "lt", "le", "gt", "ge",
"concat", "gc", "function", nullptr
};
static int32 luaI_checkevent(const char *name, const char *list[]) {
int32 e = luaO_findstring(name, list);
if (e < 0)
luaL_verror("`%.50s' is not a valid event name", name);
return e;
}
/* events in LUA_T_NIL are all allowed, since this is used as a
* 'placeholder' for "default" fallbacks
*/
static char validevents[NUM_TAGS][IM_N] = { // ORDER LUA_T, ORDER IM
{1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, // LUA_T_USERDATA
{1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1}, // LUA_T_NUMBER
{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, // LUA_T_STRING
{0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // LUA_T_ARRAY
{1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, // LUA_T_PROTO
{1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, // LUA_T_CPROTO
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // LUA_T_TASK
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} // LUA_T_NIL
};
static int32 validevent(int32 t, int32 e) { // ORDER LUA_T
return (t < LUA_T_NIL) ? 1 : validevents[-t][e];
}
static void init_entry(int32 tag) {
for (int32 i = 0; i < IM_N; i++)
ttype(luaT_getim(tag, i)) = LUA_T_NIL;
}
static bool tmFBAdded = false;
void luaT_init() {
IMtable_size = NUM_TAGS * 2;
last_tag = -(NUM_TAGS - 1);
IMtable = luaM_newvector(IMtable_size, struct IM);
for (int32 t = -(IMtable_size - 1); t <= 0; t++)
init_entry(t);
tmFBAdded = false;
}
int32 lua_newtag() {
--last_tag;
if (-last_tag >= IMtable_size)
IMtable_size = luaM_growvector(&IMtable, IMtable_size, struct IM, memEM, MAX_INT);
init_entry(last_tag);
return last_tag;
}
static void checktag(int32 tag) {
if (!(last_tag <= tag && tag <= 0))
luaL_verror("%d is not a valid tag", tag);
}
void luaT_realtag(int32 tag) {
if (!(last_tag <= tag && tag < LUA_T_NIL))
luaL_verror("tag %d is not result of `newtag'", tag);
}
int32 lua_copytagmethods(int32 tagto, int32 tagfrom) {
int32 e;
checktag(tagto);
checktag(tagfrom);
for (e = 0; e < IM_N; e++) {
if (validevent(tagto, e))
*luaT_getim(tagto, e) = *luaT_getim(tagfrom, e);
}
return tagto;
}
int32 luaT_efectivetag(TObject *o) {
int32 t;
switch (t = ttype(o)) {
case LUA_T_ARRAY:
return o->value.a->htag;
case LUA_T_USERDATA:
{
int32 tag = o->value.ud.tag;
return (tag >= 0) ? LUA_T_USERDATA : tag;
}
case LUA_T_CLOSURE:
return o->value.cl->consts[0].ttype;
#ifdef LUA_DEBUG
case LUA_T_PMARK:
case LUA_T_CMARK:
case LUA_T_CLMARK:
case LUA_T_LINE:
lua_error("internal error");
#endif
default:
return t;
}
}
TObject *luaT_gettagmethod(int32 t, const char *event) {
int32 e = luaI_checkevent(event, luaT_eventname);
checktag(t);
if (validevent(t, e))
return luaT_getim(t,e);
else
return &luaO_nilobject;
}
void luaT_settagmethod(int32 t, const char *event, TObject *func) {
TObject temp = *func;
int32 e = luaI_checkevent(event, luaT_eventname);
checktag(t);
if (!validevent(t, e))
luaL_verror("settagmethod: cannot change tag method `%.20s' for tag %d",
luaT_eventname[e], t);
*func = *luaT_getim(t,e);
*luaT_getim(t, e) = temp;
}
const char *luaT_travtagmethods(int32 (*fn)(TObject *)) {
int32 e;
if (fn(&errorim))
return "error";
for (e = IM_GETTABLE; e <= IM_FUNCTION; e++) { // ORDER IM
int32 t;
for (t = 0; t >= last_tag; t--)
if (fn(luaT_getim(t, e)))
return luaT_eventname[e];
}
return nullptr;
}
/*
* compatibility with old fallback system
*/
#ifdef LUA_COMPAT2_5
void errorFB() {
lua_Object o = lua_getparam(1);
if (lua_isstring(o))
fprintf(stderr, "lua: %s\n", lua_getstring(o));
else
fprintf(stderr, "lua: unknown error\n");
}
void nilFB() { }
void typeFB () {
lua_error("unexpected type");
}
static void fillvalids(IMS e, TObject *func) {
int32 t;
for (t = LUA_T_NIL; t <= LUA_T_USERDATA; t++)
if (validevent(t, e))
*luaT_getim(t, e) = *func;
}
static luaL_reg tmFB[] = {
{" typeFB", typeFB},
{" errorFB", errorFB},
{" nilFB", nilFB}
};
void luaT_setfallback() {
static const char *oldnames [] = { "error", "getglobal", "arith", "order", nullptr };
TObject oldfunc;
lua_CFunction replace;
if (!tmFBAdded) {
luaL_addlibtolist(tmFB, (sizeof(tmFB) / sizeof(tmFB[0])));
tmFBAdded = true;
}
const char *name = luaL_check_string(1);
lua_Object func = lua_getparam(2);
luaL_arg_check(lua_isfunction(func), 2, "function expected");
switch (luaO_findstring(name, oldnames)) {
case 0: // old error fallback
oldfunc = errorim;
errorim = *luaA_Address(func);
replace = errorFB;
break;
case 1: // old getglobal fallback
oldfunc = *luaT_getim(LUA_T_NIL, IM_GETGLOBAL);
*luaT_getim(LUA_T_NIL, IM_GETGLOBAL) = *luaA_Address(func);
replace = nilFB;
break;
case 2:
{ // old arith fallback
int32 i;
oldfunc = *luaT_getim(LUA_T_NUMBER, IM_POW);
for (i = IM_ADD; i <= IM_UNM; i++) // ORDER IM
fillvalids(i, luaA_Address(func));
replace = typeFB;
break;
}
case 3:
{ // old order fallback
int32 i;
oldfunc = *luaT_getim(LUA_T_NIL, IM_LT);
for (i = IM_LT; i <= IM_GE; i++) // ORDER IM
fillvalids(i, luaA_Address(func));
replace = typeFB;
break;
}
default:
{
int32 e;
if ((e = luaO_findstring(name, luaT_eventname)) >= 0) {
oldfunc = *luaT_getim(LUA_T_NIL, e);
fillvalids(e, luaA_Address(func));
replace = (e == IM_GC || e == IM_INDEX) ? nilFB : typeFB;
} else {
luaL_verror("`%.50s' is not a valid fallback name", name);
replace = nullptr; // to avoid warnings
oldfunc.ttype = LUA_T_NIL; // to avoid warnings
}
}
}
if (oldfunc.ttype != LUA_T_NIL)
luaA_pushobject(&oldfunc);
else
lua_pushcfunction(replace);
}
#endif
} // end of namespace Grim