/
e-face
/
SuperPuperTerminal
Обзор
Документация
Войти
/
e-face
/
SuperPuperTerminal
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/script.cpp
706 строк
18 KB
e-face
First one
14 фев 2026, 19:38
14 фев 2026, 19:38
87f499b
Код
Авторство
О чём код?
#include "script.h" extern "C" { #include <lua-5.2.3/src/lua.h> #include <lua-5.2.3/src/lauxlib.h> #include <lua-5.2.3/src/lualib.h> #include <lua-5.2.3/src/lobject.h> #include <lua-5.2.3/src/lstate.h> #include <lua-5.2.3/src/lgc.h> } //--------------------------------------------------------- //--------------------------------------------------------- //--------------------------------------------------------- int argCount(lua_State *l) { return lua_gettop(l); } //------------------------------------------------------ void pushResult(lua_State* l, const QString& v) { lua_pushstring(l, v.toUtf8().data()); } //------------------------------------------------------ void pushResult(lua_State *l, int v) { lua_pushinteger(l, v); } //------------------------------------------------------ void pushResult(lua_State *l, uint v) { lua_pushunsigned(l, v); } //------------------------------------------------------ void pushResult(lua_State *l, float v) { lua_pushnumber(l, v); } //------------------------------------------------------ void pushResult(lua_State *l, double v) { lua_pushnumber(l, v); } //------------------------------------------------------ void pushResult(lua_State *l, bool v) { lua_pushboolean(l, v); } //------------------------------------------------------ int &popArg(lua_State *l, int num, int &v) { return v = lua_tointeger(l, num); } //------------------------------------------------------ uint &popArg(lua_State *l, int num, uint &v) { return v = lua_tounsigned(l, num); } //------------------------------------------------------ QString &popArg(lua_State *l, int num, QString &v) { return v = lua_tostring(l, num); } //------------------------------------------------------ double &popArg(lua_State *l, int num, double &v) { return v = lua_tonumber(l, num); } //------------------------------------------------------ float &popArg(lua_State* l, int num, float& v) { return v = lua_tonumber(l, num); } //------------------------------------------------------ bool &popArg(lua_State *l, int num, bool &v) { return v = lua_toboolean(l, num); } //--------------------------------------------------------- #define TO_PROXY_FUNC(name) name##Proxy //--------------------------------------------------------- //--------------------------------------------------------- //--------------------------------------------------------- struct LuaProxyFuncInfo { QString name; lua_CFunction func; static QList<LuaProxyFuncInfo>& list() { static QList<LuaProxyFuncInfo> info; return info; } LuaProxyFuncInfo(const QString& name, lua_CFunction func) { //gDbg() << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" << name.toUtf8(); this->name = name; this->func = func; list().append(*this); this->name.clear(); this->func = 0; } }; //--------------------------------------------------------- //--------------------------------------------------------- //--------------------------------------------------------- static ScriptTarget* mmScriptTarget(0); //--------------------------------------------------------- //--------------------------------------------------------- //--------------------------------------------------------- #define PROXY_0(ret, name) \ template<class T> \ typename std::enable_if<std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 0) return 0; \ mmScriptTarget->name(); \ return 0; \ } \ template<class T> \ typename std::enable_if<!std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 0) \ { \ pushResult(l, T()); \ return 1; \ } \ pushResult(l, (T)mmScriptTarget->name()); \ return 1; \ } \ static LuaProxyFuncInfo name##RegItem( \ #name, TO_PROXY_FUNC(name)<ret>); //--------------------------------------------------------- #define PROXY_1(ret, name, T1) \ template<class T> \ typename std::enable_if<std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 1) return 0; \ T1 t1; \ mmScriptTarget->name(popArg(l, 1, t1)); \ return 0; \ } \ template<class T> \ typename std::enable_if<!std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 1) \ { \ pushResult(l, T()); \ return 1; \ } \ T1 t1; \ pushResult(l, (T)mmScriptTarget->name(popArg(l, 1, t1))); \ return 1; \ } \ static LuaProxyFuncInfo name##RegItem( \ #name, TO_PROXY_FUNC(name)<ret>); //--------------------------------------------------------- #define PROXY_2(ret, name, T1, T2) \ template<class T> \ typename std::enable_if<std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 2) return 0; \ T1 t1; T2 t2; \ mmScriptTarget->name(popArg(l, 1, t1), popArg(l, 2, t2)); \ return 0; \ } \ template<class T> \ typename std::enable_if<!std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 2) \ { \ pushResult(l, T()); \ return 1; \ } \ T1 t1; T2 t2;\ pushResult(l, (T)mmScriptTarget->name(popArg(l, 1, t1), \ popArg(l, 2, t2))); \ return 1; \ } \ static LuaProxyFuncInfo name##RegItem( \ #name, TO_PROXY_FUNC(name)<ret>); //--------------------------------------------------------- #define PROXY_3(ret, name, T1, T2, T3) \ template<class T> \ typename std::enable_if<std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 3) return 0; \ T1 t1; T2 t2; T3 t3; \ mmScriptTarget->name(popArg(l, 1, t1), popArg(l, 2, t2), \ popArg(l, 3, t3)); \ return 0; \ } \ template<class T> \ typename std::enable_if<!std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 3) \ { \ pushResult(l, T()); \ return 1; \ } \ T1 t1; T2 t2; T3 t3; \ pushResult(l, (T)mmScriptTarget->name(popArg(l, 1, t1), \ popArg(l, 2, t2), popArg(l, 3, t3))); \ return 1; \ } \ static LuaProxyFuncInfo name##RegItem( \ #name, TO_PROXY_FUNC(name)<ret>); //--------------------------------------------------------- #define PROXY_4(ret, name, T1, T2, T3, T4) \ template<class T> \ typename std::enable_if<std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 4) return 0; \ T1 t1; T2 t2; T3 t3; \ T4 t4; \ mmScriptTarget->name(popArg(l, 1, t1), popArg(l, 2, t2), \ popArg(l, 3, t3), popArg(l, 4, t4)); \ return 0; \ } \ template<class T> \ typename std::enable_if<!std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 4) \ { \ pushResult(l, T()); \ return 1; \ } \ T1 t1; T2 t2; T3 t3; \ T4 t4; \ pushResult(l, (T)mmScriptTarget->name(popArg(l, 1, t1), \ popArg(l, 2, t2), popArg(l, 3, t3), \ popArg(l, 4, t4))); \ return 1; \ } \ static LuaProxyFuncInfo name##RegItem( \ #name, TO_PROXY_FUNC(name)<ret>); //--------------------------------------------------------- #define PROXY_5(ret, name, T1, T2, T3, T4, T5) \ template<class T> \ typename std::enable_if<std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 5) return 0; \ T1 t1; T2 t2; T3 t3; \ T4 t4; T5 t5; \ mmScriptTarget->name(popArg(l, 1, t1), popArg(l, 2, t2), \ popArg(l, 3, t3), popArg(l, 4, t4), \ popArg(l, 5, t5)); \ return 0; \ } \ template<class T> \ typename std::enable_if<!std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 5) \ { \ pushResult(l, T()); \ return 1; \ } \ T1 t1; T2 t2; T3 t3; \ T4 t4; T5 t5; \ pushResult(l, (T)mmScriptTarget->name(popArg(l, 1, t1), \ popArg(l, 2, t2), popArg(l, 3, t3), \ popArg(l, 4, t4), popArg(l, 5, t5))); \ return 1; \ } \ static LuaProxyFuncInfo name##RegItem( \ #name, TO_PROXY_FUNC(name)<ret>); //--------------------------------------------------------- #define PROXY_6(ret, name, T1, T2, T3, T4, T5, T6) \ template<class T> \ typename std::enable_if<std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 6) return 0; \ T1 t1; T2 t2; T3 t3; \ T4 t4; T5 t5; T6 t6; \ mmScriptTarget->name(popArg(l, 1, t1), popArg(l, 2, t2), \ popArg(l, 3, t3), popArg(l, 4, t4), \ popArg(l, 5, t5), popArg(l, 6, t6)); \ return 0; \ } \ template<class T> \ typename std::enable_if<!std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 6) \ { \ pushResult(l, T()); \ return 1; \ } \ T1 t1; T2 t2; T3 t3; \ T4 t4; T5 t5; T6 t6; \ pushResult(l, (T)mmScriptTarget->name(popArg(l, 1, t1), \ popArg(l, 2, t2), popArg(l, 3, t3), \ popArg(l, 4, t4), popArg(l, 5, t5), \ popArg(l, 6, t6))); \ return 1; \ } \ static LuaProxyFuncInfo name##RegItem( \ #name, TO_PROXY_FUNC(name)<ret>); //--------------------------------------------------------- #define PROXY_7(ret, name, T1, T2, T3, T4, T5, T6, T7) \ template<class T> \ typename std::enable_if<std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 7) return 0; \ T1 t1; T2 t2; T3 t3; \ T4 t4; T5 t5; T6 t6; T7 t7; \ mmScriptTarget->name(popArg(l, 1, t1), popArg(l, 2, t2), \ popArg(l, 3, t3), popArg(l, 4, t4), \ popArg(l, 5, t5), popArg(l, 6, t6), \ popArg(l, 7, t7)); \ return 0; \ } \ template<class T> \ typename std::enable_if<!std::is_same<T, void>::value, int>::type \ TO_PROXY_FUNC(name)(lua_State* l) \ { \ if (argCount(l) != 7) \ { \ pushResult(l, T()); \ return 1; \ } \ T1 t1; T2 t2; T3 t3; \ T4 t4; T5 t5; T6 t6; T7 t7; \ pushResult(l, (T)mmScriptTarget->name(popArg(l, 1, t1), \ popArg(l, 2, t2), popArg(l, 3, t3), \ popArg(l, 4, t4), popArg(l, 5, t5), \ popArg(l, 6, t6), popArg(l, 7, t7))); \ return 1; \ } \ static LuaProxyFuncInfo name##RegItem( \ #name, TO_PROXY_FUNC(name)<ret>); //--------------------------------------------------------- //--------------------------------------------------------- //--------------------------------------------------------- Script::Script(const QString& name) { clear(); _name = name; } //--------------------------------------------------------- Script::~Script() { clear(); } //--------------------------------------------------------- const QString &Script::name() const { return _name; } //--------------------------------------------------------- void Script::clear() { _data.clear(); resetCaret(); } //--------------------------------------------------------- void Script::resetCaret() { _caret = 0; } //--------------------------------------------------------- bool Script::endOfData() const { return _caret == (int)_data.count(); } //--------------------------------------------------------- const char* Script::data() const { return _data.begin(); } //--------------------------------------------------------- int Script::size() const { return _data.count(); } //--------------------------------------------------------- bool Script::read(char** data, int* size) { if (endOfData()) return false; *data = _data.begin(); *size = _data.count(); _caret = _data.count(); return true; } //--------------------------------------------------------- void Script::write(const char* data, int size) { QByteArray temp(_data); _data = QByteArray(temp.count() + size, 0); memcpy(_data.begin() + 0, temp.begin(), temp.count()); memcpy(_data.begin() + temp.count(), (const void*)data, size); _caret = _data.count(); } //--------------------------------------------------------- //--------------------------------------------------------- //--------------------------------------------------------- ScriptEngine::ScriptEngine(const ScriptEngine &other) { *this = other; } //--------------------------------------------------------- ScriptEngine &ScriptEngine::operator =(const ScriptEngine &other) { Q_UNUSED(other); return *this; } //--------------------------------------------------------- static QString mmScriptPreamble /*= "function stopww() goto ___end_034002453334_of_prg end\n"*/; static QString mmScriptPostamble /*= "\n\n::___end_034002453334_of_prg::\n\n"*/; #define MM_ADD_ENUM_VALUE(name, value) \ { \ char p[34]; \ ltoa((int)value, p, 10); \ mmScriptPreamble += QString(name) + \ " = " + (const char*)p + " \n"; \ } //--------------------------------------------------------- QByteArray ScriptEngine::_preproc(const QString &script) const { if (script.count() > 4 && script[0] == '#' && script[1] == 'e' && script[2] == 'x' && script[3] == 't') { } return (mmScriptPreamble + script + mmScriptPostamble).toUtf8(); } //--------------------------------------------------------- //--------------------------------------------------------- //--------------------------------------------------------- REGISTRATE_SCRIPT_FUNCTIONS //--------------------------------------------------------- //--------------------------------------------------------- //--------------------------------------------------------- ScriptEngine::ScriptEngine() { _vm = luaL_newstate(); luaL_openlibs(_vm); installTarget(0); for (auto it = LuaProxyFuncInfo::list().begin(); it != LuaProxyFuncInfo::list().end(); ++it) { lua_register(_vm, (*it).name.toUtf8(), (*it).func); } REGISTRATE_SCRIPT_ENUMVALUES } //--------------------------------------------------------- ScriptEngine::~ScriptEngine() { if (_vm) lua_close(_vm); } //--------------------------------------------------------- int mmDumpWriter(lua_State *L, const void* p, size_t sz, void* data) { Q_UNUSED(L); Script* s = (Script*)data; s->write((const char*)p, sz); return 0; } //--------------------------------------------------------- bool ScriptEngine::compile(Script& out, const QString& script) { out.clear(); int result = luaL_loadstring(_vm, _preproc(script)); switch(result) { case LUA_ERRSYNTAX: { //aLog(ll tr("Script call: Syntax error") + checkErrors()); } return false; case LUA_ERRMEM: { //log(tr("Script call: memory allocation error") + checkErrors()); } return false; default: break; } result = lua_dump(_vm, mmDumpWriter, (void*)&out); return result == 0; } //--------------------------------------------------------- void ScriptEngine::installTarget(ScriptTarget* target) { if (target) { _target = target; } else { _target = &_defaultTarget; } mmScriptTarget = &_defaultTarget; } //--------------------------------------------------------- const char* mmDumpReader(lua_State *L, void *data, size_t *size) { Q_UNUSED(L); Script* s = (Script*)data; if (s->endOfData()) return 0; int rsize = 0; char* rdata = 0; if (!s->read(&rdata, &rsize)) return 0; *size = rsize; return (const char*)rdata; } //--------------------------------------------------------- bool ScriptEngine::execute(Script &script) { mmScriptTarget = _target; script.resetCaret(); int result = lua_load(_vm, mmDumpReader, (void*)&script, script.name().toLatin1(), 0); switch(result) { case LUA_ERRSYNTAX: { mmScriptTarget = &_defaultTarget; //aLog(ll tr("Script call: Syntax error") + checkErrors()); } return false; case LUA_ERRMEM: { mmScriptTarget = &_defaultTarget; //log(tr("Script call: memory allocation error") + checkErrors()); } return false; default: break; } result = lua_pcall(_vm, 0, LUA_MULTRET, 0); switch(result) { case LUA_ERRRUN: { mmScriptTarget = &_defaultTarget; //log(tr("Script call: runtime error") + checkErrors()); } return false; case LUA_ERRMEM: { mmScriptTarget = &_defaultTarget; //log(tr("Script call: memory allocation error") + checkErrors()); } return false; case LUA_ERRERR: { mmScriptTarget = &_defaultTarget; //log(tr("Script call: error while running the message handler") + checkErrors()); } return false; case LUA_ERRGCMM: { mmScriptTarget = &_defaultTarget; //log(tr("Script call: error while running a __gc metamethod") + checkErrors()); } return false; default:; //log(tr("Script call: unknown error") + checkErrors()); } mmScriptTarget = &_defaultTarget; return true; } //--------------------------------------------------------- bool ScriptEngine::execute(const QString& script) { mmScriptTarget = _target; int result = luaL_loadstring(_vm, _preproc(script)); switch(result) { case LUA_ERRSYNTAX: { mmScriptTarget = &_defaultTarget; //aLog(ll tr("Script call: Syntax error") + checkErrors()); } return false; case LUA_ERRMEM: { mmScriptTarget = &_defaultTarget; //log(tr("Script call: memory allocation error") + checkErrors()); } return false; default: break; } result = lua_pcall(_vm, 0, LUA_MULTRET, 0); switch(result) { case LUA_ERRRUN: { mmScriptTarget = &_defaultTarget; //log(tr("Script call: runtime error") + checkErrors()); } return false; case LUA_ERRMEM: { mmScriptTarget = &_defaultTarget; //log(tr("Script call: memory allocation error") + checkErrors()); } return false; case LUA_ERRERR: { mmScriptTarget = &_defaultTarget; //log(tr("Script call: error while running the message handler") + checkErrors()); } return false; case LUA_ERRGCMM: { mmScriptTarget = &_defaultTarget; //log(tr("Script call: error while running a __gc metamethod") + checkErrors()); } return false; default:; //log(tr("Script call: unknown error") + checkErrors()); } mmScriptTarget = &_defaultTarget; return true; } //---------------------------------------------------------