lua.c
changeset 109 2d2111cb5109
parent 108 dedb85093c02
child 110 bd9f24178d67
equal deleted inserted replaced
108:dedb85093c02 109:2d2111cb5109
    60 	"Provides command /lua" )
    60 	"Provides command /lua" )
    61 #endif
    61 #endif
    62 
    62 
    63 static module_info_t info_lua_experimental = {
    63 static module_info_t info_lua_experimental = {
    64 	.branch      = "experimental",
    64 	.branch      = "experimental",
    65 	.api         = 25,
    65 	.api         = 27,
    66 	.version     = PROJECT_VERSION,
    66 	.version     = PROJECT_VERSION,
    67 	.description = DESCRIPTION,
    67 	.description = DESCRIPTION,
    68 	.requires    = NULL,
    68 	.requires    = NULL,
    69 	.init        = mlua_init,
    69 	.init        = mlua_init,
    70 	.uninit      = mlua_uninit,
    70 	.uninit      = mlua_uninit,
   800 	{ NULL,        0               },
   800 	{ NULL,        0               },
   801 };
   801 };
   802 #define MLUA_YESNO_POS ( 21 )
   802 #define MLUA_YESNO_POS ( 21 )
   803 
   803 
   804 typedef struct {
   804 typedef struct {
   805 	int        reference;
   805 	int        cbref;
   806 	int        parse_args;
   806 	int        parse_args;
       
   807 #ifdef HAVE_CMD_ID
       
   808 	gpointer   cmid;
       
   809 #else
       
   810 	int        nameref;
       
   811 #endif
       
   812 	int        selfref;
   807 	lua_State *L;
   813 	lua_State *L;
   808 } lua_command_callback_t;
   814 } lua_command_t;
   809 
       
   810 static GSList *lua_added_commands = NULL;
       
   811 
   815 
   812 static GSList *lua_added_categories = NULL;
   816 static GSList *lua_added_categories = NULL;
   813 
   817 
   814 // returns true if string contains errors - unclosed quotes or unvalued option
   818 // returns true if string contains errors - unclosed quotes or unvalued option
   815 /// command arguments table
   819 /// command arguments table
   923 
   927 
   924 /// command function
   928 /// command function
   925 /// Function to handle newly registered command.
   929 /// Function to handle newly registered command.
   926 /// Argument type passed depends on how command is registered.
   930 /// Argument type passed depends on how command is registered.
   927 /// A: string (arguments) or command arguments table
   931 /// A: string (arguments) or command arguments table
   928 static void lua_main_command_handler (char *args, lua_command_callback_t *cb)
   932 static void lua_main_command_handler (char *args, lua_command_t *cb)
   929 {
   933 {
   930 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference);
   934 	lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->cbref);
   931 
   935 
   932 	if (cb->parse_args)
   936 	if (cb->parse_args)
   933 		luaL_pushargs (cb->L, args);
   937 		luaL_pushargs (cb->L, args);
   934 	else
   938 	else
   935 		lua_pushstring (cb->L, args);
   939 		lua_pushstring (cb->L, args);
  1018 	g_free (word);
  1022 	g_free (word);
  1019 	return 0;
  1023 	return 0;
  1020 }
  1024 }
  1021 
  1025 
  1022 /// main.command
  1026 /// main.command
  1023 /// Associates or breaks association between mcabber command name and lua function.
  1027 /// Associates mcabber command name and lua function.
  1024 /// To unregister command omit function argument.
  1028 /// As a completion you can also specify a string name (see completion type) instead of table, for non-builtin, you can just pass integer id.
  1025 /// If you specify a third argument, table (even empty), function will return completion group id or nothing.
       
  1026 /// You can also specify a string name (see completion type) instead of table, for non-builtin, you can just pass integer id.
       
  1027 /// Note, that for now there are no way to unregister completion group, so, resources can be exausted easily.
  1029 /// Note, that for now there are no way to unregister completion group, so, resources can be exausted easily.
  1028 /// Also note, that it ignores keys in a completion table.
  1030 /// Also note, that it ignores keys in a completion table.
  1029 /// A: string (command name), command function (optional), boolean (parse args flag, optional), table (completions, optional)/completion type (or integer comletion group id, optional)
  1031 /// A: string (command name), command function, boolean (parse args flag, optional), table (completions, optional)/completion type (or integer comletion group id, optional)
  1030 /// R: completion type (integer completion group id or string for builtin types, optional)
  1032 /// R: userdata (command object)
  1031 static int lua_main_command (lua_State *L)
  1033 static int lua_main_command (lua_State *L)
  1032 {
  1034 {
  1033 	const char             *name = luaL_checkstring (L, 1); // XXX: to_utf8? looks like no :/
  1035 	const char    *name  = luaL_checkstring (L, 1); // XXX: to_utf8? looks like no :/
  1034 	lua_command_callback_t *cb;
  1036 	lua_command_t *cb;
  1035 	int                     top  = lua_gettop (L);
  1037 	int            top   = lua_gettop (L);
  1036 	if (top > 1 && !(top == 2 && lua_isnil (L, 2))) { // Register
  1038 	guint          cid   = 0;
  1037 		guint cid = 0;
  1039 	int            parse = 0;
  1038 		int parse = 0;
  1040 	luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
  1039 		luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected");
  1041 
  1040 
  1042 	if (top > 2) { // parse flag provided
  1041 		if (top > 2) { // parse flag provided
  1043 		parse = lua_toboolean (L, 3);
  1042 			parse = lua_toboolean (L, 3);
  1044 
  1043 
  1045 		if (top > 3) { // Completions provided
  1044 			if (top > 3) { // Completions provided
  1046 			if (lua_type (L, 4) == LUA_TTABLE) {
  1045 				if (lua_type (L, 4) == LUA_TTABLE) {
  1047 				cid = compl_new_category ();
  1046 					cid = compl_new_category ();
  1048 				if (cid) {
  1047 					if (cid) {
  1049 					lua_added_categories = g_slist_prepend (lua_added_categories, (gpointer) cid);
  1048 						lua_added_categories = g_slist_prepend (lua_added_categories, (gpointer) cid);
  1050 					lua_pushnil (L);
  1049 						lua_pushnil (L);
  1051 					while (lua_next (L, 4)) {
  1050 						while (lua_next (L, 4)) {
  1052 						char *word = to_utf8 (luaL_checkstring (L, -1));
  1051 							char *word = to_utf8 (luaL_checkstring (L, -1));
  1053 						compl_add_category_word (cid, word);
  1052 							compl_add_category_word (cid, word);
  1054 						lua_pop (L, 1);
  1053 							lua_pop (L, 1);
  1055 						g_free (word);
  1054 							g_free (word);
       
  1055 						}
       
  1056 					}
  1056 					}
  1057 				} else
  1057 				}
  1058 					cid = luaL_checkenum (L, 4, lua_completion_type);
  1058 			} else
  1059 			}
  1059 				cid = luaL_checkenum (L, 4, lua_completion_type);
  1060 		}
  1060 		}
  1061 
  1061 	}
  1062 		cb = luaL_malloc (L, sizeof (lua_command_callback_t));
  1062 	
  1063 		lua_pushvalue (L, 2);
  1063 	cb = lua_newuserdata (L, sizeof (lua_command_t));
  1064 		cb->reference  = luaL_ref (L, LUA_REGISTRYINDEX);
  1064 	luaL_getmetatable (L, "mcabber.command");
  1065 		cb->parse_args = parse;
  1065 	lua_setmetatable (L, -2);
  1066 		cb->L          = L;
  1066 	lua_pushvalue (L, 2);
  1067 		cmd_add (name, "", cid, 0, (void (*) (char *p)) lua_main_command_handler, cb);
  1067 	cb -> cbref      = luaL_ref (L, LUA_REGISTRYINDEX);
  1068 
  1068 	lua_pushvalue (L, -1);
  1069 		lua_added_commands = g_slist_prepend (lua_added_commands, g_strdup (name));
  1069 	cb -> selfref    = luaL_ref (L, LUA_REGISTRYINDEX);
  1070 
  1070 	cb -> parse_args = parse;
  1071 		if (cid) {
  1071 	cb -> L          = L;
  1072 			luaL_pushenum (L, cid, lua_completion_type);
  1072 #ifdef HAVE_CMD_ID
  1073 			return 1;
  1073 	cb -> cmid       = cmd_add (name, "", cid, 0, (void (*) (char *p)) lua_main_command_handler, cb);
  1074 		}
  1074 #else
  1075 	} else { // Unregister
  1075 	lua_pushvalue (L, 1);
  1076 		GSList *el = g_slist_find_custom (lua_added_commands, name, (GCompareFunc) g_strcmp0);
  1076 	cb -> nameref    = luaL_ref (L, LUA_REGISTRYINDEX);
  1077 
  1077 	cmd_add (name, "", cid, 0, (void (*) (char *p)) lua_main_command_handler, cb);
  1078 		cb = cmd_del (name);
  1078 #endif
  1079 		if (cb) {
  1079 
  1080 			luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference);
  1080 	return 1;
  1081 			luaL_free (cb->L, cb);
  1081 }
  1082 		}
  1082 
  1083 
  1083 static void lua_mcabber_unregister_command (lua_State *L, lua_command_t *cb)
  1084 		if (el) {
  1084 {
  1085 			g_free (el->data);
  1085 #ifdef HAVE_CMD_ID
  1086 			lua_added_commands = g_slist_delete_link (lua_added_commands, el);
  1086 	if (cb -> cmid)
  1087 		}
  1087 		cmd_del (cb -> cmid);
       
  1088 #else
       
  1089 	const char *name;
       
  1090 
       
  1091 	if (cb -> nameref == LUA_NOREF)
       
  1092 		return;
       
  1093 
       
  1094 	lua_rawgeti (L, LUA_REGISTRYINDEX, cb -> nameref);
       
  1095 	name = lua_tostring (L, -1);
       
  1096 	cmd_del (name);
       
  1097 	lua_pop (L, 1);
       
  1098 #endif
       
  1099 }
       
  1100 
       
  1101 /// command:del
       
  1102 /// Unregisters given command from mcabber. Object will be destroyed later.
       
  1103 static int lua_mcabber_command_del (lua_State *L)
       
  1104 {
       
  1105 	lua_command_t *cb = luaL_checkudata (L, 1, "mcabber.command");
       
  1106 	luaL_argcheck (L, cb != NULL, 1, "mcabber command object expected");
       
  1107 	lua_mcabber_unregister_command (L, cb);
       
  1108 	if (cb -> selfref != LUA_NOREF) {
       
  1109 		luaL_unref (L, LUA_REGISTRYINDEX, cb -> selfref);
       
  1110 		cb -> selfref = LUA_NOREF;
  1088 	}
  1111 	}
  1089 	return 0;
  1112 	return 0;
       
  1113 }
       
  1114 
       
  1115 static int lua_mcabber_command_gc (lua_State *L)
       
  1116 {
       
  1117 	lua_command_t *cb = luaL_checkudata (L, 1, "mcabber.command");
       
  1118 	luaL_argcheck (L, cb != NULL, 1, "mcabber command object expected");
       
  1119 	lua_mcabber_unregister_command (L, cb);
       
  1120 #ifndef HAVE_CMD_ID
       
  1121 	if (cb -> nameref != LUA_NOREF)
       
  1122 		luaL_unref (L, LUA_REGISTRYINDEX, cb -> nameref);
       
  1123 #endif
       
  1124 	if (cb -> cbref != LUA_NOREF)
       
  1125 		luaL_unref (L, LUA_REGISTRYINDEX, cb -> cbref);
       
  1126 	return 0;
       
  1127 }
       
  1128 
       
  1129 static const luaL_Reg lua_mcabber_command_reg_m[] = {
       
  1130 	{ "del",  lua_mcabber_command_del },
       
  1131 	{ "__gc", lua_mcabber_command_gc  },
       
  1132 	{ NULL,   NULL                 },
       
  1133 };
       
  1134 
       
  1135 static void lua_command_init (lua_State *L)
       
  1136 {
       
  1137 	luaL_newmetatable (L, "mcabber.command");
       
  1138 	lua_pushvalue (L, -1);
       
  1139 	lua_setfield (L, -2, "__index");
       
  1140 	luaL_register (L, NULL, lua_mcabber_command_reg_m);
       
  1141 	lua_pop (L, 1);
  1090 }
  1142 }
  1091 
  1143 
  1092 // TIMER
  1144 // TIMER
  1093 
  1145 
  1094 typedef struct {
  1146 typedef struct {
  1698 #ifdef LLM_LOG_HANDLER
  1750 #ifdef LLM_LOG_HANDLER
  1699 	// FIXME: this should not be here.
  1751 	// FIXME: this should not be here.
  1700 	lua_lm_log_handler_id = g_log_set_handler ("lua-lm", G_LOG_LEVEL_MASK, (GLogFunc) lua_lm_log_handler, NULL);
  1752 	lua_lm_log_handler_id = g_log_set_handler ("lua-lm", G_LOG_LEVEL_MASK, (GLogFunc) lua_lm_log_handler, NULL);
  1701 #endif
  1753 #endif
  1702 
  1754 
  1703 	lua_hook_init (lua);
  1755 	lua_hook_init    (lua);
       
  1756 	lua_command_init (lua);
  1704 
  1757 
  1705 	{
  1758 	{
  1706 		char *initfile = expand_filename (settings_opt_get ("lua_init_filename"));
  1759 		char *initfile = expand_filename (settings_opt_get ("lua_init_filename"));
  1707 		
  1760 		
  1708 		if (!initfile)
  1761 		if (!initfile)
  1764 {
  1817 {
  1765 	xmpp_del_feature (xmlns);
  1818 	xmpp_del_feature (xmlns);
  1766 	g_free (xmlns);
  1819 	g_free (xmlns);
  1767 }
  1820 }
  1768 
  1821 
  1769 static void lua_commands_destroy (char *name, gpointer ignore)
       
  1770 {
       
  1771 	lua_command_callback_t *cb = cmd_del (name);
       
  1772 	if (cb) {
       
  1773 		luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference);
       
  1774 		luaL_free (cb->L, cb);
       
  1775 	}
       
  1776 	g_free (name);
       
  1777 }
       
  1778 
       
  1779 static void lua_categories_destroy (guint id, gpointer ignore)
  1822 static void lua_categories_destroy (guint id, gpointer ignore)
  1780 {
  1823 {
  1781 	compl_del_category (id);
  1824 	compl_del_category (id);
  1782 }
  1825 }
  1783 
  1826 
  1787 		hk_arg_t args[] = {
  1830 		hk_arg_t args[] = {
  1788 			{ NULL, NULL },
  1831 			{ NULL, NULL },
  1789 		};
  1832 		};
  1790 		hk_run_handlers ("hook-lua-quit", args);
  1833 		hk_run_handlers ("hook-lua-quit", args);
  1791 
  1834 
  1792 		// hook handlers will be unregistered upon objects destruction
  1835 		// hook handlers and commands will be unregistered upon objects destruction
  1793 
  1836 
  1794 		g_slist_foreach (lua_bgreads, (GFunc) lua_bgreads_destroy, NULL);
  1837 		g_slist_foreach (lua_bgreads, (GFunc) lua_bgreads_destroy, NULL);
  1795 		g_slist_free (lua_bgreads);
  1838 		g_slist_free (lua_bgreads);
  1796 		lua_bgreads = NULL;
  1839 		lua_bgreads = NULL;
  1797 
  1840 
  1806 
  1849 
  1807 		g_slist_foreach (lua_added_features, (GFunc) lua_features_destroy, NULL);
  1850 		g_slist_foreach (lua_added_features, (GFunc) lua_features_destroy, NULL);
  1808 		g_slist_free (lua_added_features);
  1851 		g_slist_free (lua_added_features);
  1809 		lua_added_features = NULL;
  1852 		lua_added_features = NULL;
  1810 
  1853 
  1811 		g_slist_foreach (lua_added_commands, (GFunc) lua_commands_destroy, NULL);
  1854 		cmd_del ("lua");
  1812 		g_slist_free (lua_added_commands);
  1855 
  1813 		lua_added_commands = NULL;
  1856 		lua_close (lua);
       
  1857 		lua = NULL;
  1814 
  1858 
  1815 		g_slist_foreach (lua_added_categories, (GFunc) lua_categories_destroy, NULL);
  1859 		g_slist_foreach (lua_added_categories, (GFunc) lua_categories_destroy, NULL);
  1816 		g_slist_free (lua_added_categories);
  1860 		g_slist_free (lua_added_categories);
  1817 		lua_added_categories = NULL;
  1861 		lua_added_categories = NULL;
  1818 
       
  1819 		cmd_del ("lua");
       
  1820 
       
  1821 		lua_close (lua);
       
  1822 		lua = NULL;
       
  1823 
  1862 
  1824 #ifdef LLM_LOG_HANDLER
  1863 #ifdef LLM_LOG_HANDLER
  1825 		// FIXME: shouldn't be here
  1864 		// FIXME: shouldn't be here
  1826 		g_log_remove_handler ("lua-lm", lua_lm_log_handler_id);
  1865 		g_log_remove_handler ("lua-lm", lua_lm_log_handler_id);
  1827 #endif
  1866 #endif