summaryrefslogtreecommitdiff
path: root/plugins/MirLua/src/mlua.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/MirLua/src/mlua.cpp')
-rw-r--r--plugins/MirLua/src/mlua.cpp183
1 files changed, 175 insertions, 8 deletions
diff --git a/plugins/MirLua/src/mlua.cpp b/plugins/MirLua/src/mlua.cpp
index 156e957a02..d3c835ee7d 100644
--- a/plugins/MirLua/src/mlua.cpp
+++ b/plugins/MirLua/src/mlua.cpp
@@ -21,6 +21,173 @@ CMLua::~CMLua()
Unload();
}
+/***********************************************/
+
+static int mlua_print(lua_State *L)
+{
+ CMStringA data;
+ int nargs = lua_gettop(L);
+ for (int i = 1; i <= nargs; i++)
+ {
+ switch (lua_type(L, i))
+ {
+ case LUA_TNIL:
+ data.Append("nil");
+ break;
+ case LUA_TBOOLEAN:
+ data.AppendFormat("%s", lua_toboolean(L, i) ? "true" : "false");
+ break;
+ case LUA_TNUMBER:
+ case LUA_TSTRING:
+ data.AppendFormat("%s", lua_tostring(L, i));
+ break;
+ default:
+ data.AppendFormat("%s(0x%p)", luaL_typename(L, i), lua_topointer(L, i));
+ break;
+ }
+ data.Append(", ");
+ }
+ if (data.GetLength() >= 1)
+ data.Delete(data.GetLength() - 2, 2);
+
+ Log(data.GetBuffer());
+
+ return 0;
+}
+
+static int mlua_toansi(lua_State *L)
+{
+ const char *value = luaL_checkstring(L, 1);
+ int codepage = luaL_optinteger(L, 2, Langpack_GetDefaultCodePage());
+
+ ptrA string(mir_strdup(value));
+ lua_pushstring(L, mir_utf8decodecp(string, codepage, NULL));
+
+ return 1;
+}
+
+static int mlua_toucs2(lua_State *L)
+{
+ const char *value = luaL_checkstring(L, 1);
+
+ ptrW unicode(mir_utf8decodeW(value));
+ size_t length = mir_wstrlen(unicode) * sizeof(wchar_t);
+
+ ptrA string((char*)mir_calloc(length + 1));
+ memcpy(string, unicode, length);
+
+ lua_pushlstring(L, string, length + 1);
+
+ return 1;
+}
+
+static int mlua_topointer(lua_State *L)
+{
+ switch (lua_type(L, 1))
+ {
+ case LUA_TBOOLEAN:
+ lua_pushlightuserdata(L, (void*)lua_toboolean(L, 1));
+ break;
+ case LUA_TNUMBER:
+ if (lua_isinteger(L, 1))
+ {
+ lua_Integer value = lua_tointeger(L, 1);
+ if (value > INTPTR_MAX)
+ {
+ const char *msg = lua_pushfstring(L, "%f is larger than %d", value, INTPTR_MAX);
+ return luaL_argerror(L, 1, msg);
+ }
+ lua_pushlightuserdata(L, (void*)value);
+ }
+ break;
+ case LUA_TSTRING:
+ lua_pushlightuserdata(L, (void*)lua_tostring(L, 1));
+ break;
+ case LUA_TLIGHTUSERDATA:
+ lua_pushvalue(L, 1);
+ default:
+ return luaL_argerror(L, 1, luaL_typename(L, 1));
+ }
+
+ return 1;
+}
+
+static int mlua_tonumber(lua_State *L)
+{
+ if (lua_islightuserdata(L, 1))
+ {
+ lua_Integer value = (lua_Integer)lua_touserdata(L, 1);
+ lua_pushinteger(L, value);
+ return 1;
+ }
+
+ int n = lua_gettop(L);
+ lua_pushvalue(L, lua_upvalueindex(1));
+ lua_pushvalue(L, 1);
+ if (n == 2)
+ lua_pushvalue(L, 2);
+ luaM_pcall(L, n, 1);
+
+ return 1;
+}
+
+static int mlua_interpolate(lua_State *L)
+{
+ const char *string = luaL_checkstring(L, 1);
+
+ char pattern[128];
+
+ if (lua_istable(L, 2))
+ {
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 2))
+ {
+ lua_pushvalue(L, -2);
+ const char *key = lua_tostring(L, -1);
+ const char *val = lua_tostring(L, -2);
+
+ mir_snprintf(pattern, "{%s}", key);
+ string = luaL_gsub(L, string, pattern, val);
+ lua_pop(L, 1);
+ }
+ }
+ else
+ {
+ int nargs = lua_gettop(L);
+ for (int i = 2; i <= nargs; i++)
+ {
+ const char *val = lua_tostring(L, i);
+
+ mir_snprintf(pattern, "{%d}", i - 1);
+ string = luaL_gsub(L, string, pattern, val);
+ lua_pop(L, 1);
+ }
+ }
+
+ lua_Debug ar;
+
+ size_t level = 1;
+
+ while (lua_getstack(L, level++, &ar))
+ {
+ size_t i = 1;
+ while (const char *name = lua_getlocal(L, &ar, i++))
+ {
+ const char *val = lua_tostring(L, -1);
+ if (val)
+ {
+ mir_snprintf(pattern, "${%s}", name);
+ string = luaL_gsub(L, string, pattern, val);
+ lua_pop(L, 1);
+ }
+ }
+ }
+ lua_pushstring(L, string);
+
+ return 1;
+}
+
+/***********************************************/
+
void CMLua::SetPaths()
{
wchar_t path[MAX_PATH];
@@ -47,23 +214,23 @@ void CMLua::Load()
SetPaths();
- lua_register(L, "print", luaM_print);
- lua_register(L, "a", luaM_toansi);
- lua_register(L, "u", luaM_toucs2);
- lua_register(L, "topointer", luaM_topointer);
+ lua_register(L, "print", mlua_print);
+ lua_register(L, "a", mlua_toansi);
+ lua_register(L, "u", mlua_toucs2);
+ lua_register(L, "topointer", mlua_topointer);
lua_getglobal(L, "tonumber");
- lua_setglobal(L, "_tonumber");
- lua_register(L, "tonumber", luaM_tonumber);
+ lua_pushcclosure(L, mlua_tonumber, 1);
+ lua_setglobal(L, "tonumber");
lua_pushstring(L, "");
lua_getmetatable(L, -1);
lua_pushstring(L, "__mod");
- lua_pushcfunction(L, luaM_interpolate);
+ lua_pushcfunction(L, mlua_interpolate);
lua_rawset(L, -3);
lua_pushstring(L, "__index");
lua_rawget(L, -2);
- lua_pushcfunction(L, luaM_interpolate);
+ lua_pushcfunction(L, mlua_interpolate);
lua_setfield(L, -2, "interpolate");
lua_pop(L, 3);