#include "stdafx.h" CMLuaVariablesLoader::CMLuaVariablesLoader(lua_State *L) : L(L) { } /***********************************************/ static int mlua__and(lua_State *L) { int nargs = lua_gettop(L); if (nargs < 1) luaL_error(L, "bad count of arguments"); for (int i = 1; i <= nargs; i++) { bool res = luaM_toboolean(L, i); if (res == false) { lua_pushboolean(L, 0); return 1; } } lua_pushboolean(L, 1); return 1; } static int mlua__equal(lua_State *L) { int nargs = lua_gettop(L); if (nargs != 2) luaL_error(L, "bad count of arguments"); int x = atoi(luaL_checkstring(L, 1)); int y = atoi(luaL_checkstring(L, 2)); lua_pushboolean(L, x == y); return 1; } static int mlua__if(lua_State *L) { int nargs = lua_gettop(L); if (nargs != 3) luaL_error(L, "bad count of arguments"); int x = luaM_toboolean(L, 1); const char *res = x ? luaL_checkstring(L, 2) : luaL_checkstring(L, 3); lua_pushstring(L, res); return 1; } /***********************************************/ static int mlua__add(lua_State *L) { int nargs = lua_gettop(L); if (nargs < 1) luaL_error(L, "bad count of arguments"); int res = 0; for (int i = 1; i <= nargs; i++) res += luaL_checkinteger(L, i); lua_pushfstring(L, "%d", res); return 1; } static int mlua__div(lua_State *L) { int nargs = lua_gettop(L); if (nargs != 2) luaL_error(L, "bad count of arguments"); int x = luaL_checkinteger(L, 1); int y = luaL_checkinteger(L, 2); lua_pushfstring(L, "%d", x - y); return 1; } static int mlua__hex(lua_State *L) { int nargs = lua_gettop(L); if (nargs != 2) luaL_error(L, "bad count of arguments"); int x = luaL_checkinteger(L, 1); int pad = luaL_checkinteger(L, 2); CMStringA format(FORMAT, "0x%%0%dx", pad); CMStringA value(FORMAT, format, x); lua_pushstring(L, value); return 1; } static int mlua__max(lua_State *L) { int nargs = lua_gettop(L); if (nargs < 1) luaL_error(L, "bad count of arguments"); int res = 0; for (int i = 1; i <= nargs; i++) { int val = luaL_optinteger(L, i, INT_MIN); if (val > res) res = val; } lua_pushfstring(L, "%d", res); return 1; } static int mlua__min(lua_State *L) { int nargs = lua_gettop(L); if (nargs < 1) luaL_error(L, "bad count of arguments"); int res = 0; for (int i = 1; i <= nargs; i++) { int val = luaL_optinteger(L, i, INT_MAX); if (val < res) res = val; } lua_pushfstring(L, "%d", res); return 1; } static int mlua__mod(lua_State *L) { int nargs = lua_gettop(L); if (nargs != 2) luaL_error(L, "bad count of arguments"); int x = luaL_checkinteger(L, 1); int y = luaL_checkinteger(L, 2); lua_pushfstring(L, "%d", x % y); return 1; } static int mlua__mul(lua_State *L) { int nargs = lua_gettop(L); if (nargs != 2) luaL_error(L, "bad count of arguments"); int x = luaL_checkinteger(L, 1); int y = luaL_checkinteger(L, 2); lua_pushfstring(L, "%d", x * y); return 1; } static int mlua__muldiv(lua_State *L) { int nargs = lua_gettop(L); if (nargs != 3) luaL_error(L, "bad count of arguments"); int x = luaL_checkinteger(L, 1); int y = luaL_checkinteger(L, 2); int z = luaL_checkinteger(L, 3); lua_pushfstring(L, "%d", (x * y) / z); return 1; } static int mlua__num(lua_State *L) { int nargs = lua_gettop(L); if (nargs != 2) luaL_error(L, "bad count of arguments"); int x = luaL_checkinteger(L, 1); int pad = luaL_checkinteger(L, 2); CMStringA format(FORMAT, "%%0%dx", pad); CMStringA value(FORMAT, format, x); lua_pushstring(L, value); return 1; } static int mlua__rand(lua_State *L) { lua_pushfstring(L, "%d", rand()); return 1; } static luaL_Reg varsApi[] = { // logic { "_vand", mlua__and }, { "_vequal", mlua__equal }, { "_vif", mlua__if }, // math { "_vadd", mlua__add }, { "_vdiv", mlua__div }, { "_vhex", mlua__hex }, { "_vmax", mlua__max }, { "_vmin", mlua__min }, { "_vmod", mlua__mod }, { "_vmul", mlua__mul }, { "_vmuldiv", mlua__muldiv }, { "_vnum", mlua__num }, { "_vrand", mlua__rand }, { nullptr, nullptr } }; static wchar_t* translate(lua_State *L, const wchar_t *format, const wchar_t* /*extra*/, MCONTACT /*hContact*/ = NULL) { // this should quote string params but is not work yet std::wregex regex(L"(?<=\\(|,)`?([^0-9][a-z_0-9 ]+)`?(?=,|\\))"); std::wstring query = std::regex_replace(format, regex, L"'$1'"); regex = L"\\?([a-z_0-9]+)\\("; query = std::regex_replace(query, regex, L"_v$1("); query.insert(0, L"return "); wchar_t *result = nullptr; CMLuaEnvironment env(L); if (env.Eval(query.c_str()) == LUA_OK) result = mir_utf8decodeW(lua_tostring(L, -1)); else result = mir_wstrdup(format); lua_pop(L, 1); env.Unload(); return result; } static int mlua_vars(lua_State *L) { ptrW format(mir_utf8decodeW(lua_tostring(L, 1))); ptrW extra(mir_utf8decodeW(lua_tostring(L, 2))); MCONTACT hContact = lua_tointeger(L, 3); ptrW result(translate(L, format, extra, hContact)); lua_pushstring(L, T2Utf(result)); return 1; } /***********************************************/ static INT_PTR FormatString(void *obj, WPARAM wParam, LPARAM) { lua_State *L = (lua_State*)obj; FORMATINFO *fi = (FORMATINFO*)wParam; ptrW result; if ((fi->flags & FIF_UNICODE) == 0) { _A2T format(fi->szFormat.a); _A2T extra(fi->szExtraText.a); result = translate(L, format, extra, fi->hContact); } else result = translate(L, fi->szFormat.w, fi->szExtraText.w, fi->hContact); lua_pushstring(L, T2Utf(result)); return (INT_PTR)result.detach(); } static int CompareTokens(const TOKENREGISTER *p1, const TOKENREGISTER *p2) { return mir_wstrcmpi(p1->szTokenString.w, p2->szTokenString.w); } LIST tokens(10, CompareTokens); static INT_PTR RegisterToken(void*, WPARAM, LPARAM lParam) { // lua_State *L = (lua_State*)obj; TOKENREGISTER *tr = (TOKENREGISTER*)lParam; if (tr == nullptr || tr->szTokenString.w == nullptr || tr->cbSize <= 0) return -1; } /***********************************************/ void CMLuaVariablesLoader::LoadVariables() { if (ServiceExists(MS_VARS_FORMATSTRING)) return; //CreateServiceFunctionObj(MS_VARS_FORMATSTRING, FormatString, L); //CreateServiceFunctionObj(MS_VARS_REGISTERTOKEN, RegisterToken, L); Log("Loading variables functions"); lua_register(L, "vars", mlua_vars); lua_pushglobaltable(L); luaL_setfuncs(L, varsApi, 0); } void CMLuaVariablesLoader::Load(lua_State *L) { CMLuaVariablesLoader loader(L); loader.LoadVariables(); }