mirror of
https://github.com/libretro/scummvm.git
synced 2025-04-09 10:11:23 +00:00
259 lines
6.3 KiB
C++
259 lines
6.3 KiB
C++
/*
|
|
** Global State
|
|
** See Copyright Notice in lua.h
|
|
*/
|
|
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_setjmp
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_longjmp
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_stdin
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_stdout
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_stderror
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_fprintf
|
|
#define FORBIDDEN_SYMBOL_EXCEPTION_FILE
|
|
|
|
#include "common/endian.h"
|
|
|
|
#include "engines/grim/debug.h"
|
|
#include "engines/grim/actor.h"
|
|
#include "engines/grim/color.h"
|
|
|
|
#include "engines/grim/lua/lbuiltin.h"
|
|
#include "engines/grim/lua/ldo.h"
|
|
#include "engines/grim/lua/lauxlib.h"
|
|
#include "engines/grim/lua/lfunc.h"
|
|
#include "engines/grim/lua/lgc.h"
|
|
#include "engines/grim/lua/llex.h"
|
|
#include "engines/grim/lua/lmem.h"
|
|
#include "engines/grim/lua/lstate.h"
|
|
#include "engines/grim/lua/lstring.h"
|
|
#include "engines/grim/lua/ltable.h"
|
|
#include "engines/grim/lua/ltask.h"
|
|
#include "engines/grim/lua/ltm.h"
|
|
#include "engines/grim/lua/lualib.h"
|
|
#include "engines/grim/lua/luadebug.h"
|
|
|
|
namespace Grim {
|
|
|
|
GCnode rootproto;
|
|
GCnode rootcl;
|
|
GCnode rootglobal;
|
|
GCnode roottable;
|
|
struct ref *refArray;
|
|
int32 refSize;
|
|
int32 GCthreshold;
|
|
int32 nblocks;
|
|
int32 Mbuffsize;
|
|
int32 Mbuffnext;
|
|
char *Mbuffbase;
|
|
char *Mbuffer;
|
|
TObject errorim;
|
|
stringtable *string_root;
|
|
int32 last_tag;
|
|
struct IM *IMtable;
|
|
int32 IMtable_size;
|
|
|
|
LState *lua_state = nullptr;
|
|
LState *lua_rootState = nullptr;
|
|
|
|
int globalTaskSerialId = 0;
|
|
|
|
void stderrorim();
|
|
|
|
static luaL_reg stdErrorRimFunc[] = {
|
|
{ "stderrorim", stderrorim }
|
|
};
|
|
|
|
static void lua_openthr() {
|
|
Mbuffsize = 0;
|
|
Mbuffnext = 0;
|
|
Mbuffbase = nullptr;
|
|
Mbuffer = nullptr;
|
|
}
|
|
|
|
#define STACK_UNIT 256
|
|
|
|
void lua_stateinit(LState *state) {
|
|
state->prev = nullptr;
|
|
state->next = nullptr;
|
|
state->all_paused = 0;
|
|
state->paused = false;
|
|
state->preventBreakCounter = 0;
|
|
state->callLevelCounter = 0;
|
|
state->updated = false;
|
|
|
|
state->numCblocks = 0;
|
|
state->Cstack.base = 0;
|
|
state->Cstack.lua2C = 0;
|
|
state->Cstack.num = 0;
|
|
state->errorJmp = nullptr;
|
|
state->id = globalTaskSerialId++;
|
|
state->task = nullptr;
|
|
state->prevTask = nullptr;
|
|
state->taskFunc.ttype = LUA_T_NIL;
|
|
state->sleepFor = 0;
|
|
|
|
state->stack.stack = luaM_newvector(STACK_UNIT, TObject);
|
|
state->stack.top = state->stack.stack;
|
|
state->stack.last = state->stack.stack + (STACK_UNIT - 1);
|
|
}
|
|
|
|
void lua_statedeinit(LState *state) {
|
|
if (state->prev)
|
|
state->prev->next = state->next;
|
|
if (state->next)
|
|
state->next->prev = state->prev;
|
|
state->next = nullptr;
|
|
state->prev = nullptr;
|
|
|
|
if (state->task) {
|
|
lua_Task *t, *m;
|
|
for (t = state->task; t != nullptr;) {
|
|
m = t->next;
|
|
luaM_free(t);
|
|
t = m;
|
|
}
|
|
}
|
|
|
|
free(state->stack.stack);
|
|
}
|
|
|
|
void lua_resetglobals() {
|
|
lua_openthr();
|
|
|
|
rootproto.next = nullptr;
|
|
rootproto.marked = 0;
|
|
rootcl.next = nullptr;
|
|
rootcl.marked = 0;
|
|
rootglobal.next = nullptr;
|
|
rootglobal.marked = 0;
|
|
roottable.next = nullptr;
|
|
roottable.marked = 0;
|
|
refArray = nullptr;
|
|
refSize = 0;
|
|
GCthreshold = GARBAGE_BLOCK;
|
|
nblocks = 0;
|
|
|
|
luaD_init();
|
|
luaS_init();
|
|
luaX_init();
|
|
}
|
|
|
|
void callHook(lua_Function func, const char *filename, int32 line) {
|
|
const char *name, *type;
|
|
FILE *output = stdout;
|
|
int i;
|
|
|
|
for (i = 0; i < lua_state->callLevelCounter; i++) {
|
|
fprintf(output, " ");
|
|
}
|
|
fprintf(output, "id: %d ", lua_state->id);
|
|
type = lua_getobjname(func, &name);
|
|
if (func == LUA_NOOBJECT) {
|
|
fprintf(output, "<< %s\n", filename);
|
|
return;
|
|
} else {
|
|
fprintf(output, ">> %s ", filename);
|
|
}
|
|
|
|
switch (*type) {
|
|
case 'g':
|
|
fprintf(output, "function: %s(", name);
|
|
for (i = 1; ; i++) {
|
|
if (lua_getparam(i) == LUA_NOOBJECT)
|
|
break;
|
|
if (lua_isnil(lua_getparam(i)))
|
|
fprintf(output, "nil");
|
|
else if (lua_istable(lua_getparam(i)))
|
|
fprintf(output, "{...}");
|
|
else if (lua_isuserdata(lua_getparam(i))) {
|
|
if (lua_tag(lua_getparam(i)) == MKTAG('A','C','T','R')) {
|
|
Actor *a = Actor::getPool().getObject(lua_getuserdata(lua_getparam(i)));
|
|
fprintf(output, "<actor \"%s\">", a->getName().c_str());
|
|
} else if (lua_tag(lua_getparam(i)) == MKTAG('C','O','L','R')) {
|
|
Color c(lua_getuserdata(lua_getparam(i)));
|
|
fprintf(output, "<color #%02x%02x%02x>", c.getRed(), c.getGreen(), c.getBlue());
|
|
} else
|
|
fprintf(output, "<userdata %d>", lua_getuserdata(lua_getparam(i)));
|
|
} else if (lua_isfunction(lua_getparam(i))) {
|
|
lua_getobjname(lua_getparam(i), &name);
|
|
fprintf(output, "<function %s>", name);
|
|
} else if (lua_isnumber(lua_getparam(i)))
|
|
fprintf(output, "%g", lua_getnumber(lua_getparam(i)));
|
|
else if (lua_isstring(lua_getparam(i)))
|
|
fprintf(output, "\"%s\"", lua_getstring(lua_getparam(i)));
|
|
else
|
|
fprintf(output, "<unknown>");
|
|
if (lua_getparam(i + 1) != LUA_NOOBJECT)
|
|
fprintf(output, ", ");
|
|
}
|
|
fprintf(output, ")");
|
|
break;
|
|
case 't':
|
|
fprintf(output, "`%s' tag method", name);
|
|
break;
|
|
default:
|
|
{
|
|
if (line == 0)
|
|
fprintf(output, "{START SCRIPT: %s}", filename);
|
|
else if (line < 0) {
|
|
fprintf(output, "Unknown %s", filename);
|
|
} else
|
|
fprintf(output, "function (%s:%d)", filename, line);
|
|
}
|
|
}
|
|
fprintf(output, "\n");
|
|
}
|
|
|
|
void lua_open() {
|
|
if (lua_state)
|
|
return;
|
|
lua_rootState = lua_state = luaM_new(LState);
|
|
lua_stateinit(lua_state);
|
|
lua_resetglobals();
|
|
luaT_init();
|
|
luaB_predefine();
|
|
luaL_addlibtolist(stdErrorRimFunc, (sizeof(stdErrorRimFunc) / sizeof(stdErrorRimFunc[0])));
|
|
if (Debug::isChannelEnabled(Debug::Lua))
|
|
lua_callhook = callHook;
|
|
}
|
|
|
|
void lua_close() {
|
|
TaggedString *alludata = luaS_collectudata();
|
|
GCthreshold = MAX_INT; // to avoid GC during GC
|
|
luaC_hashcallIM((Hash *)roottable.next); // GC t.methods for tables
|
|
luaC_strcallIM(alludata); // GC tag methods for userdata
|
|
luaD_gcIM(&luaO_nilobject); // GC tag method for nil (signal end of GC)
|
|
luaH_free((Hash *)roottable.next);
|
|
luaF_freeproto((TProtoFunc *)rootproto.next);
|
|
luaF_freeclosure((Closure *)rootcl.next);
|
|
luaS_free(alludata);
|
|
luaS_freeall();
|
|
luaM_free(IMtable);
|
|
luaM_free(refArray);
|
|
luaM_free(Mbuffer);
|
|
|
|
LState *tmpState, *state;
|
|
for (state = lua_rootState; state != nullptr;) {
|
|
tmpState = state->next;
|
|
lua_statedeinit(state);
|
|
luaM_free(state);
|
|
state = tmpState;
|
|
}
|
|
|
|
Mbuffer = nullptr;
|
|
IMtable = nullptr;
|
|
refArray = nullptr;
|
|
lua_rootState = lua_state = nullptr;
|
|
|
|
#ifdef LUA_DEBUG
|
|
printf("total de blocos: %ld\n", numblocks);
|
|
printf("total de memoria: %ld\n", totalmem);
|
|
#endif
|
|
}
|
|
|
|
bool lua_isopen() {
|
|
return (lua_rootState);
|
|
}
|
|
|
|
} // end of namespace Grim
|