changeset 97 | b00f9ce82016 |
parent 95 | f2f4c7810a72 |
child 98 | 59aeae623ac6 |
96:270ce1cfc823 | 97:b00f9ce82016 |
---|---|
23 #include <lualib.h> |
23 #include <lualib.h> |
24 #include <stdio.h> |
24 #include <stdio.h> |
25 #include <stdlib.h> // getenv |
25 #include <stdlib.h> // getenv |
26 #include <string.h> // strcmp |
26 #include <string.h> // strcmp |
27 |
27 |
28 #include <mcabber/logprint.h> // scr_LogPrint |
28 #include <mcabber/logprint.h> // scr_log_print |
29 #include <mcabber/screen.h> // scr_Beep, scr_WriteIncomingMessage |
29 #include <mcabber/screen.h> // scr_Beep, scr_WriteIncomingMessage |
30 #include <mcabber/hbuf.h> // HBB_PREFIX_INFO |
30 #include <mcabber/hbuf.h> // HBB_PREFIX_INFO |
31 #include <mcabber/commands.h> // process_command, cmd_add, cmd_del |
31 #include <mcabber/commands.h> // process_command, cmd_add, cmd_del |
32 #include <mcabber/xmpp.h> // xmpp_getstatus, xmpp_getstatusmsg, lconnection |
32 #include <mcabber/xmpp.h> // xmpp_getstatus, xmpp_getstatusmsg, lconnection |
33 #include <mcabber/xmpp_helper.h> // xmpp_add_feature, xmpp_del_feature |
33 #include <mcabber/xmpp_helper.h> // xmpp_add_feature, xmpp_del_feature |
58 "Provides command /lua" ) |
58 "Provides command /lua" ) |
59 #endif |
59 #endif |
60 |
60 |
61 static module_info_t info_lua_experimental = { |
61 static module_info_t info_lua_experimental = { |
62 .branch = "experimental", |
62 .branch = "experimental", |
63 .api = 5, |
63 .api = 10, |
64 .version = PROJECT_VERSION, |
64 .version = PROJECT_VERSION, |
65 .description = DESCRIPTION, |
65 .description = DESCRIPTION, |
66 .requires = NULL, |
66 .requires = NULL, |
67 .init = mlua_init, |
67 .init = mlua_init, |
68 .uninit = mlua_uninit, |
68 .uninit = mlua_uninit, |
69 .next = NULL, |
69 .next = NULL, |
70 }; |
70 }; |
71 |
71 |
72 module_info_t info_lua = { |
72 module_info_t info_lua = { |
73 .branch = "dev", |
73 .branch = "dev", |
74 .api = 4, |
74 .api = 11, |
75 .version = PROJECT_VERSION, |
75 .version = PROJECT_VERSION, |
76 .description = DESCRIPTION, |
76 .description = DESCRIPTION, |
77 .requires = NULL, |
77 .requires = NULL, |
78 .init = mlua_init, |
78 .init = mlua_init, |
79 .uninit = mlua_uninit, |
79 .uninit = mlua_uninit, |
126 luaL_addlstring (&B, xbuf, 8); // XXX |
126 luaL_addlstring (&B, xbuf, 8); // XXX |
127 } |
127 } |
128 } |
128 } |
129 luaL_pushresult (&B); |
129 luaL_pushresult (&B); |
130 |
130 |
131 scr_LogPrint (LPRINT_LOGNORM | LPRINT_NOTUTF8, lua_tostring (L, -1)); |
131 scr_log_print (LPRINT_LOGNORM | LPRINT_NOTUTF8, lua_tostring (L, -1)); |
132 return 0; |
132 return 0; |
133 } |
133 } |
134 |
134 |
135 /// dopath |
135 /// dopath |
136 /// Loads lua file from default location. |
136 /// Loads lua file from default location. |
149 char *fname = g_strconcat (name, ".lua", NULL); |
149 char *fname = g_strconcat (name, ".lua", NULL); |
150 path = mcabber_config_filename (fname); |
150 path = mcabber_config_filename (fname); |
151 g_free (fname); |
151 g_free (fname); |
152 } |
152 } |
153 |
153 |
154 if (ret = luaL_loadfile (L, path)) |
154 if ((ret = luaL_loadfile (L, path))) |
155 scr_LogPrint (LPRINT_LOGNORM, "lua: Unable to compile file %s: %s", path, lua_tostring (L, -1)); |
155 scr_log_print (LPRINT_LOGNORM, "lua: Unable to compile file %s: %s", path, lua_tostring (L, -1)); |
156 else if (ret = lua_pcall (L, 0, LUA_MULTRET, 0)) |
156 else if ((ret = lua_pcall (L, 0, LUA_MULTRET, 0))) |
157 scr_LogPrint (LPRINT_LOGNORM, "lua: Runtime error in file %s: %s", path, lua_tostring (L, -1)); |
157 scr_log_print (LPRINT_LOGNORM, "lua: Runtime error in file %s: %s", path, lua_tostring (L, -1)); |
158 g_free (path); |
158 g_free (path); |
159 |
159 |
160 if (ret) |
160 if (ret) |
161 return 1; |
161 return 1; |
162 else |
162 else |
227 /// A: log print type, message, message... |
227 /// A: log print type, message, message... |
228 static int lua_main_log (lua_State *L) |
228 static int lua_main_log (lua_State *L) |
229 { |
229 { |
230 int type = luaL_checkenum_multi (L, 1, lua_lprint); |
230 int type = luaL_checkenum_multi (L, 1, lua_lprint); |
231 lua_concat (L, lua_gettop (L) - 1); |
231 lua_concat (L, lua_gettop (L) - 1); |
232 scr_LogPrint (type, lua_tostring (L, -1)); |
232 scr_log_print (type, lua_tostring (L, -1)); |
233 return 0; |
233 return 0; |
234 } |
234 } |
235 |
235 |
236 // expects table on top |
236 // expects table on top |
237 static void lua_options_callback (char *key, char *value, lua_State *L) |
237 static void lua_options_callback (char *key, char *value, lua_State *L) |
396 static int lua_main_print_info (lua_State *L) |
396 static int lua_main_print_info (lua_State *L) |
397 { |
397 { |
398 char *jid = to_utf8 (luaL_checkstring (L, 1)); |
398 char *jid = to_utf8 (luaL_checkstring (L, 1)); |
399 char *to = jidtodisp (jid); |
399 char *to = jidtodisp (jid); |
400 char *mesg = to_utf8 (luaL_checkstring (L, 2)); |
400 char *mesg = to_utf8 (luaL_checkstring (L, 2)); |
401 scr_WriteIncomingMessage (to, mesg, 0, HBB_PREFIX_INFO, 0); |
401 scr_write_incoming_message (to, mesg, 0, HBB_PREFIX_INFO, 0); |
402 g_free (mesg); |
402 g_free (mesg); |
403 g_free (to); |
403 g_free (to); |
404 g_free (jid); |
404 g_free (jid); |
405 return 0; |
405 return 0; |
406 } |
406 } |
407 |
407 |
408 /// main.beep |
408 /// main.beep |
409 /// Beeps with system speaker. |
409 /// Beeps with system speaker. |
410 static int lua_main_beep (lua_State *L) |
410 static int lua_main_beep (lua_State *L) |
411 { |
411 { |
412 scr_Beep (); |
412 scr_beep (); |
413 return 0; |
413 return 0; |
414 } |
414 } |
415 |
415 |
416 /// main.run |
416 /// main.run |
417 /// Runs specified mcabber command. |
417 /// Runs specified mcabber command. |
462 { |
462 { |
463 if (lua_gettop (L) > 0) { // Set |
463 if (lua_gettop (L) > 0) { // Set |
464 // XXX: we need not convert to utf, RS works on jids/names in locale charset, |
464 // XXX: we need not convert to utf, RS works on jids/names in locale charset, |
465 // but will jidtodisp always correctly work on such tings? |
465 // but will jidtodisp always correctly work on such tings? |
466 char *jid = jidtodisp (luaL_checkstring (L, 1)); |
466 char *jid = jidtodisp (luaL_checkstring (L, 1)); |
467 scr_RosterSearch (jid); |
467 scr_roster_search (jid); |
468 g_free (jid); |
468 g_free (jid); |
469 return 0; |
469 return 0; |
470 } else { // Get |
470 } else { // Get |
471 char *jid = from_utf8 (buddy_getjid (BUDDATA (current_buddy))); |
471 char *jid = from_utf8 (buddy_getjid (BUDDATA (current_buddy))); |
472 lua_pushstring (L, jid); |
472 lua_pushstring (L, jid); |
654 |
654 |
655 lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); |
655 lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); |
656 luaL_pushenum (cb->L, context, lua_event_context); |
656 luaL_pushenum (cb->L, context, lua_event_context); |
657 lua_pushstring (cb -> L, arg); |
657 lua_pushstring (cb -> L, arg); |
658 if (lua_pcall (cb->L, 2, 1, 0)) { |
658 if (lua_pcall (cb->L, 2, 1, 0)) { |
659 scr_LogPrint (LPRINT_LOGNORM, "lua: Event callback execution error: %s", lua_tostring (cb->L, -1)); |
659 scr_log_print (LPRINT_LOGNORM, "lua: Event callback execution error: %s", lua_tostring (cb->L, -1)); |
660 lua_pop (cb->L, 1); |
660 lua_pop (cb->L, 1); |
661 } |
661 } |
662 |
662 |
663 if (lua_toboolean (cb -> L, -1)) |
663 if (lua_toboolean (cb -> L, -1)) |
664 return TRUE; |
664 return TRUE; |
892 luaL_pushargs (cb->L, args); |
892 luaL_pushargs (cb->L, args); |
893 else |
893 else |
894 lua_pushstring (cb->L, args); |
894 lua_pushstring (cb->L, args); |
895 |
895 |
896 if (lua_pcall (cb->L, 1, 0, 0)) { |
896 if (lua_pcall (cb->L, 1, 0, 0)) { |
897 scr_LogPrint (LPRINT_LOGNORM, "lua: Command execution error: %s", lua_tostring (cb->L, -1)); |
897 scr_log_print (LPRINT_LOGNORM, "lua: Command execution error: %s", lua_tostring (cb->L, -1)); |
898 lua_pop (cb->L, 1); |
898 lua_pop (cb->L, 1); |
899 } |
899 } |
900 } |
900 } |
901 |
901 |
902 /// main.parse_args |
902 /// main.parse_args |
961 { |
961 { |
962 guint cid = luaL_checkinteger (L, 1); |
962 guint cid = luaL_checkinteger (L, 1); |
963 char *word = to_utf8 (luaL_checkstring (L, 2)); // XXX |
963 char *word = to_utf8 (luaL_checkstring (L, 2)); // XXX |
964 compl_add_category_word (cid, word); |
964 compl_add_category_word (cid, word); |
965 g_free (word); |
965 g_free (word); |
966 return 0; |
|
966 } |
967 } |
967 |
968 |
968 /// main.del_completion |
969 /// main.del_completion |
969 /// Removes word from a completion list. |
970 /// Removes word from a completion list. |
970 /// A: integer (completion group id), string (word) |
971 /// A: integer (completion group id), string (word) |
972 { |
973 { |
973 guint cid = luaL_checkinteger (L, 1); |
974 guint cid = luaL_checkinteger (L, 1); |
974 char *word = to_utf8 (luaL_checkstring (L, 2)); // XXX |
975 char *word = to_utf8 (luaL_checkstring (L, 2)); // XXX |
975 compl_del_category_word (cid, word); |
976 compl_del_category_word (cid, word); |
976 g_free (word); |
977 g_free (word); |
978 return 0; |
|
977 } |
979 } |
978 |
980 |
979 /// main.command |
981 /// main.command |
980 /// Associates or breaks association between mcabber command name and lua function. |
982 /// Associates or breaks association between mcabber command name and lua function. |
981 /// To unregister command omit function argument. |
983 /// To unregister command omit function argument. |
1069 static gboolean lua_timer_callback (lua_timer_callback_t *cb) |
1071 static gboolean lua_timer_callback (lua_timer_callback_t *cb) |
1070 { |
1072 { |
1071 int ret; |
1073 int ret; |
1072 lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); |
1074 lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); |
1073 if (lua_pcall (cb->L, 0, 1, 0)) { |
1075 if (lua_pcall (cb->L, 0, 1, 0)) { |
1074 scr_LogPrint (LPRINT_LOGNORM, "lua: Timer callback execution error: %s", lua_tostring (cb->L, -1)); |
1076 scr_log_print (LPRINT_LOGNORM, "lua: Timer callback execution error: %s", lua_tostring (cb->L, -1)); |
1075 lua_pop (cb->L, 1); |
1077 lua_pop (cb->L, 1); |
1076 return FALSE; |
1078 return FALSE; |
1077 } |
1079 } |
1078 ret = lua_toboolean (cb->L, -1); |
1080 ret = lua_toboolean (cb->L, -1); |
1079 lua_pop (cb->L, 1); |
1081 lua_pop (cb->L, 1); |
1138 break; |
1140 break; |
1139 |
1141 |
1140 lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); |
1142 lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); |
1141 lua_pushlstring (cb->L, lua_bgread_buffer, read); |
1143 lua_pushlstring (cb->L, lua_bgread_buffer, read); |
1142 if (lua_pcall (cb->L, 1, 1, 0)) { |
1144 if (lua_pcall (cb->L, 1, 1, 0)) { |
1143 scr_LogPrint (LPRINT_LOGNORM, "lua: Bgread callback execution error: %s", lua_tostring (cb->L, -1)); |
1145 scr_log_print (LPRINT_LOGNORM, "lua: Bgread callback execution error: %s", lua_tostring (cb->L, -1)); |
1144 lua_pop (cb->L, 1); |
1146 lua_pop (cb->L, 1); |
1145 return FALSE; |
1147 return FALSE; |
1146 } |
1148 } |
1147 ret = lua_toboolean (cb->L, -1); |
1149 ret = lua_toboolean (cb->L, -1); |
1148 lua_pop (cb->L, 1); |
1150 lua_pop (cb->L, 1); |
1153 |
1155 |
1154 if (condition & ~G_IO_IN) { // err or hup |
1156 if (condition & ~G_IO_IN) { // err or hup |
1155 lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); |
1157 lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); |
1156 lua_pushnil (cb->L); |
1158 lua_pushnil (cb->L); |
1157 if (lua_pcall (cb->L, 1, 1, 0)) { |
1159 if (lua_pcall (cb->L, 1, 1, 0)) { |
1158 scr_LogPrint (LPRINT_LOGNORM, "lua: Bgread callback execution error: %s", lua_tostring (cb->L, -1)); |
1160 scr_log_print (LPRINT_LOGNORM, "lua: Bgread callback execution error: %s", lua_tostring (cb->L, -1)); |
1159 lua_pop (cb->L, 1); |
1161 lua_pop (cb->L, 1); |
1160 return FALSE; |
1162 return FALSE; |
1161 } |
1163 } |
1162 ret = lua_toboolean (cb->L, -1); |
1164 ret = lua_toboolean (cb->L, -1); |
1163 lua_pop (cb->L, 1); |
1165 lua_pop (cb->L, 1); |
1207 // unref? |
1209 // unref? |
1208 |
1210 |
1209 return 0; |
1211 return 0; |
1210 } |
1212 } |
1211 |
1213 |
1212 // MAIN INITIALIZATION CODE |
1214 // HOOKÂ HANDLING |
1213 |
1215 |
1214 #ifdef LLM_LOG_HANDLER |
1216 typedef struct { |
1215 // FIXME: this should not be here |
1217 lua_State *L; // lua environment for handler use |
1216 guint lua_lm_log_handler_id; |
1218 int nameref; // reference to hook name string |
1217 |
1219 int cbref; // reference to hook handler function |
1218 void lua_lm_log_handler (const gchar *domain, GLogLevelFlags log_level, const gchar *message, gpointer ignore) |
1220 int selfref; // self-reference to object |
1219 { |
1221 guint hid; // hook id for object destruction |
1220 if (settings_opt_get_int ("lua_lm_debug")) |
1222 } lua_hook_t; |
1221 scr_LogPrint (LPRINT_LOGNORM, "%s: %s", domain, message); |
1223 |
1222 } |
1224 /// hook handler result |
1223 #endif |
1225 /// What to do with hook processing afterwards |
1224 |
1226 /// G: |
1225 static void do_lua(char *arg, lua_State *L) |
1227 static const string2enum_t lua_hook_handler_result[] = { |
1226 { |
1228 { "proceed", HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS }, |
1227 if (luaL_loadbuffer (L, arg, strlen (arg), "line")) { |
1229 { "stop", HOOK_HANDLER_RESULT_NO_MORE_HANDLER }, |
1228 scr_LogPrint (LPRINT_LOGNORM, "lua: Compilation error: %s", lua_tostring (L, -1)); |
1230 { "drop", HOOK_HANDLER_RESULT_NO_MORE_HANDLER_DROP_DATA }, |
1229 lua_pop (L, 1); |
1231 { NULL, HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS }, |
1230 return; |
1232 }; |
1231 } |
1233 |
1232 |
1234 /// hook handler priority |
1233 if (lua_pcall (L, 0, 0, 0)) { |
1235 /// Feel free to specify just a number instead of some preset value. |
1234 scr_LogPrint (LPRINT_NORMAL, "lua: Runtime error: %s", lua_tostring(L, -1)); |
1236 /// G: |
1235 lua_pop (L, 1); |
1237 static const string2enum_t lua_hook_handler_priority[] = { |
1236 return; |
1238 { "high", G_PRIORITY_HIGH }, |
1237 } |
1239 { "default", G_PRIORITY_DEFAULT }, |
1238 } |
1240 { "idle-high", G_PRIORITY_HIGH_IDLE }, |
1239 |
1241 { "idle", G_PRIORITY_DEFAULT_IDLE }, |
1240 static void lua_hook (guint32 hookid, hk_arg_t *args, lua_State *L) |
1242 { "low", G_PRIORITY_LOW }, |
1241 { |
1243 { NULL, G_PRIORITY_DEFAULT }, |
1242 hk_arg_t *arg = args; |
1244 }; |
1243 const char *hook = settings_opt_get ("lua_hook_function"); |
1245 |
1244 if (!hook) |
1246 /// hook function |
1245 return; |
1247 /// Function to be called, when hook will be processsed. |
1246 lua_getglobal (L, hook); |
1248 /// XXX: we can provide object as argument, but is this necessary? |
1249 /// A: table (arguments hash) |
|
1250 /// R: hook handler result |
|
1251 static guint lua_hook_cb (const gchar *hookid, hk_arg_t *args, gpointer data) |
|
1252 { |
|
1253 lua_hook_t *cb = data; |
|
1254 hk_arg_t *arg = args; |
|
1255 guint ret = HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS; |
|
1256 lua_State *L = cb -> L; |
|
1257 |
|
1258 if (cb -> cbref == LUA_NOREF) |
|
1259 return HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS; |
|
1260 |
|
1261 lua_rawgeti (L, LUA_REGISTRYINDEX, cb -> cbref); |
|
1247 if (!lua_isfunction (L, -1)) { |
1262 if (!lua_isfunction (L, -1)) { |
1248 lua_pop (L, 1); |
1263 lua_pop (L, 1); |
1249 return; |
1264 return HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS; |
1250 } |
1265 } |
1266 |
|
1251 lua_newtable (L); |
1267 lua_newtable (L); |
1268 lua_pushliteral (L, "hook"); |
|
1269 lua_pushstring (L, hookid); |
|
1270 lua_settable (L, -3); |
|
1252 while (arg->name != NULL) { |
1271 while (arg->name != NULL) { |
1253 char *name = from_utf8 (arg->name); |
1272 char *name = from_utf8 (arg->name); |
1254 char *value = from_utf8 (arg->value); |
1273 char *value = from_utf8 (arg->value); |
1255 lua_pushstring (L, name); |
1274 lua_pushstring (L, name); |
1256 lua_pushstring (L, value); |
1275 lua_pushstring (L, value); |
1257 lua_settable (L, -3); |
1276 lua_settable (L, -3); |
1258 g_free (name); |
1277 g_free (name); |
1259 g_free (value); |
1278 g_free (value); |
1260 arg++; |
1279 arg++; |
1261 } |
1280 } |
1262 if (lua_pcall (L, 1, 0, 0)) { |
1281 |
1263 scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook handler: %s", lua_tostring (L, -1)); |
1282 if (lua_pcall (L, 1, 1, 0)) { |
1283 scr_log_print (LPRINT_NORMAL, "lua: Error in hook handler: %s", lua_tostring (L, -1)); |
|
1264 lua_pop (L, 1); |
1284 lua_pop (L, 1); |
1285 } else { |
|
1286 switch (lua_type (L, -1)) { |
|
1287 case LUA_TSTRING: |
|
1288 case LUA_TNUMBER: |
|
1289 ret = luaL_checkenum (L, -1, lua_hook_handler_result); |
|
1290 break; |
|
1291 default: |
|
1292 ret = HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS; |
|
1293 break; |
|
1294 } |
|
1295 lua_pop (L, 1); |
|
1296 } |
|
1297 |
|
1298 return ret; |
|
1299 } |
|
1300 |
|
1301 /// main.hook |
|
1302 /// Installs hook handler, returns an object, that you need to keep until |
|
1303 /// hook handling is no more needed. |
|
1304 /// A: string (hook name), hook function, integer (priority, optional) |
|
1305 /// R: userdata (hook object) |
|
1306 static int lua_main_hook (lua_State *L) |
|
1307 { |
|
1308 const char *hook_name = luaL_checkstring (L, 1); |
|
1309 int priority = G_PRIORITY_DEFAULT; |
|
1310 lua_hook_t *cb; |
|
1311 |
|
1312 luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected"); |
|
1313 |
|
1314 if (lua_gettop (L) > 2) |
|
1315 priority = luaL_checkenum (L, 3, lua_hook_handler_priority); |
|
1316 |
|
1317 cb = lua_newuserdata (L, sizeof (lua_hook_t)); |
|
1318 luaL_getmetatable (L, "mcabber.hook"); |
|
1319 lua_setmetatable (L, -2); |
|
1320 |
|
1321 lua_pushvalue (L, -1); |
|
1322 cb -> selfref = luaL_ref (L, LUA_REGISTRYINDEX); |
|
1323 lua_pushvalue (L, 1); |
|
1324 cb -> nameref = luaL_ref (L, LUA_REGISTRYINDEX); |
|
1325 lua_pushvalue (L, 2); |
|
1326 cb -> cbref = luaL_ref (L, LUA_REGISTRYINDEX); |
|
1327 cb -> L = L; |
|
1328 cb -> hid = hk_add_handler (lua_hook_cb, hook_name, priority, cb); |
|
1329 |
|
1330 return 1; |
|
1331 } |
|
1332 |
|
1333 static void lua_mcabber_unregister_hook (lua_State *L, lua_hook_t *cb) |
|
1334 { |
|
1335 const char *name; |
|
1336 |
|
1337 if (!cb -> hid || cb -> nameref == LUA_NOREF) |
|
1338 return; |
|
1339 |
|
1340 lua_rawgeti (L, LUA_REGISTRYINDEX, cb -> nameref); |
|
1341 name = lua_tostring (L, -1); |
|
1342 if (name) { |
|
1343 hk_del_handler (name, cb -> hid); |
|
1344 cb -> hid = 0; |
|
1345 } |
|
1346 |
|
1347 lua_pop (L, 1); |
|
1348 } |
|
1349 |
|
1350 /// hook:del |
|
1351 /// Unregisters given hook handler from mcabber. Object will be destroyed later. |
|
1352 static int lua_mcabber_hook_del (lua_State *L) |
|
1353 { |
|
1354 lua_hook_t *cb = luaL_checkudata (L, 1, "mcabber.hook"); |
|
1355 luaL_argcheck (L, cb != NULL, 1, "mcabber hook object expected"); |
|
1356 lua_mcabber_unregister_hook (L, cb); |
|
1357 if (cb -> selfref != LUA_NOREF) { |
|
1358 luaL_unref (L, LUA_REGISTRYINDEX, cb -> selfref); |
|
1359 cb -> selfref = LUA_NOREF; |
|
1360 } |
|
1361 return 0; |
|
1362 } |
|
1363 |
|
1364 static int lua_mcabber_hook_gc (lua_State *L) |
|
1365 { |
|
1366 lua_hook_t *cb = luaL_checkudata (L, 1, "mcabber.hook"); |
|
1367 luaL_argcheck (L, cb != NULL, 1, "mcabber hook object expected"); |
|
1368 lua_mcabber_unregister_hook (L, cb); |
|
1369 if (cb -> nameref != LUA_NOREF) |
|
1370 luaL_unref (L, LUA_REGISTRYINDEX, cb -> nameref); |
|
1371 if (cb -> cbref != LUA_NOREF) |
|
1372 luaL_unref (L, LUA_REGISTRYINDEX, cb -> cbref); |
|
1373 return 0; |
|
1374 } |
|
1375 |
|
1376 static const luaL_Reg lua_mcabber_hook_reg_m[] = { |
|
1377 { "del", lua_mcabber_hook_del }, |
|
1378 { "__gc", lua_mcabber_hook_gc }, |
|
1379 { NULL, NULL }, |
|
1380 }; |
|
1381 |
|
1382 static void lua_hook_init (lua_State *L) |
|
1383 { |
|
1384 luaL_newmetatable (L, "mcabber.hook"); |
|
1385 lua_pushvalue (L, -1); |
|
1386 lua_setfield (L, -2, "__index"); |
|
1387 luaL_register (L, NULL, lua_mcabber_hook_reg_m); |
|
1388 lua_pop (L, 1); |
|
1389 } |
|
1390 |
|
1391 #if 0 |
|
1392 // OPTION GUARDS |
|
1393 |
|
1394 GSList *lua_installed_guards = NULL; |
|
1395 |
|
1396 typedef struct { |
|
1397 lua_State *L; // lua environment for handler use |
|
1398 int nameref; // reference to key name string |
|
1399 int cbref; // reference to guard function |
|
1400 // int objref; // self_reference to object |
|
1401 guint hid; // hook id for object destruction |
|
1402 } lua_guard_t; |
|
1403 |
|
1404 /// guard function |
|
1405 /// Function to be called, when option changes it's value. |
|
1406 /// Old option value is still accessible through main.option. |
|
1407 /// A: string (key), string (new value) |
|
1408 /// R: string (value to save in hash table) |
|
1409 static gchar *lua_guard_cb (const gchar *key, const gchar *value) |
|
1410 { |
|
1411 lua_guard_t *cb = ;// FIXME |
|
1412 lua_State *L = cb -> L; |
|
1413 |
|
1414 if (cb -> cbref == LUA_NOREF) |
|
1415 return g_strdup (value); |
|
1416 |
|
1417 lua_rawgeti (L, LUA_REGISTRYINDEX, cb -> cbref); |
|
1418 if (!lua_isfunction (L, -1)) { |
|
1419 lua_pop (L, 1); |
|
1420 return g_strdup (value); |
|
1421 } |
|
1422 |
|
1423 lua_pushstring (L, key); |
|
1424 lua_psuhstring (L, value); |
|
1425 |
|
1426 if (lua_pcall (L, 2, 1, 0)) { |
|
1427 scr_log_print (LPRINT_NORMAL, "lua: Error in hook handler: %s", lua_tostring (L, -1)); |
|
1428 lua_pop (L, 1); |
|
1429 return g_strdup (value); |
|
1430 } |
|
1431 |
|
1432 return g_strdup (lua_tostring (L, -1)); |
|
1433 } |
|
1434 |
|
1435 /// main.guard |
|
1436 /// Installs option guard for given option. Returns guard object, that |
|
1437 /// should be kept around as long, as guard is needed. |
|
1438 /// A: string (option name), guard function |
|
1439 /// R: userdata (guard object) |
|
1440 static int lua_main_guard (lua_State *L) |
|
1441 { |
|
1442 const char *name = luaL_checkstring (L, 1); |
|
1443 int priority = G_PRIORITY_DEFAULT; |
|
1444 lua_guard_t *cb; |
|
1445 |
|
1446 luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected"); |
|
1447 |
|
1448 cb = lua_newuserdata (L, sizeof (lua_guard_t)); |
|
1449 luaL_getmetatable (L, "mcabber.guard"); |
|
1450 lua_setmetatable (L, -2); |
|
1451 |
|
1452 lua_pushvalue (L, 1); |
|
1453 cb -> nameref = luaL_ref (L, LUA_REGISTRYINDEX); |
|
1454 lua_pushvalue (L, 2); |
|
1455 cb -> cbref = luaL_ref (L, LUA_REGISTRYINDEX); |
|
1456 cb -> L = L; |
|
1457 |
|
1458 settings_set_guard (name, lua_guard_cb) |
|
1459 |
|
1460 return 1; |
|
1461 } |
|
1462 |
|
1463 static void lua_mcabber_unregister_guard (lua_State *L, lua_guard_t *cb) |
|
1464 { |
|
1465 const char *name; |
|
1466 |
|
1467 if (cb -> nameref == LUA_NOREF) |
|
1468 return; |
|
1469 |
|
1470 lua_rawgeti (L, LUA_REGISTRYINDEX, cb -> nameref); |
|
1471 name = lua_tostring (L, -1); |
|
1472 if (name) { |
|
1473 settings_del_guard (name); |
|
1474 luaL_unref (L, LUA_REGISTRYINDEX, cb -> nameref); |
|
1475 cb -> nameref = LUA_NOREF; |
|
1476 } |
|
1477 |
|
1478 lua_pop (L, 1); |
|
1479 } |
|
1480 |
|
1481 /// guard:del |
|
1482 /// Unregisters given option guard from mcabber. Object will be destroyed later. |
|
1483 static int lua_mcabber_guard_del (lua_State *L) |
|
1484 { |
|
1485 lua_guard_t *cb = luaL_checkudata (L, 1, "mcabber.guard"); |
|
1486 luaL_argcheck (L, cb != NULL, 1, "mcabber guard object expected"); |
|
1487 lua_mcabber_unregister_guard (L, cb); |
|
1488 return 0; |
|
1489 } |
|
1490 |
|
1491 static int lua_mcabber_guard_gc (lua_State *L) |
|
1492 { |
|
1493 lua_hook_t *cb = luaL_checkudata (L, 1, "mcabber.guard"); |
|
1494 luaL_argcheck (L, cb != NULL, 1, "mcabber guard object expected"); |
|
1495 lua_mcabber_unregister_guard (L, cb); |
|
1496 if (cb -> cbref != LUA_NOREF) |
|
1497 luaL_unref (L, LUA_REGISTRYINDEX, cb -> cbref); |
|
1498 return 0; |
|
1499 } |
|
1500 |
|
1501 static const luaL_Reg lua_mcabber_hook_reg_m[] = { |
|
1502 { "del", lua_mcabber_guard_del }, |
|
1503 { "__gc", lua_mcabber_guard_gc }, |
|
1504 { NULL, NULL }, |
|
1505 }; |
|
1506 |
|
1507 static void lua_guard_init (lua_State *L) |
|
1508 { |
|
1509 luaL_newmetatable (L, "mcabber.guard"); |
|
1510 lua_pushvalue (L, -1); |
|
1511 lua_setfield (L, -2, "__index"); |
|
1512 luaL_register (L, NULL, lua_mcabber_guard_reg_m); |
|
1513 lua_pop (L, 1); |
|
1514 } |
|
1515 |
|
1516 static void lua_guard_uninit (lua_State *L) |
|
1517 { |
|
1518 } |
|
1519 #endif |
|
1520 |
|
1521 // MAIN INITIALIZATION CODE |
|
1522 |
|
1523 #ifdef LLM_LOG_HANDLER |
|
1524 // FIXME: this should not be here |
|
1525 guint lua_lm_log_handler_id; |
|
1526 |
|
1527 void lua_lm_log_handler (const gchar *domain, GLogLevelFlags log_level, const gchar *message, gpointer ignore) |
|
1528 { |
|
1529 if (settings_opt_get_int ("lua_lm_debug")) |
|
1530 scr_log_print (LPRINT_LOGNORM, "%s: %s", domain, message); |
|
1531 } |
|
1532 #endif |
|
1533 |
|
1534 static void do_lua(char *arg, lua_State *L) |
|
1535 { |
|
1536 if (luaL_loadbuffer (L, arg, strlen (arg), "line")) { |
|
1537 scr_log_print (LPRINT_LOGNORM, "lua: Compilation error: %s", lua_tostring (L, -1)); |
|
1538 lua_pop (L, 1); |
|
1539 return; |
|
1540 } |
|
1541 |
|
1542 if (lua_pcall (L, 0, 0, 0)) { |
|
1543 scr_log_print (LPRINT_NORMAL, "lua: Runtime error: %s", lua_tostring(L, -1)); |
|
1544 lua_pop (L, 1); |
|
1545 return; |
|
1265 } |
1546 } |
1266 } |
1547 } |
1267 |
1548 |
1268 static void *lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { |
1549 static void *lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { |
1269 if (nsize == 0) { |
1550 if (nsize == 0) { |
1301 reg ( roster ) |
1582 reg ( roster ) |
1302 reg ( current_buddy ) |
1583 reg ( current_buddy ) |
1303 reg ( full_jid ) |
1584 reg ( full_jid ) |
1304 reg ( buddy_info ) |
1585 reg ( buddy_info ) |
1305 reg ( timer ) |
1586 reg ( timer ) |
1587 reg ( alias ) |
|
1588 reg ( binding ) |
|
1589 reg ( fileoption ) |
|
1590 reg ( add_feature ) |
|
1591 reg ( del_feature ) |
|
1592 reg ( event ) |
|
1593 reg ( parse_args ) |
|
1594 reg ( add_category ) |
|
1595 reg ( del_category ) |
|
1596 reg ( add_completion ) |
|
1597 reg ( del_completion ) |
|
1598 reg ( command ) |
|
1599 reg ( print_info ) |
|
1600 reg ( beep ) |
|
1601 reg ( run ) |
|
1602 reg ( status ) |
|
1603 reg ( roster ) |
|
1604 reg ( current_buddy ) |
|
1605 reg ( full_jid ) |
|
1606 reg ( buddy_info ) |
|
1607 reg ( timer ) |
|
1306 reg ( bgread ) |
1608 reg ( bgread ) |
1609 reg ( hook ) |
|
1307 { NULL, NULL }, |
1610 { NULL, NULL }, |
1308 }; |
1611 }; |
1309 #undef reg |
1612 #undef reg |
1310 |
1613 |
1311 const gchar *g_module_check_init (GModule *module) |
1614 const gchar *g_module_check_init (GModule *module) |
1353 #ifdef LLM_LOG_HANDLER |
1656 #ifdef LLM_LOG_HANDLER |
1354 // FIXME: this should not be here. |
1657 // FIXME: this should not be here. |
1355 lua_lm_log_handler_id = g_log_set_handler ("lua-lm", G_LOG_LEVEL_MASK, (GLogFunc) lua_lm_log_handler, NULL); |
1658 lua_lm_log_handler_id = g_log_set_handler ("lua-lm", G_LOG_LEVEL_MASK, (GLogFunc) lua_lm_log_handler, NULL); |
1356 #endif |
1659 #endif |
1357 |
1660 |
1661 lua_hook_init (lua); |
|
1662 |
|
1358 { |
1663 { |
1359 char *initfile = expand_filename (settings_opt_get ("lua_init_filename")); |
1664 char *initfile = expand_filename (settings_opt_get ("lua_init_filename")); |
1360 |
1665 |
1361 if (!initfile) |
1666 if (!initfile) |
1362 scr_LogPrint (LPRINT_LOGNORM, "lua: Cannot determine config file name"); |
1667 scr_log_print (LPRINT_LOGNORM, "lua: Cannot determine config file name"); |
1363 else { |
1668 else { |
1364 if (luaL_loadfile(lua, initfile)) { |
1669 if (luaL_loadfile(lua, initfile)) { |
1365 scr_LogPrint (LPRINT_LOGNORM, "lua: Unable to compile rc file: %s", lua_tostring (lua, -1)); |
1670 scr_log_print (LPRINT_LOGNORM, "lua: Unable to compile rc file: %s", lua_tostring (lua, -1)); |
1366 lua_pop (lua, 1); |
1671 lua_pop (lua, 1); |
1367 } else if (lua_pcall (lua, 0, LUA_MULTRET, 0)) { |
1672 } else if (lua_pcall (lua, 0, LUA_MULTRET, 0)) { |
1368 scr_LogPrint (LPRINT_LOGNORM, "lua: Runtime error in rc file: %s", lua_tostring(lua, -1)); |
1673 scr_log_print (LPRINT_LOGNORM, "lua: Runtime error in rc file: %s", lua_tostring(lua, -1)); |
1369 lua_pop (lua, 1); |
1674 lua_pop (lua, 1); |
1370 } else |
1675 } else |
1371 scr_LogPrint (LPRINT_LOGNORM, "lua: Loaded %s", initfile); |
1676 scr_log_print (LPRINT_LOGNORM, "lua: Loaded %s", initfile); |
1372 g_free (initfile); |
1677 g_free (initfile); |
1373 } |
1678 } |
1374 } |
1679 } |
1375 |
|
1376 hk_add_handler ((hk_handler_t) lua_hook, ~((guint32)0), lua); |
|
1377 |
1680 |
1378 { |
1681 { |
1379 hk_arg_t args[] = { |
1682 hk_arg_t args[] = { |
1380 { "hook", "hook-start" }, |
1683 { NULL, NULL }, |
1381 { NULL, NULL }, |
|
1382 }; |
1684 }; |
1383 lua_hook (0, args, lua); |
1685 hk_run_handlers("hook-lua-start", args); |
1384 } |
1686 } |
1385 } |
1687 } |
1386 |
1688 |
1387 static void lua_events_cancel (gpointer data, gpointer ignore) |
1689 static void lua_events_cancel (gpointer data, gpointer ignore) |
1388 { |
1690 { |
1439 |
1741 |
1440 static void mlua_uninit (void) |
1742 static void mlua_uninit (void) |
1441 { |
1743 { |
1442 if (lua) { |
1744 if (lua) { |
1443 hk_arg_t args[] = { |
1745 hk_arg_t args[] = { |
1444 { "hook", "hook-quit" }, |
1746 { NULL, NULL }, |
1445 { NULL, NULL }, |
|
1446 }; |
1747 }; |
1447 lua_hook (0, args, lua); |
1748 hk_run_handlers ("hook-lua-quit", args); |
1448 |
1749 |
1449 hk_del_handler ((hk_handler_t) lua_hook, lua); |
1750 // hook handlers will be unregistered upon objects destruction |
1450 |
1751 |
1451 g_slist_foreach (lua_bgreads, (GFunc) lua_bgreads_destroy, NULL); |
1752 g_slist_foreach (lua_bgreads, (GFunc) lua_bgreads_destroy, NULL); |
1452 g_slist_free (lua_bgreads); |
1753 g_slist_free (lua_bgreads); |
1453 lua_bgreads = NULL; |
1754 lua_bgreads = NULL; |
1454 |
1755 |