diff options
author | aunsane <aunsane@gmail.com> | 2018-03-22 01:53:49 +0300 |
---|---|---|
committer | aunsane <aunsane@gmail.com> | 2018-03-22 01:54:09 +0300 |
commit | 2a498d86625f65f6ab308fa20c421099c785bf94 (patch) | |
tree | 9c0d59f41411e46288f88ccdbde4a0d23f440720 /plugins/MirLua | |
parent | 46cded99bbfb90bea8e998e9183c20cc3e4f7365 (diff) |
MirLua: various fixes
- CMLua now inherit PLUGIN
- additional lua fuctions initialization moved to separated loader
- ability to realod script without object recreation
- scropt object should control own enable state
- fix m_json whit is not workes almost at all
- version bump
Diffstat (limited to 'plugins/MirLua')
-rw-r--r-- | plugins/MirLua/src/m_json.cpp | 74 | ||||
-rw-r--r-- | plugins/MirLua/src/m_json.h | 23 | ||||
-rw-r--r-- | plugins/MirLua/src/m_message.cpp | 6 | ||||
-rw-r--r-- | plugins/MirLua/src/m_srmm.cpp | 2 | ||||
-rw-r--r-- | plugins/MirLua/src/main.cpp | 46 | ||||
-rw-r--r-- | plugins/MirLua/src/mlua.cpp | 234 | ||||
-rw-r--r-- | plugins/MirLua/src/mlua.h | 16 | ||||
-rw-r--r-- | plugins/MirLua/src/mlua_function_loader.cpp | 194 | ||||
-rw-r--r-- | plugins/MirLua/src/mlua_function_loader.h | 14 | ||||
-rw-r--r-- | plugins/MirLua/src/mlua_module_loader.cpp | 2 | ||||
-rw-r--r-- | plugins/MirLua/src/mlua_module_loader.h | 5 | ||||
-rw-r--r-- | plugins/MirLua/src/mlua_options.cpp | 78 | ||||
-rw-r--r-- | plugins/MirLua/src/mlua_options.h | 11 | ||||
-rw-r--r-- | plugins/MirLua/src/mlua_script.cpp | 63 | ||||
-rw-r--r-- | plugins/MirLua/src/mlua_script.h | 9 | ||||
-rw-r--r-- | plugins/MirLua/src/mlua_script_loader.cpp | 24 | ||||
-rw-r--r-- | plugins/MirLua/src/mlua_script_loader.h | 7 | ||||
-rw-r--r-- | plugins/MirLua/src/stdafx.h | 13 | ||||
-rw-r--r-- | plugins/MirLua/src/version.h | 2 |
19 files changed, 423 insertions, 400 deletions
diff --git a/plugins/MirLua/src/m_json.cpp b/plugins/MirLua/src/m_json.cpp index 60f75411e9..eccef5cff2 100644 --- a/plugins/MirLua/src/m_json.cpp +++ b/plugins/MirLua/src/m_json.cpp @@ -2,8 +2,7 @@ static void lua2json(lua_State *L, JSONNode &node) { - switch (lua_type(L, -1)) - { + switch (lua_type(L, -1)) { case LUA_TNIL: node.nullify(); break; @@ -54,25 +53,36 @@ static void lua2json(lua_State *L, JSONNode &node) static int json__index(lua_State *L) { - JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); + + JSONNode *child; + if (node->type() == JSON_ARRAY) { + int idx = lua_tointeger(L, 2); + child = &node->at(idx - 1); + } + else { + const char *key = lua_tostring(L, 2); + child = &node->at(key); + } - switch (node.type()) + switch (child->type()) { case JSON_NULL: lua_pushnil(L); break; case JSON_STRING: - lua_pushstring(L, node.as_string().c_str()); + lua_pushstring(L, child->as_string().c_str()); break; case JSON_NUMBER: - lua_pushnumber(L, node.as_int()); + lua_pushnumber(L, child->as_int()); break; case JSON_BOOL: - lua_pushboolean(L, node.as_bool()); + lua_pushboolean(L, child->as_bool()); break; - case JSON_NODE: case JSON_ARRAY: - new (L) JSONNode(node); + case JSON_NODE: + JSONNode **udata = (JSONNode**)lua_newuserdata(L, sizeof(JSONNode*)); + *udata = child; luaL_setmetatable(L, MT_JSON); } @@ -81,46 +91,51 @@ static int json__index(lua_State *L) static int json__newindex(lua_State *L) { - JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); const char *key = lua_tostring(L, 2); - JSONNode child = node[key]; - if (child.isnull()) { - child.set_name(key); - lua2json(L, child); - node << child; + if (json_type(node) == JSON_ARRAY) { + int idx = lua_tointeger(L, 2); + JSONNode *child = json_at(node, idx - 1); + lua2json(L, *child); return 0; } - lua2json(L, child); - node[key] = child; + JSONNode *child = json_get(node, key); + if (json_type(child) == JSON_NULL) { + json_set_name(child, key); + lua2json(L, *child); + json_push_back(node, child); + return 0; + } + + lua2json(L, *child); return 0; } static int json__len(lua_State *L) { - JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; - - lua_pushnumber(L, node.size()); + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); + lua_pushnumber(L, json_size(node)); return 1; } static int json__tostring(lua_State *L) { - JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); - lua_pushstring(L, node.write().c_str()); + lua_pushstring(L, node->write().c_str()); return 1; } static int json__gc(lua_State *L) { - JSON *json = (JSON*)luaL_checkudata(L, 1, MT_JSON); + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); - delete json; + json_delete(node); return 0; } @@ -143,8 +158,8 @@ static int lua_Decode(lua_State *L) { const char *string = luaL_checkstring(L, 1); - JSONNode *node = json_parse(string); - new (L) JSON(node); + JSONNode **udata = (JSONNode**)lua_newuserdata(L, sizeof(JSONNode*)); + *udata = json_parse(string); luaL_setmetatable(L, MT_JSON); return 1; @@ -152,8 +167,7 @@ static int lua_Decode(lua_State *L) static int lua_Encode(lua_State *L) { - switch (lua_type(L, 1)) - { + switch (lua_type(L, 1)) { case LUA_TNIL: lua_pushliteral(L, "null"); break; @@ -190,8 +204,8 @@ static int lua_Encode(lua_State *L) } case LUA_TUSERDATA: { - JSONNode &node = *((JSON*)luaL_checkudata(L, 1, MT_JSON))->node; - lua_pushstring(L, node.write().c_str()); + JSONNode *node = *(JSONNode**)luaL_checkudata(L, 1, MT_JSON); + lua_pushstring(L, node->write().c_str()); break; } case LUA_TLIGHTUSERDATA: diff --git a/plugins/MirLua/src/m_json.h b/plugins/MirLua/src/m_json.h index bb3a2e1568..1357505bec 100644 --- a/plugins/MirLua/src/m_json.h +++ b/plugins/MirLua/src/m_json.h @@ -1,29 +1,6 @@ #ifndef _LUA_M_JSON_H_ #define _LUA_M_JSON_H_ -#include <m_json.h> - -struct JSON -{ - JSONNode *node; - bool bDelete; - - JSON(JSONNode &refNode, bool bCopy = false) - : node(bCopy ? json_copy(&refNode) : &refNode), bDelete(bCopy) { } - JSON(JSONNode *n, bool bD = true) - : node(n), bDelete(bD) { } - ~JSON() - { - if (bDelete) - json_delete(node); - } - - __inline void* operator new(size_t size, lua_State *L) - { - return lua_newuserdata(L, size); - } -}; - #define MT_JSON "JSON" #define MLUA_JSON "m_json" diff --git a/plugins/MirLua/src/m_message.cpp b/plugins/MirLua/src/m_message.cpp index c02adb0478..e382616954 100644 --- a/plugins/MirLua/src/m_message.cpp +++ b/plugins/MirLua/src/m_message.cpp @@ -27,15 +27,13 @@ static int message_Send(lua_State *L) INT_PTR res = 1;
const char *szProto = GetContactProto(hContact);
- if (db_get_b(hContact, szProto, "ChatRoom", 0) == TRUE)
- {
+ if (db_get_b(hContact, szProto, "ChatRoom", 0) == TRUE) {
ptrW wszChatRoom(db_get_wsa(hContact, szProto, "ChatRoomID"));
ptrW wszMessage(mir_utf8decodeW(message));
res = Chat_SendUserMessage(szProto, wszChatRoom, wszMessage);
lua_pushinteger(L, res);
}
- else if ((res = ProtoChainSend(hContact, PSS_MESSAGE, 0, (LPARAM)message)) != ACKRESULT_FAILED)
- {
+ else if ((res = ProtoChainSend(hContact, PSS_MESSAGE, 0, (LPARAM)message)) != ACKRESULT_FAILED) {
DBEVENTINFO dbei = {};
dbei.szModule = MODULE;
dbei.timestamp = time(nullptr);
diff --git a/plugins/MirLua/src/m_srmm.cpp b/plugins/MirLua/src/m_srmm.cpp index cd1562fe61..9a98755380 100644 --- a/plugins/MirLua/src/m_srmm.cpp +++ b/plugins/MirLua/src/m_srmm.cpp @@ -44,7 +44,7 @@ static int lua_AddButton(lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); - BBButton bbb = { }; + BBButton bbb = {}; MakeBBButton(L, bbb); int hScriptLangpack = CMLuaEnvironment::GetEnvironmentId(L); diff --git a/plugins/MirLua/src/main.cpp b/plugins/MirLua/src/main.cpp index 22fabbbdef..d316b47cd0 100644 --- a/plugins/MirLua/src/main.cpp +++ b/plugins/MirLua/src/main.cpp @@ -38,41 +38,35 @@ extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD) return &pluginInfo;
}
-int OnModulesLoaded(WPARAM, LPARAM)
+int OnOptionsInit(WPARAM wParam, LPARAM)
{
- g_hCLibsFolder = FoldersRegisterCustomPathT(MODULE, "CLibsFolder", MIRLUA_PATHT, TranslateT("C libs folder"));
- g_hScriptsFolder = FoldersRegisterCustomPathT(MODULE, "ScriptsFolder", MIRLUA_PATHT, TranslateT("Scripts folder"));
-
- HookEvent(ME_OPT_INITIALISE, CMLuaOptions::OnOptionsInit);
-
- InitIcons();
-
- g_mLua = new CMLua();
- g_mLua->Load();
+ OPTIONSDIALOGPAGE odp = {};
+ odp.hInstance = g_hInstance;
+ odp.flags = ODPF_BOLDGROUPS | ODPF_UNICODE | ODPF_DONTTRANSLATE;
+ odp.szGroup.w = LPGENW("Services");
+ odp.szTitle.w = L"Lua";
+ odp.szTab.w = LPGENW("Scripts");
+ odp.pDialog = new CMLuaOptions(g_mLua);
+ Options_AddPage(wParam, &odp);
return 0;
}
-INT_PTR Call(WPARAM wParam, LPARAM lParam)
+int OnModulesLoaded(WPARAM, LPARAM)
{
- return g_mLua->Call(wParam, lParam);
-}
+ g_hCLibsFolder = FoldersRegisterCustomPathT(MODULE, "CLibsFolder", MIRLUA_PATHT, TranslateT("C libs folder"));
+ g_hScriptsFolder = FoldersRegisterCustomPathT(MODULE, "ScriptsFolder", MIRLUA_PATHT, TranslateT("Scripts folder"));
-INT_PTR Exec(WPARAM wParam, LPARAM lParam)
-{
- return g_mLua->Exec(wParam, lParam);
-}
+ HookEvent(ME_OPT_INITIALISE, OnOptionsInit);
-INT_PTR Eval(WPARAM wParam, LPARAM lParam)
-{
- return g_mLua->Eval(wParam, lParam);
+ return 0;
}
extern "C" int __declspec(dllexport) Load(void)
{
mir_getLP(&pluginInfo);
- HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
+ InitIcons();
NETLIBUSER nlu = {};
nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_HTTPCONNS;
@@ -89,9 +83,10 @@ extern "C" int __declspec(dllexport) Load(void) hRecvMessage = CreateHookableEvent(MODULE PSR_MESSAGE);
CreateProtoServiceFunction(MODULE, PSR_MESSAGE, FilterRecvMessage);
- CreateServiceFunction(MS_LUA_CALL, Call);
- CreateServiceFunction(MS_LUA_EXEC, Exec);
- CreateServiceFunction(MS_LUA_EVAL, Eval);
+ g_mLua = new CMLua();
+ g_mLua->Load();
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
return 0;
}
@@ -100,8 +95,7 @@ extern "C" int __declspec(dllexport) Unload(void) {
delete g_mLua;
- if (hNetlib)
- {
+ if (hNetlib) {
Netlib_CloseHandle(hNetlib);
hNetlib = nullptr;
}
diff --git a/plugins/MirLua/src/mlua.cpp b/plugins/MirLua/src/mlua.cpp index 3f1da7760c..b0a12289c6 100644 --- a/plugins/MirLua/src/mlua.cpp +++ b/plugins/MirLua/src/mlua.cpp @@ -2,10 +2,17 @@ int hMLuaLangpack;
-CMLua::CMLua() : L(nullptr), Scripts(1)
+CMLua::CMLua()
+ : PLUGIN(MODULE),
+ L(nullptr),
+ Scripts(1)
{
MUUID muidLast = MIID_LAST;
hMLuaLangpack = GetPluginLangId(muidLast, 0);
+
+ CreatePluginService(MS_LUA_CALL, &CMLua::Call);
+ CreatePluginService(MS_LUA_EXEC, &CMLua::Exec);
+ CreatePluginService(MS_LUA_EVAL, &CMLua::Eval);
}
CMLua::~CMLua()
@@ -13,216 +20,17 @@ 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:
- data.AppendFormat("%s", lua_tostring(L, i));
- break;
- case LUA_TSTRING:
- data.AppendFormat("'%s'", lua_tostring(L, i));
- break;
- default:
- if (luaL_callmeta(L, i, "__tostring")) {
- data.AppendFormat("'%s'", lua_tostring(L, -1));
- break;
- }
- 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, nullptr));
-
- 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, 3)) {
- 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 ? val : "");
- }
- }
- 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 ? val : "");
- lua_pop(L, 1);
- }
- }
-
- lua_Debug ar;
- int level = 1;
- while (lua_getstack(L, level++, &ar)) {
- int i = 1;
- while (const char *name = lua_getlocal(L, &ar, i++)) {
- const char *val = lua_tostring(L, -1);
- mir_snprintf(pattern, "{%s}", name);
- string = luaL_gsub(L, string, pattern, val ? val : "");
- lua_pop(L, 1);
- }
- }
-
- lua_pushstring(L, string);
-
- return 1;
-}
-
-/***********************************************/
-
-void CMLua::SetPaths()
-{
- wchar_t path[MAX_PATH];
-
- lua_getglobal(L, "package");
-
- FoldersGetCustomPathT(g_hCLibsFolder, path, _countof(path), VARSW(MIRLUA_PATHT));
- lua_pushfstring(L, "%s\\?.dll", ptrA(mir_utf8encodeW(path)));
- lua_setfield(L, -2, "cpath");
-
- FoldersGetCustomPathT(g_hScriptsFolder, path, _countof(path), VARSW(MIRLUA_PATHT));
- lua_pushfstring(L, "%s\\?.lua", ptrA(mir_utf8encodeW(path)));
- lua_setfield(L, -2, "path");
-
- lua_pop(L, 1);
-}
-
void CMLua::Load()
{
Log("Loading lua engine");
L = luaL_newstate();
- Log("Loading std modules");
+ Log("Loading standard modules");
luaL_openlibs(L);
- SetPaths();
-
- lua_register(L, "print", mlua_print);
- lua_register(L, "a", mlua_toansi);
- lua_register(L, "toansi", mlua_toansi);
- lua_register(L, "u", mlua_toucs2);
- lua_register(L, "toucs2", mlua_toucs2);
- lua_register(L, "topointer", mlua_topointer);
-
- lua_getglobal(L, "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, mlua_interpolate);
- lua_rawset(L, -3);
- lua_pushstring(L, "__index");
- lua_rawget(L, -2);
- lua_pushcfunction(L, mlua_interpolate);
- lua_setfield(L, -2, "interpolate");
- lua_pop(L, 3);
-
lua_atpanic(L, luaM_atpanic);
- Log("Loading miranda modules");
+ CMLuaFunctionLoader::Load(L);
CMLuaModuleLoader::Load(L);
- Log("Loading scripts");
CMLuaScriptLoader::Load(L);
}
@@ -243,6 +51,12 @@ void CMLua::Unload() lua_close(L);
}
+void CMLua::Reload()
+{
+ Unload();
+ Load();
+}
+
/***********************************************/
static int mlua_call(lua_State *L)
@@ -276,7 +90,7 @@ INT_PTR CMLua::Call(WPARAM wParam, LPARAM lParam) lua_newtable(L);
lua_pushcclosure(L, mlua_call, 1);
-
+
CMLuaEnvironment env(L);
env.Load();
@@ -286,11 +100,11 @@ INT_PTR CMLua::Call(WPARAM wParam, LPARAM lParam) return (INT_PTR)result;
}
-INT_PTR CMLua::Exec(WPARAM, LPARAM lParam)
+INT_PTR CMLua::Eval(WPARAM, LPARAM lParam)
{
- const wchar_t *path = (const wchar_t*)lParam;
+ const wchar_t *script = (const wchar_t*)lParam;
- if (luaL_loadfile(L, ptrA(mir_utf8encodeW(path)))) {
+ if (luaL_loadstring(L, ptrA(mir_utf8encodeW(script)))) {
ReportError(L);
return NULL;
}
@@ -304,11 +118,11 @@ INT_PTR CMLua::Exec(WPARAM, LPARAM lParam) return (INT_PTR)result;
}
-INT_PTR CMLua::Eval(WPARAM, LPARAM lParam)
+INT_PTR CMLua::Exec(WPARAM, LPARAM lParam)
{
- const wchar_t *script = (const wchar_t*)lParam;
+ const wchar_t *path = (const wchar_t*)lParam;
- if (luaL_loadstring(L, ptrA(mir_utf8encodeW(script)))) {
+ if (luaL_loadfile(L, ptrA(mir_utf8encodeW(path)))) {
ReportError(L);
return NULL;
}
@@ -320,4 +134,4 @@ INT_PTR CMLua::Eval(WPARAM, LPARAM lParam) lua_pop(L, 1);
return (INT_PTR)result;
-}
\ No newline at end of file +}
diff --git a/plugins/MirLua/src/mlua.h b/plugins/MirLua/src/mlua.h index 44ebd4a40d..6f5bdca432 100644 --- a/plugins/MirLua/src/mlua.h +++ b/plugins/MirLua/src/mlua.h @@ -1,12 +1,18 @@ #ifndef _LUA_CORE_H_
#define _LUA_CORE_H_
-class CMLua
+class CMLua : private PLUGIN<CMLua>
{
+ friend class CMLuaOptions;
+
private:
lua_State *L;
- void SetPaths();
+ void Unload();
+
+ INT_PTR __cdecl Eval(WPARAM, LPARAM);
+ INT_PTR __cdecl Call(WPARAM, LPARAM);
+ INT_PTR __cdecl Exec(WPARAM, LPARAM);
public:
OBJLIST<CMLuaScript> Scripts;
@@ -15,11 +21,7 @@ public: ~CMLua();
void Load();
- void Unload();
-
- INT_PTR Call(WPARAM, LPARAM);
- INT_PTR Exec(WPARAM, LPARAM);
- INT_PTR Eval(WPARAM, LPARAM);
+ void Reload();
};
#endif //_LUA_CORE_H_
diff --git a/plugins/MirLua/src/mlua_function_loader.cpp b/plugins/MirLua/src/mlua_function_loader.cpp new file mode 100644 index 0000000000..6e82086d29 --- /dev/null +++ b/plugins/MirLua/src/mlua_function_loader.cpp @@ -0,0 +1,194 @@ +#include "stdafx.h" + +CMLuaFunctionLoader::CMLuaFunctionLoader(lua_State *L) : L(L) +{ +} + +/***********************************************/ + +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: + data.AppendFormat("%s", lua_tostring(L, i)); + break; + case LUA_TSTRING: + data.AppendFormat("'%s'", lua_tostring(L, i)); + break; + default: + if (luaL_callmeta(L, i, "__tostring")) { + data.AppendFormat("'%s'", lua_tostring(L, -1)); + break; + } + 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, nullptr)); + + 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, 3)) { + 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 ? val : ""); + } + } + 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 ? val : ""); + lua_pop(L, 1); + } + } + + lua_Debug ar; + int level = 1; + while (lua_getstack(L, level++, &ar)) { + int i = 1; + while (const char *name = lua_getlocal(L, &ar, i++)) { + const char *val = lua_tostring(L, -1); + mir_snprintf(pattern, "{%s}", name); + string = luaL_gsub(L, string, pattern, val ? val : ""); + lua_pop(L, 1); + } + } + + lua_pushstring(L, string); + + return 1; +} + +/***********************************************/ + +void CMLuaFunctionLoader::LoadFunctions() +{ + Log("Loading additional functions"); + + lua_register(L, "print", mlua_print); + lua_register(L, "a", mlua_toansi); + lua_register(L, "toansi", mlua_toansi); + lua_register(L, "u", mlua_toucs2); + lua_register(L, "toucs2", mlua_toucs2); + lua_register(L, "topointer", mlua_topointer); + + lua_getglobal(L, "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, mlua_interpolate); + lua_rawset(L, -3); + lua_pushstring(L, "__index"); + lua_rawget(L, -2); + lua_pushcfunction(L, mlua_interpolate); + lua_setfield(L, -2, "interpolate"); + lua_pop(L, 3); +} + +void CMLuaFunctionLoader::Load(lua_State *L) +{ + CMLuaFunctionLoader loader(L); + loader.LoadFunctions(); +}
\ No newline at end of file diff --git a/plugins/MirLua/src/mlua_function_loader.h b/plugins/MirLua/src/mlua_function_loader.h new file mode 100644 index 0000000000..9724ccdc3d --- /dev/null +++ b/plugins/MirLua/src/mlua_function_loader.h @@ -0,0 +1,14 @@ +#pragma once + +class CMLuaFunctionLoader +{ +private: + lua_State *L; + + CMLuaFunctionLoader(lua_State *L); + + void LoadFunctions(); + +public: + static void Load(lua_State *L); +}; diff --git a/plugins/MirLua/src/mlua_module_loader.cpp b/plugins/MirLua/src/mlua_module_loader.cpp index d914bad120..ff9594f363 100644 --- a/plugins/MirLua/src/mlua_module_loader.cpp +++ b/plugins/MirLua/src/mlua_module_loader.cpp @@ -19,6 +19,8 @@ void CMLuaModuleLoader::Preload(const char *name, lua_CFunction loader) void CMLuaModuleLoader::LoadModules()
{
+ Log("Loading miranda modules");
+
// load m_core module
Load(MLUA_CORE, luaopen_m_core);
// load all internal modules
diff --git a/plugins/MirLua/src/mlua_module_loader.h b/plugins/MirLua/src/mlua_module_loader.h index 123c05bf41..bab8e79e84 100644 --- a/plugins/MirLua/src/mlua_module_loader.h +++ b/plugins/MirLua/src/mlua_module_loader.h @@ -1,5 +1,4 @@ -#ifndef _LUA_MODULE_LOADER_H_
-#define _LUA_MODULE_LOADER_H_
+#pragma once
class CMLuaModuleLoader
{
@@ -16,5 +15,3 @@ private: public:
static void Load(lua_State *L);
};
-
-#endif //_LUA_MODULE_LOADER_H_
\ No newline at end of file diff --git a/plugins/MirLua/src/mlua_options.cpp b/plugins/MirLua/src/mlua_options.cpp index a4afbf33dc..9aff70ba3f 100644 --- a/plugins/MirLua/src/mlua_options.cpp +++ b/plugins/MirLua/src/mlua_options.cpp @@ -1,11 +1,11 @@ #include "stdafx.h"
-CMLuaOptions::CMLuaOptions(int idDialog)
- : CPluginDlgBase(g_hInstance, idDialog, MODULE),
+CMLuaOptions::CMLuaOptions(CMLua *mLua)
+ : CPluginDlgBase(g_hInstance, IDD_OPTIONS, MODULE),
+ m_mLua(mLua), isScriptListInit(false),
m_popupOnError(this, IDC_POPUPONERROR),
m_popupOnObsolete(this, IDC_POPUPONOBSOLETE),
- isScriptListInit(false), m_scripts(this, IDC_SCRIPTS),
- m_reload(this, IDC_RELOAD)
+ m_scripts(this, IDC_SCRIPTS), m_reload(this, IDC_RELOAD)
{
CreateLink(m_popupOnError, "PopupOnError", DBVT_BYTE, 1);
CreateLink(m_popupOnObsolete, "PopupOnObsolete", DBVT_BYTE, 1);
@@ -16,12 +16,11 @@ CMLuaOptions::CMLuaOptions(int idDialog) void CMLuaOptions::LoadScripts()
{
- for (auto &it : g_mLua->Scripts) {
- wchar_t *fileName = NEWWSTR_ALLOCA(it->GetFileName());
- int iIcon = it->GetStatus() - 1;
- int iItem = m_scripts.AddItem(fileName, iIcon, (LPARAM)it);
- if (db_get_b(NULL, MODULE, _T2A(fileName), 1))
- m_scripts.SetCheckState(iItem, TRUE);
+ for (auto &script : m_mLua->Scripts) {
+ wchar_t *fileName = NEWWSTR_ALLOCA(script->GetFileName());
+ int iIcon = script->GetStatus() - 1;
+ int iItem = m_scripts.AddItem(fileName, iIcon, (LPARAM)script);
+ m_scripts.SetCheckState(iItem, script->IsEnabled());
m_scripts.SetItem(iItem, 1, TranslateT("Open"), 2);
m_scripts.SetItem(iItem, 2, TranslateT("Reload"), 3);
}
@@ -39,9 +38,13 @@ void CMLuaOptions::OnInitDialog() ImageList_AddIcon(hImageList, GetIcon(IDI_OPEN));
ImageList_AddIcon(hImageList, GetIcon(IDI_RELOAD));
- wchar_t scriptDir[MAX_PATH], relativeScriptDir[MAX_PATH], header[MAX_PATH + 100];
+ wchar_t scriptDir[MAX_PATH];
FoldersGetCustomPathT(g_hScriptsFolder, scriptDir, _countof(scriptDir), VARSW(MIRLUA_PATHT));
+
+ wchar_t relativeScriptDir[MAX_PATH];
PathToRelativeW(scriptDir, relativeScriptDir, nullptr);
+
+ wchar_t header[MAX_PATH + 100];
mir_snwprintf(header, L"%s (%s)", TranslateT("Common scripts"), relativeScriptDir);
m_scripts.AddColumn(0, L"Script", 380);
@@ -57,12 +60,11 @@ void CMLuaOptions::OnApply() {
int count = m_scripts.GetItemCount();
for (int iItem = 0; iItem < count; iItem++) {
- wchar_t fileName[MAX_PATH];
- m_scripts.GetItemText(iItem, 0, fileName, _countof(fileName));
+ CMLuaScript *script = (CMLuaScript*)m_scripts.GetItemData(iItem);
if (!m_scripts.GetCheckState(iItem))
- db_set_b(NULL, MODULE, _T2A(fileName), 0);
+ script->Disable();
else
- db_unset(NULL, MODULE, _T2A(fileName));
+ script->Enable();
}
}
@@ -82,41 +84,36 @@ INT_PTR CMLuaOptions::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) }
break;
}
-
return CDlgBase::DlgProc(msg, wParam, lParam);
}
void CMLuaOptions::OnScriptListClick(CCtrlListView::TEventInfo *evt)
{
- LVITEM lvi = { 0 };
+ LVITEM lvi = {};
lvi.iItem = evt->nmlvia->iItem;
- if (lvi.iItem == -1) return;
+ if (lvi.iItem == -1)
+ return;
+
lvi.pszText = (LPTSTR)mir_calloc(MAX_PATH * sizeof(wchar_t));
lvi.cchTextMax = MAX_PATH;
lvi.mask = LVIF_GROUPID | LVIF_TEXT | LVIF_PARAM;
- evt->treeviewctrl->GetItem(&lvi);
+ m_scripts.GetItem(&lvi);
lvi.iSubItem = evt->nmlvia->iSubItem;
CMLuaScript *script = (CMLuaScript*)lvi.lParam;
- switch (lvi.iSubItem)
- {
+ switch (lvi.iSubItem) {
case 1:
- ShellExecute(m_hwnd, L"Open", script->GetFilePath(), nullptr, nullptr, SW_SHOWNORMAL);
+ ShellExecute(m_hwnd, L"open", script->GetFilePath(), nullptr, nullptr, SW_SHOWNORMAL);
break;
case 2:
- CMLuaScript *oldScript = script;
- script = new CMLuaScript(*script);
- delete oldScript;
- script->Load();
-
- lvi.mask = LVIF_PARAM | LVIF_IMAGE;
+ script->Reload();
+ lvi.mask = LVIF_IMAGE;
lvi.iSubItem = 0;
- lvi.lParam = (LPARAM)script;
lvi.iImage = script->GetStatus() - 1;
- ListView_SetItem(m_scripts.GetHwnd(), &lvi);
- m_scripts.Update(evt->nmlvia->iItem);
+ m_scripts.SetItem(&lvi);
+ m_scripts.Update(lvi.iItem);
break;
}
@@ -127,24 +124,7 @@ void CMLuaOptions::OnReload(CCtrlBase*) {
isScriptListInit = false;
m_scripts.DeleteAllItems();
- g_mLua->Unload();
- g_mLua->Load();
+ m_mLua->Reload();
LoadScripts();
isScriptListInit = true;
}
-
-/****************************************/
-
-int CMLuaOptions::OnOptionsInit(WPARAM wParam, LPARAM)
-{
- OPTIONSDIALOGPAGE odp = { 0 };
- odp.hInstance = g_hInstance;
- odp.flags = ODPF_BOLDGROUPS | ODPF_UNICODE | ODPF_DONTTRANSLATE;
- odp.szGroup.w = LPGENW("Services");
- odp.szTitle.w = L"Lua";
- odp.szTab.w = LPGENW("Scripts");
- odp.pDialog = CMLuaOptions::CreateOptionsPage();
- Options_AddPage(wParam, &odp);
-
- return 0;
-}
\ No newline at end of file diff --git a/plugins/MirLua/src/mlua_options.h b/plugins/MirLua/src/mlua_options.h index a8168d70da..2e3b4ff7f7 100644 --- a/plugins/MirLua/src/mlua_options.h +++ b/plugins/MirLua/src/mlua_options.h @@ -1,15 +1,15 @@ #ifndef _LUA_OPTIONS_H_
#define _LUA_OPTIONS_H_
-#include <m_gui.h>
-
class CMLuaOptions : public CPluginDlgBase
{
private:
+ CMLua *m_mLua;
+ bool isScriptListInit;
+
CCtrlCheck m_popupOnError;
CCtrlCheck m_popupOnObsolete;
- bool isScriptListInit;
CCtrlListView m_scripts;
CCtrlButton m_reload;
@@ -25,10 +25,7 @@ protected: INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam);
public:
- CMLuaOptions(int idDialog);
-
- static int OnOptionsInit(WPARAM wParam, LPARAM);
- static CDlgBase *CreateOptionsPage() { return new CMLuaOptions(IDD_OPTIONS); }
+ CMLuaOptions(CMLua *mLua);
};
#endif //_LUA_OPTIONS_H_
\ No newline at end of file diff --git a/plugins/MirLua/src/mlua_script.cpp b/plugins/MirLua/src/mlua_script.cpp index 310fecddf9..83b5008e15 100644 --- a/plugins/MirLua/src/mlua_script.cpp +++ b/plugins/MirLua/src/mlua_script.cpp @@ -28,29 +28,10 @@ CMLuaScript::CMLuaScript(const CMLuaScript &script) CMLuaScript::~CMLuaScript()
{
- if (status == Loaded)
- {
- lua_rawgeti(L, LUA_REGISTRYINDEX, unloadRef);
- if (lua_isfunction(L, -1))
- luaM_pcall(L);
- lua_pushnil(L);
- lua_rawsetp(L, LUA_REGISTRYINDEX, this);
- status = None;
- }
-
- luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
- lua_pushnil(L);
- lua_setfield(L, -2, moduleName);
- lua_pop(L, 1);
-
+ Unload();
mir_free(moduleName);
}
-const char* CMLuaScript::GetModuleName() const
-{
- return moduleName;
-}
-
const wchar_t* CMLuaScript::GetFilePath() const
{
return filePath;
@@ -61,6 +42,21 @@ const wchar_t* CMLuaScript::GetFileName() const return fileName;
}
+bool CMLuaScript::IsEnabled()
+{
+ return db_get_b(NULL, MODULE, _T2A(fileName), 1);
+}
+
+void CMLuaScript::Enable()
+{
+ db_unset(NULL, MODULE, _T2A(fileName));
+}
+
+void CMLuaScript::Disable()
+{
+ db_set_b(NULL, MODULE, _T2A(fileName), 0);
+}
+
CMLuaScript::Status CMLuaScript::GetStatus() const
{
return status;
@@ -85,7 +81,7 @@ bool CMLuaScript::Load() if (lua_isnoneornil(L, -1))
return true;
- luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
+ luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
lua_getfield(L, -1, moduleName);
if (!lua_toboolean(L, -1)) {
lua_pop(L, 1);
@@ -115,4 +111,27 @@ bool CMLuaScript::Load() lua_pop(L, 1);
return true;
-}
\ No newline at end of file +}
+
+void CMLuaScript::Unload()
+{
+ if (status == Loaded) {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, unloadRef);
+ if (lua_isfunction(L, -1))
+ luaM_pcall(L);
+ lua_pushnil(L);
+ lua_rawsetp(L, LUA_REGISTRYINDEX, this);
+ status = None;
+ }
+
+ luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
+ lua_pushnil(L);
+ lua_setfield(L, -2, moduleName);
+ lua_pop(L, 1);
+}
+
+bool CMLuaScript::Reload()
+{
+ Unload();
+ return Load();
+}
diff --git a/plugins/MirLua/src/mlua_script.h b/plugins/MirLua/src/mlua_script.h index 9a1ec98390..70c044741e 100644 --- a/plugins/MirLua/src/mlua_script.h +++ b/plugins/MirLua/src/mlua_script.h @@ -19,19 +19,24 @@ private: wchar_t *fileName;
wchar_t filePath[MAX_PATH];
+ void Unload();
+
public:
CMLuaScript(lua_State *L, const wchar_t *path);
CMLuaScript(const CMLuaScript &script);
~CMLuaScript();
- const char* GetModuleName() const;
-
const wchar_t* GetFilePath() const;
const wchar_t* GetFileName() const;
+ bool IsEnabled();
+ void Enable();
+ void Disable();
+
Status GetStatus() const;
bool Load();
+ bool Reload();
};
#endif //_LUA_SCRIPT_H_
diff --git a/plugins/MirLua/src/mlua_script_loader.cpp b/plugins/MirLua/src/mlua_script_loader.cpp index 60ceb5cbb5..95701b4559 100644 --- a/plugins/MirLua/src/mlua_script_loader.cpp +++ b/plugins/MirLua/src/mlua_script_loader.cpp @@ -1,9 +1,27 @@ #include "stdafx.h"
-CMLuaScriptLoader::CMLuaScriptLoader(lua_State *L) : L(L)
+CMLuaScriptLoader::CMLuaScriptLoader(lua_State *L)
+ : L(L)
{
}
+void CMLuaScriptLoader::SetPaths()
+{
+ wchar_t path[MAX_PATH];
+
+ lua_getglobal(L, LUA_LOADLIBNAME);
+
+ FoldersGetCustomPathT(g_hCLibsFolder, path, _countof(path), VARSW(MIRLUA_PATHT));
+ lua_pushfstring(L, "%s\\?.dll", T2Utf(path));
+ lua_setfield(L, -2, "cpath");
+
+ FoldersGetCustomPathT(g_hScriptsFolder, path, _countof(path), VARSW(MIRLUA_PATHT));
+ lua_pushfstring(L, "%s\\?.lua", T2Utf(path));
+ lua_setfield(L, -2, "path");
+
+ lua_pop(L, 1);
+}
+
void CMLuaScriptLoader::LoadScript(const wchar_t *scriptDir, const wchar_t *file)
{
wchar_t fullPath[MAX_PATH], path[MAX_PATH];
@@ -13,7 +31,7 @@ void CMLuaScriptLoader::LoadScript(const wchar_t *scriptDir, const wchar_t *file CMLuaScript *script = new CMLuaScript(L, path);
g_mLua->Scripts.insert(script);
- if (db_get_b(NULL, MODULE, _T2A(file), 1) == FALSE) {
+ if (!script->IsEnabled()) {
Log(L"%s:PASS", path);
return;
}
@@ -24,6 +42,8 @@ void CMLuaScriptLoader::LoadScript(const wchar_t *scriptDir, const wchar_t *file void CMLuaScriptLoader::LoadScripts()
{
+ SetPaths();
+
wchar_t scriptDir[MAX_PATH];
FoldersGetCustomPathT(g_hScriptsFolder, scriptDir, _countof(scriptDir), VARSW(MIRLUA_PATHT));
diff --git a/plugins/MirLua/src/mlua_script_loader.h b/plugins/MirLua/src/mlua_script_loader.h index e455793adf..74489a0500 100644 --- a/plugins/MirLua/src/mlua_script_loader.h +++ b/plugins/MirLua/src/mlua_script_loader.h @@ -1,5 +1,4 @@ -#ifndef _LUA_SCRIPT_LOADER_H_
-#define _LUA_SCRIPT_LOADER_H_
+#pragma once
class CMLuaScriptLoader
{
@@ -7,6 +6,8 @@ private: lua_State *L;
CMLuaScriptLoader(lua_State *L);
+
+ void SetPaths();
void LoadScript(const wchar_t *scriptDir, const wchar_t *file);
void LoadScripts();
@@ -14,5 +15,3 @@ private: public:
static void Load(lua_State *L);
};
-
-#endif //_LUA_SCRIPT_LOADER_H_
\ No newline at end of file diff --git a/plugins/MirLua/src/stdafx.h b/plugins/MirLua/src/stdafx.h index 2939b66922..3b5d8ffb6d 100644 --- a/plugins/MirLua/src/stdafx.h +++ b/plugins/MirLua/src/stdafx.h @@ -1,5 +1,4 @@ -#ifndef _COMMON_H_
-#define _COMMON_H_
+#pragma once
#include <windows.h>
#include <time.h>
@@ -25,6 +24,9 @@ #include <m_folders.h>
#include <m_popup.h>
#include <m_toptoolbar.h>
+#include <m_json.h>
+#include <m_gui.h>
+#include <m_plugin.h>
#include <m_lua.h>
#include <mirlua.h>
@@ -37,6 +39,7 @@ class CMLuaScript; #include "mlua.h"
#include "mlua_environment.h"
#include "mlua_script.h"
+#include "mlua_function_loader.h"
#include "mlua_module_loader.h"
#include "mlua_script_loader.h"
#include "mlua_options.h"
@@ -98,10 +101,6 @@ LUAMOD_API int (luaopen_m_sounds)(lua_State *L); #define MLUA_SRMM "m_srmm"
LUAMOD_API int (luaopen_m_srmm)(lua_State *L);
-/* services */
-
-INT_PTR Call(WPARAM wParam, LPARAM lParam);
-
/* utils */
extern HNETLIBUSER hNetlib;
@@ -124,5 +123,3 @@ bool luaM_toboolean(lua_State *L, int idx); void InitIcons();
HICON GetIcon(int iconId);
HANDLE GetIconHandle(int iconId);
-
-#endif //_COMMON_H_
diff --git a/plugins/MirLua/src/version.h b/plugins/MirLua/src/version.h index 65a0d49d81..c178f55fb7 100644 --- a/plugins/MirLua/src/version.h +++ b/plugins/MirLua/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0
#define __MINOR_VERSION 11
#define __RELEASE_NUM 8
-#define __BUILD_NUM 6
+#define __BUILD_NUM 7
#include <stdver.h>
|