diff options
Diffstat (limited to 'src')
28 files changed, 2122 insertions, 717 deletions
diff --git a/src/core/wee-hashtable.c b/src/core/wee-hashtable.c index bc44f1c13..0f4d91601 100644 --- a/src/core/wee-hashtable.c +++ b/src/core/wee-hashtable.c @@ -38,7 +38,9 @@ char *hashtable_type_string[HASHTABLE_NUM_TYPES] = -{ "integer", "string", "pointer", "buffer", "time" }; +{ WEECHAT_HASHTABLE_INTEGER, WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, WEECHAT_HASHTABLE_BUFFER, + WEECHAT_HASHTABLE_TIME }; /* @@ -403,6 +405,24 @@ hashtable_get_integer (struct t_hashtable *hashtable, const char *property) } /* + * hashtable_get_string: get a hashtable property as string + */ + +const char * +hashtable_get_string (struct t_hashtable *hashtable, const char *property) +{ + if (hashtable && property) + { + if (string_strcasecmp (property, "type_keys") == 0) + return hashtable_type_string[hashtable->type_keys]; + else if (string_strcasecmp (property, "type_values") == 0) + return hashtable_type_string[hashtable->type_values]; + } + + return NULL; +} + +/* * hashtable_add_to_infolist: add hashtable keys and values to infolist * return 1 if ok, 0 if error */ diff --git a/src/core/wee-hashtable.h b/src/core/wee-hashtable.h index 33dc7c11c..ab901528b 100644 --- a/src/core/wee-hashtable.h +++ b/src/core/wee-hashtable.h @@ -115,6 +115,8 @@ extern void hashtable_map (struct t_hashtable *hashtable, void *callback_map_data); extern int hashtable_get_integer (struct t_hashtable *hashtable, const char *property); +extern const char *hashtable_get_string (struct t_hashtable *hashtable, + const char *property); extern int hashtable_add_to_infolist (struct t_hashtable *hashtable, struct t_infolist_item *infolist_item, const char *prefix); diff --git a/src/core/wee-hook.c b/src/core/wee-hook.c index d5e26b6fb..d49732ff4 100644 --- a/src/core/wee-hook.c +++ b/src/core/wee-hook.c @@ -36,6 +36,7 @@ #include "weechat.h" #include "wee-hook.h" +#include "wee-hashtable.h" #include "wee-infolist.h" #include "wee-list.h" #include "wee-log.h" @@ -52,7 +53,8 @@ char *hook_type_string[HOOK_NUM_TYPES] = { "command", "command_run", "timer", "fd", "process", "connect", "print", - "signal", "config", "completion", "modifier", "info", "infolist" }; + "signal", "config", "completion", "modifier", "info", "info_hashtable", + "infolist" }; struct t_hook *weechat_hooks[HOOK_NUM_TYPES]; /* list of hooks */ struct t_hook *last_weechat_hook[HOOK_NUM_TYPES]; /* last hook */ int hook_exec_recursion = 0; /* 1 when a hook is executed */ @@ -2188,7 +2190,7 @@ hook_info (struct t_weechat_plugin *plugin, const char *info_name, } /* - * hook_info_get: get info via info hook + * hook_info_get: get info (as string) via info hook */ const char * @@ -2235,6 +2237,101 @@ hook_info_get (struct t_weechat_plugin *plugin, const char *info_name, } /* + * hook_info_hashtable: hook an info using hashtable + */ + +struct t_hook * +hook_info_hashtable (struct t_weechat_plugin *plugin, const char *info_name, + const char *description, const char *args_description, + const char *output_description, + t_hook_callback_info_hashtable *callback, + void *callback_data) +{ + struct t_hook *new_hook; + struct t_hook_info_hashtable *new_hook_info_hashtable; + int priority; + const char *ptr_info_name; + + if (!info_name || !info_name[0] || !callback) + return NULL; + + new_hook = malloc (sizeof (*new_hook)); + if (!new_hook) + return NULL; + new_hook_info_hashtable = malloc (sizeof (*new_hook_info_hashtable)); + if (!new_hook_info_hashtable) + { + free (new_hook); + return NULL; + } + + hook_get_priority_and_name (info_name, &priority, &ptr_info_name); + hook_init_data (new_hook, plugin, HOOK_TYPE_INFO_HASHTABLE, priority, + callback_data); + + new_hook->hook_data = new_hook_info_hashtable; + new_hook_info_hashtable->callback = callback; + new_hook_info_hashtable->info_name = strdup ((ptr_info_name) ? + ptr_info_name : info_name); + new_hook_info_hashtable->description = strdup ((description) ? description : ""); + new_hook_info_hashtable->args_description = strdup ((args_description) ? + args_description : ""); + new_hook_info_hashtable->output_description = strdup ((output_description) ? + output_description : ""); + + hook_add_to_list (new_hook); + + return new_hook; +} + +/* + * hook_info_get_hashtable: get info (as hashtable) via info hook + */ + +struct t_hashtable * +hook_info_get_hashtable (struct t_weechat_plugin *plugin, const char *info_name, + struct t_hashtable *hashtable) +{ + struct t_hook *ptr_hook, *next_hook; + struct t_hashtable *value; + + /* make C compiler happy */ + (void) plugin; + + if (!info_name || !info_name[0]) + return NULL; + + hook_exec_start (); + + ptr_hook = weechat_hooks[HOOK_TYPE_INFO_HASHTABLE]; + while (ptr_hook) + { + next_hook = ptr_hook->next_hook; + + if (!ptr_hook->deleted + && !ptr_hook->running + && (string_strcasecmp (HOOK_INFO_HASHTABLE(ptr_hook, info_name), + info_name) == 0)) + { + ptr_hook->running = 1; + value = (HOOK_INFO_HASHTABLE(ptr_hook, callback)) + (ptr_hook->callback_data, info_name, hashtable); + ptr_hook->running = 0; + + hook_exec_end (); + return value; + } + + ptr_hook = next_hook; + } + + hook_exec_end (); + + /* info not found */ + return NULL; +} + +/* * hook_infolist: hook an infolist */ @@ -2478,6 +2575,16 @@ unhook (struct t_hook *hook) if (HOOK_INFO(hook, args_description)) free (HOOK_INFO(hook, args_description)); break; + case HOOK_TYPE_INFO_HASHTABLE: + if (HOOK_INFO_HASHTABLE(hook, info_name)) + free (HOOK_INFO_HASHTABLE(hook, info_name)); + if (HOOK_INFO_HASHTABLE(hook, description)) + free (HOOK_INFO_HASHTABLE(hook, description)); + if (HOOK_INFO_HASHTABLE(hook, args_description)) + free (HOOK_INFO_HASHTABLE(hook, args_description)); + if (HOOK_INFO_HASHTABLE(hook, output_description)) + free (HOOK_INFO_HASHTABLE(hook, output_description)); + break; case HOOK_TYPE_INFOLIST: if (HOOK_INFOLIST(hook, infolist_name)) free (HOOK_INFOLIST(hook, infolist_name)); @@ -2815,6 +2922,36 @@ hook_add_to_infolist_type (struct t_infolist *infolist, return 0; } break; + case HOOK_TYPE_INFO_HASHTABLE: + if (!ptr_hook->deleted) + { + if (!infolist_new_var_pointer (ptr_item, "callback", HOOK_INFO_HASHTABLE(ptr_hook, callback))) + return 0; + if (!infolist_new_var_string (ptr_item, "info_name", HOOK_INFO_HASHTABLE(ptr_hook, info_name))) + return 0; + if (!infolist_new_var_string (ptr_item, "description", HOOK_INFO_HASHTABLE(ptr_hook, description))) + return 0; + if (!infolist_new_var_string (ptr_item, "description_nls", + (HOOK_INFO_HASHTABLE(ptr_hook, description) + && HOOK_INFO_HASHTABLE(ptr_hook, description)[0]) ? + _(HOOK_INFO_HASHTABLE(ptr_hook, description)) : "")) + return 0; + if (!infolist_new_var_string (ptr_item, "args_description", HOOK_INFO_HASHTABLE(ptr_hook, args_description))) + return 0; + if (!infolist_new_var_string (ptr_item, "args_description_nls", + (HOOK_INFO_HASHTABLE(ptr_hook, args_description) + && HOOK_INFO_HASHTABLE(ptr_hook, args_description)[0]) ? + _(HOOK_INFO_HASHTABLE(ptr_hook, args_description)) : "")) + return 0; + if (!infolist_new_var_string (ptr_item, "output_description", HOOK_INFO_HASHTABLE(ptr_hook, output_description))) + return 0; + if (!infolist_new_var_string (ptr_item, "output_description_nls", + (HOOK_INFO_HASHTABLE(ptr_hook, output_description) + && HOOK_INFO_HASHTABLE(ptr_hook, output_description)[0]) ? + _(HOOK_INFO_HASHTABLE(ptr_hook, output_description)) : "")) + return 0; + } + break; case HOOK_TYPE_INFOLIST: if (!ptr_hook->deleted) { @@ -3079,6 +3216,17 @@ hook_print_log () log_printf (" args_description. . . : '%s'", HOOK_INFO(ptr_hook, args_description)); } break; + case HOOK_TYPE_INFO_HASHTABLE: + if (!ptr_hook->deleted) + { + log_printf (" info_hashtable data:"); + log_printf (" callback. . . . . . . : 0x%lx", HOOK_INFO_HASHTABLE(ptr_hook, callback)); + log_printf (" info_name . . . . . . : '%s'", HOOK_INFO_HASHTABLE(ptr_hook, info_name)); + log_printf (" description . . . . . : '%s'", HOOK_INFO_HASHTABLE(ptr_hook, description)); + log_printf (" args_description. . . : '%s'", HOOK_INFO_HASHTABLE(ptr_hook, args_description)); + log_printf (" output_description. . : '%s'", HOOK_INFO_HASHTABLE(ptr_hook, output_description)); + } + break; case HOOK_TYPE_INFOLIST: if (!ptr_hook->deleted) { diff --git a/src/core/wee-hook.h b/src/core/wee-hook.h index 7a10b8ad3..2e2b735d6 100644 --- a/src/core/wee-hook.h +++ b/src/core/wee-hook.h @@ -28,6 +28,7 @@ struct t_gui_buffer; struct t_gui_line; struct t_gui_completion; struct t_weelist; +struct t_hashtable; struct t_infolist; /* hook types */ @@ -46,6 +47,7 @@ enum t_hook_type HOOK_TYPE_COMPLETION, /* custom completions */ HOOK_TYPE_MODIFIER, /* string modifier */ HOOK_TYPE_INFO, /* get some info as string */ + HOOK_TYPE_INFO_HASHTABLE, /* get some info as hashtable */ HOOK_TYPE_INFOLIST, /* get some info as infolist */ /* number of hook types */ HOOK_NUM_TYPES, @@ -78,6 +80,7 @@ enum t_hook_type #define HOOK_COMPLETION(hook, var) (((struct t_hook_completion *)hook->hook_data)->var) #define HOOK_MODIFIER(hook, var) (((struct t_hook_modifier *)hook->hook_data)->var) #define HOOK_INFO(hook, var) (((struct t_hook_info *)hook->hook_data)->var) +#define HOOK_INFO_HASHTABLE(hook, var) (((struct t_hook_info_hashtable *)hook->hook_data)->var) #define HOOK_INFOLIST(hook, var) (((struct t_hook_infolist *)hook->hook_data)->var) struct t_hook @@ -300,6 +303,21 @@ struct t_hook_info char *args_description; /* description of arguments */ }; +/* hook info (hashtable) */ + +typedef struct t_hashtable *(t_hook_callback_info_hashtable)(void *data, + const char *info_name, + struct t_hashtable *hashtable); + +struct t_hook_info_hashtable +{ + t_hook_callback_info_hashtable *callback; /* info_hashtable callback */ + char *info_name; /* name of info returned */ + char *description; /* description */ + char *args_description; /* description of arguments */ + char *output_description; /* description of output (hashtable) */ +}; + /* hook infolist */ typedef struct t_infolist *(t_hook_callback_infolist)(void *data, @@ -425,6 +443,16 @@ extern struct t_hook *hook_info (struct t_weechat_plugin *plugin, extern const char *hook_info_get (struct t_weechat_plugin *plugin, const char *info_name, const char *arguments); +extern struct t_hook *hook_info_hashtable (struct t_weechat_plugin *plugin, + const char *info_name, + const char *description, + const char *args_description, + const char *output_description, + t_hook_callback_info_hashtable *callback, + void *callback_data); +extern struct t_hashtable *hook_info_get_hashtable (struct t_weechat_plugin *plugin, + const char *info_name, + struct t_hashtable *hashtable); extern struct t_hook *hook_infolist (struct t_weechat_plugin *plugin, const char *infolist_name, const char *description, diff --git a/src/core/wee-string.c b/src/core/wee-string.c index 8e3fdb66b..da30195f4 100644 --- a/src/core/wee-string.c +++ b/src/core/wee-string.c @@ -377,7 +377,7 @@ string_replace (const char *string, const char *search, const char *replace) if (!new_string) return strdup (string); - /* replace all occurences */ + /* replace all occurrences */ new_string[0] = '\0'; while (string && string[0]) { diff --git a/src/plugins/irc/irc-info.c b/src/plugins/irc/irc-info.c index 4f1602e1a..3a6c8849a 100644 --- a/src/plugins/irc/irc-info.c +++ b/src/plugins/irc/irc-info.c @@ -229,6 +229,38 @@ irc_info_get_info_cb (void *data, const char *info_name, } /* + * irc_info_get_info_hashtable_cb: callback called when IRC info_hashtable is + * asked + */ + +struct t_hashtable * +irc_info_get_info_hashtable_cb (void *data, const char *info_name, + struct t_hashtable *hashtable) +{ + const char *message; + struct t_hashtable *value; + + /* make C compiler happy */ + (void) data; + + if (weechat_strcasecmp (info_name, "irc_parse_message") == 0) + { + if (hashtable) + { + message = (const char *)weechat_hashtable_get (hashtable, + "message"); + if (message) + { + value = irc_server_parse_message_to_hashtable (message); + return value; + } + } + } + + return NULL; +} + +/* * irc_info_get_infolist_cb: callback called when IRC infolist is asked */ @@ -448,48 +480,71 @@ void irc_info_init () { /* info hooks */ - weechat_hook_info ("irc_is_channel", N_("1 if string is a valid IRC channel name"), + weechat_hook_info ("irc_is_channel", + N_("1 if string is a valid IRC channel name"), N_("channel name"), &irc_info_get_info_cb, NULL); - weechat_hook_info ("irc_is_nick", N_("1 if string is a valid IRC nick name"), + weechat_hook_info ("irc_is_nick", + N_("1 if string is a valid IRC nick name"), N_("nickname"), &irc_info_get_info_cb, NULL); - weechat_hook_info ("irc_nick", N_("get current nick on a server"), + weechat_hook_info ("irc_nick", + N_("get current nick on a server"), N_("server name"), &irc_info_get_info_cb, NULL); - weechat_hook_info ("irc_nick_from_host", N_("get nick from IRC host"), + weechat_hook_info ("irc_nick_from_host", + N_("get nick from IRC host"), N_("IRC host (like `:nick!name@server.com`)"), &irc_info_get_info_cb, NULL); - weechat_hook_info ("irc_nick_color", N_("get nick color code"), + weechat_hook_info ("irc_nick_color", + N_("get nick color code"), N_("nickname"), &irc_info_get_info_cb, NULL); - weechat_hook_info ("irc_nick_color_name", N_("get nick color name"), + weechat_hook_info ("irc_nick_color_name", + N_("get nick color name"), N_("nickname"), &irc_info_get_info_cb, NULL); - weechat_hook_info ("irc_buffer", N_("get buffer pointer for an IRC server/channel/nick"), + weechat_hook_info ("irc_buffer", + N_("get buffer pointer for an IRC server/channel/nick"), N_("server,channel,nick (channel and nicks are optional)"), &irc_info_get_info_cb, NULL); - weechat_hook_info ("irc_server_isupport", N_("1 if server supports this feature (from IRC message 005)"), + weechat_hook_info ("irc_server_isupport", + N_("1 if server supports this feature (from IRC message 005)"), N_("server,feature"), &irc_info_get_info_cb, NULL); - weechat_hook_info ("irc_server_isupport_value", N_("value of feature, if supported by server (from IRC message 005)"), + weechat_hook_info ("irc_server_isupport_value", + N_("value of feature, if supported by server (from IRC message 005)"), N_("server,feature"), &irc_info_get_info_cb, NULL); + /* info_hashtable hooks */ + weechat_hook_info_hashtable ("irc_parse_message", + N_("parse an IRC message"), + N_("\"message\": IRC message"), + /* TRANSLATORS: please do not translate key names (enclosed by quotes) */ + N_("\"nick\": nick, \"host\": host, " + "\"command\": command, \"channel\": channel, " + "\"arguments\": arguments (includes channel)"), + &irc_info_get_info_hashtable_cb, NULL); + /* infolist hooks */ - weechat_hook_infolist ("irc_server", N_("list of IRC servers"), + weechat_hook_infolist ("irc_server", + N_("list of IRC servers"), N_("server pointer (optional)"), N_("server name (can start or end with \"*\" as wildcard) (optional)"), &irc_info_get_infolist_cb, NULL); - weechat_hook_infolist ("irc_channel", N_("list of channels for an IRC server"), + weechat_hook_infolist ("irc_channel", + N_("list of channels for an IRC server"), N_("channel pointer (optional)"), N_("server name"), &irc_info_get_infolist_cb, NULL); - weechat_hook_infolist ("irc_nick", N_("list of nicks for an IRC channel"), + weechat_hook_infolist ("irc_nick", + N_("list of nicks for an IRC channel"), N_("nick pointer (optional)"), N_("server,channel,nick (channel and nick are optional)"), &irc_info_get_infolist_cb, NULL); - weechat_hook_infolist ("irc_ignore", N_("list of IRC ignores"), + weechat_hook_infolist ("irc_ignore", + N_("list of IRC ignores"), N_("ignore pointer (optional)"), NULL, &irc_info_get_infolist_cb, NULL); diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c index 75b117902..9c6322b31 100644 --- a/src/plugins/irc/irc-server.c +++ b/src/plugins/irc/irc-server.c @@ -1215,6 +1215,9 @@ irc_server_parse_message (const char *message, char **nick, char **host, if (arguments) *arguments = NULL; + if (!message) + return; + /* * we will use this message as example: * :FlashCode!n=FlashCod@host.com PRIVMSG #channel :hello! @@ -1324,6 +1327,46 @@ irc_server_parse_message (const char *message, char **nick, char **host, } /* + * irc_server_parse_message_to_hashtable: parse IRC message and return hashtable + * with keys: nick, host, command, + * channel, arguments + * Note: hashtable has to be free() + * after use + */ + +struct t_hashtable * +irc_server_parse_message_to_hashtable (const char *message) +{ + char *nick, *host, *command, *channel, *arguments; + char empty_str[1] = { '\0' }; + struct t_hashtable *hashtable; + + irc_server_parse_message (message, &nick, &host, &command, &channel, + &arguments); + + hashtable = weechat_hashtable_new (8, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); + if (!hashtable) + return NULL; + + weechat_hashtable_set (hashtable, "nick", + (nick) ? (void *)nick : (void *)empty_str); + weechat_hashtable_set (hashtable, "host", + (host) ? (void *)host : (void *)empty_str); + weechat_hashtable_set (hashtable, "command", + (command) ? (void *)command : (void *)empty_str); + weechat_hashtable_set (hashtable, "channel", + (channel) ? (void *)channel : (void *)empty_str); + weechat_hashtable_set (hashtable, "arguments", + (arguments) ? (void *)arguments : (void *)empty_str); + + return hashtable; +} + +/* * irc_server_send_one_msg: send one message to IRC server * if queue_msg > 0, then messages are in a queue and * sent slowly (to be sure there will not be any diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h index 8ca2615f8..02e6a8134 100644 --- a/src/plugins/irc/irc-server.h +++ b/src/plugins/irc/irc-server.h @@ -203,6 +203,7 @@ extern int irc_server_rename (struct t_irc_server *server, const char *new_name) extern void irc_server_send_signal (struct t_irc_server *server, const char *signal, const char *command, const char *full_message); +extern struct t_hashtable *irc_server_parse_message_to_hashtable (const char *message); extern void irc_server_sendf (struct t_irc_server *server, int queue_msg, const char *format, ...); extern struct t_irc_server *irc_server_search (const char *server_name); diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 5317e4f14..a66769b7a 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -527,6 +527,7 @@ plugin_load (const char *filename) new_plugin->hashtable_get = &hashtable_get; new_plugin->hashtable_map = &hashtable_map; new_plugin->hashtable_get_integer = &hashtable_get_integer; + new_plugin->hashtable_get_string = &hashtable_get_string; new_plugin->hashtable_add_to_infolist = &hashtable_add_to_infolist; new_plugin->hashtable_remove = &hashtable_remove; new_plugin->hashtable_remove_all = &hashtable_remove_all; @@ -592,6 +593,7 @@ plugin_load (const char *filename) new_plugin->hook_modifier = &hook_modifier; new_plugin->hook_modifier_exec = &hook_modifier_exec; new_plugin->hook_info = &hook_info; + new_plugin->hook_info_hashtable = &hook_info_hashtable; new_plugin->hook_infolist = &hook_infolist; new_plugin->unhook = &unhook; new_plugin->unhook_all = &unhook_all_plugin; @@ -639,6 +641,7 @@ plugin_load (const char *filename) new_plugin->network_connect_to = &network_connect_to; new_plugin->info_get = &hook_info_get; + new_plugin->info_get_hashtable = &hook_info_get_hashtable; new_plugin->infolist_new = &infolist_new; new_plugin->infolist_new_item = &infolist_new_item; diff --git a/src/plugins/scripts/lua/weechat-lua-api.c b/src/plugins/scripts/lua/weechat-lua-api.c index 7a5de5bd7..1c38cc2c7 100644 --- a/src/plugins/scripts/lua/weechat-lua-api.c +++ b/src/plugins/scripts/lua/weechat-lua-api.c @@ -1218,7 +1218,8 @@ weechat_lua_api_config_reload_cb (void *data, struct t_config_file *config_file) { struct t_script_callback *script_callback; - char *lua_argv[3], empty_arg[1] = { '\0' }; + void *lua_argv[2]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1232,7 +1233,7 @@ weechat_lua_api_config_reload_cb (void *data, rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "ss", lua_argv); if (!rc) ret = WEECHAT_CONFIG_READ_FILE_NOT_FOUND; @@ -1307,7 +1308,8 @@ weechat_lua_api_config_read_cb (void *data, const char *option_name, const char *value) { struct t_script_callback *script_callback; - char *lua_argv[6], empty_arg[1] = { '\0' }; + void *lua_argv[5]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1319,12 +1321,11 @@ weechat_lua_api_config_read_cb (void *data, lua_argv[2] = script_ptr2str (section); lua_argv[3] = (option_name) ? (char *)option_name : empty_arg; lua_argv[4] = (value) ? (char *)value : empty_arg; - lua_argv[5] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "sssss", lua_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_SET_ERROR; @@ -1354,7 +1355,8 @@ weechat_lua_api_config_section_write_cb (void *data, const char *section_name) { struct t_script_callback *script_callback; - char *lua_argv[4], empty_arg[1] = { '\0' }; + void *lua_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1364,12 +1366,11 @@ weechat_lua_api_config_section_write_cb (void *data, lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; lua_argv[1] = script_ptr2str (config_file); lua_argv[2] = (section_name) ? (char *)section_name : empty_arg; - lua_argv[3] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "sss", lua_argv); if (!rc) ret = WEECHAT_CONFIG_WRITE_ERROR; @@ -1398,7 +1399,8 @@ weechat_lua_api_config_section_write_default_cb (void *data, const char *section_name) { struct t_script_callback *script_callback; - char *lua_argv[4], empty_arg[1] = { '\0' }; + void *lua_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1408,12 +1410,11 @@ weechat_lua_api_config_section_write_default_cb (void *data, lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; lua_argv[1] = script_ptr2str (config_file); lua_argv[2] = (section_name) ? (char *)section_name : empty_arg; - lua_argv[3] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "sss", lua_argv); if (!rc) ret = WEECHAT_CONFIG_WRITE_ERROR; @@ -1443,7 +1444,8 @@ weechat_lua_api_config_section_create_option_cb (void *data, const char *value) { struct t_script_callback *script_callback; - char *lua_argv[6], empty_arg[1] = { '\0' }; + void *lua_argv[5]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1455,12 +1457,11 @@ weechat_lua_api_config_section_create_option_cb (void *data, lua_argv[2] = script_ptr2str (section); lua_argv[3] = (option_name) ? (char *)option_name : empty_arg; lua_argv[4] = (value) ? (char *)value : empty_arg; - lua_argv[5] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "sssss", lua_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_SET_ERROR; @@ -1491,7 +1492,8 @@ weechat_lua_api_config_section_delete_option_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *lua_argv[5], empty_arg[1] = { '\0' }; + void *lua_argv[4]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1502,12 +1504,11 @@ weechat_lua_api_config_section_delete_option_cb (void *data, lua_argv[1] = script_ptr2str (config_file); lua_argv[2] = script_ptr2str (section); lua_argv[3] = script_ptr2str (option); - lua_argv[4] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "ssss", lua_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_UNSET_ERROR; @@ -1667,7 +1668,8 @@ weechat_lua_api_config_option_check_value_cb (void *data, const char *value) { struct t_script_callback *script_callback; - char *lua_argv[4], empty_arg[1] = { '\0' }; + void *lua_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1677,12 +1679,11 @@ weechat_lua_api_config_option_check_value_cb (void *data, lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; lua_argv[1] = script_ptr2str (option); lua_argv[2] = (value) ? (char *)value : empty_arg; - lua_argv[3] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "sss", lua_argv); if (!rc) ret = 0; @@ -1709,7 +1710,8 @@ weechat_lua_api_config_option_change_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *lua_argv[3], empty_arg[1] = { '\0' }; + void *lua_argv[2]; + char empty_arg[1] = { '\0' }; int *rc; script_callback = (struct t_script_callback *)data; @@ -1718,12 +1720,11 @@ weechat_lua_api_config_option_change_cb (void *data, { lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; lua_argv[1] = script_ptr2str (option); - lua_argv[2] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "ss", lua_argv); if (lua_argv[1]) free (lua_argv[1]); @@ -1742,7 +1743,8 @@ weechat_lua_api_config_option_delete_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *lua_argv[3], empty_arg[1] = { '\0' }; + void *lua_argv[2]; + char empty_arg[1] = { '\0' }; int *rc; script_callback = (struct t_script_callback *)data; @@ -1751,12 +1753,11 @@ weechat_lua_api_config_option_delete_cb (void *data, { lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; lua_argv[1] = script_ptr2str (option); - lua_argv[2] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "ss", lua_argv); if (lua_argv[1]) free (lua_argv[1]); @@ -3276,7 +3277,8 @@ weechat_lua_api_hook_command_cb (void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { struct t_script_callback *script_callback; - char *lua_argv[4], empty_arg[1] = { '\0' }; + void *lua_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; /* make C compiler happy */ @@ -3289,12 +3291,11 @@ weechat_lua_api_hook_command_cb (void *data, struct t_gui_buffer *buffer, lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; lua_argv[1] = script_ptr2str (buffer); lua_argv[2] = (argc > 1) ? argv_eol[1] : empty_arg; - lua_argv[3] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "sss", lua_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3380,7 +3381,8 @@ weechat_lua_api_hook_command_run_cb (void *data, struct t_gui_buffer *buffer, const char *command) { struct t_script_callback *script_callback; - char *lua_argv[4], empty_arg[1] = { '\0' }; + void *lua_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3390,12 +3392,11 @@ weechat_lua_api_hook_command_run_cb (void *data, struct t_gui_buffer *buffer, lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; lua_argv[1] = script_ptr2str (buffer); lua_argv[2] = (command) ? (char *)command : empty_arg; - lua_argv[3] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "sss", lua_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3467,7 +3468,8 @@ int weechat_lua_api_hook_timer_cb (void *data, int remaining_calls) { struct t_script_callback *script_callback; - char *lua_argv[3], str_remaining_calls[32], empty_arg[1] = { '\0' }; + void *lua_argv[2]; + char str_remaining_calls[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3479,12 +3481,11 @@ weechat_lua_api_hook_timer_cb (void *data, int remaining_calls) lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; lua_argv[1] = str_remaining_calls; - lua_argv[2] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "ss", lua_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3560,7 +3561,8 @@ int weechat_lua_api_hook_fd_cb (void *data, int fd) { struct t_script_callback *script_callback; - char *lua_argv[3], str_fd[32], empty_arg[1] = { '\0' }; + void *lua_argv[2]; + char str_fd[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3571,12 +3573,11 @@ weechat_lua_api_hook_fd_cb (void *data, int fd) lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; lua_argv[1] = str_fd; - lua_argv[2] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "ss", lua_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3657,7 +3658,8 @@ weechat_lua_api_hook_process_cb (void *data, const char *out, const char *err) { struct t_script_callback *script_callback; - char *lua_argv[6], str_rc[32], empty_arg[1] = { '\0' }; + void *lua_argv[5]; + char str_rc[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3671,12 +3673,11 @@ weechat_lua_api_hook_process_cb (void *data, lua_argv[2] = str_rc; lua_argv[3] = (out) ? (char *)out : empty_arg; lua_argv[4] = (err) ? (char *)err : empty_arg; - lua_argv[5] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "sssss", lua_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3749,7 +3750,8 @@ weechat_lua_api_hook_connect_cb (void *data, int status, int gnutls_rc, const char *error, const char *ip_address) { struct t_script_callback *script_callback; - char *lua_argv[6], str_status[32], str_gnutls_rc[32]; + void *lua_argv[5]; + char str_status[32], str_gnutls_rc[32]; char empty_arg[1] = { '\0' }; int *rc, ret; @@ -3765,12 +3767,11 @@ weechat_lua_api_hook_connect_cb (void *data, int status, int gnutls_rc, lua_argv[2] = str_gnutls_rc; lua_argv[3] = (ip_address) ? (char *)ip_address : empty_arg; lua_argv[4] = (error) ? (char *)error : empty_arg; - lua_argv[5] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "sssss", lua_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3862,7 +3863,8 @@ weechat_lua_api_hook_print_cb (void *data, struct t_gui_buffer *buffer, const char *prefix, const char *message) { struct t_script_callback *script_callback; - char *lua_argv[9], empty_arg[1] = { '\0' }; + void *lua_argv[8]; + char empty_arg[1] = { '\0' }; static char timebuffer[64]; int *rc, ret; @@ -3885,12 +3887,11 @@ weechat_lua_api_hook_print_cb (void *data, struct t_gui_buffer *buffer, lua_argv[5] = (highlight) ? strdup ("1") : strdup ("0"); lua_argv[6] = (prefix) ? (char *)prefix : empty_arg; lua_argv[7] = (message) ? (char *)message : empty_arg; - lua_argv[8] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "ssssssss", lua_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3978,7 +3979,8 @@ weechat_lua_api_hook_signal_cb (void *data, const char *signal, const char *type_data, void *signal_data) { struct t_script_callback *script_callback; - char *lua_argv[4], empty_arg[1] = { '\0' }; + void *lua_argv[3]; + char empty_arg[1] = { '\0' }; static char value_str[64]; int *rc, ret, free_needed; @@ -4006,12 +4008,11 @@ weechat_lua_api_hook_signal_cb (void *data, const char *signal, } else lua_argv[2] = empty_arg; - lua_argv[3] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "sss", lua_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -4141,7 +4142,8 @@ weechat_lua_api_hook_config_cb (void *data, const char *option, const char *value) { struct t_script_callback *script_callback; - char *lua_argv[4], empty_arg[1] = { '\0' }; + void *lua_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4151,12 +4153,11 @@ weechat_lua_api_hook_config_cb (void *data, const char *option, lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; lua_argv[1] = (option) ? (char *)option : empty_arg; lua_argv[2] = (value) ? (char *)value : empty_arg; - lua_argv[3] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "sss", lua_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -4229,7 +4230,8 @@ weechat_lua_api_hook_completion_cb (void *data, const char *completion_item, struct t_gui_completion *completion) { struct t_script_callback *script_callback; - char *lua_argv[5], empty_arg[1] = { '\0' }; + void *lua_argv[4]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4240,12 +4242,11 @@ weechat_lua_api_hook_completion_cb (void *data, const char *completion_item, lua_argv[1] = (completion_item) ? (char *)completion_item : empty_arg; lua_argv[2] = script_ptr2str (buffer); lua_argv[3] = script_ptr2str (completion); - lua_argv[4] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "ssss", lua_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -4369,7 +4370,8 @@ weechat_lua_api_hook_modifier_cb (void *data, const char *modifier, const char *string) { struct t_script_callback *script_callback; - char *lua_argv[5], empty_arg[1] = { '\0' }; + void *lua_argv[4]; + char empty_arg[1] = { '\0' }; script_callback = (struct t_script_callback *)data; @@ -4379,12 +4381,11 @@ weechat_lua_api_hook_modifier_cb (void *data, const char *modifier, lua_argv[1] = (modifier) ? (char *)modifier : empty_arg; lua_argv[2] = (modifier_data) ? (char *)modifier_data : empty_arg; lua_argv[3] = (string) ? (char *)string : empty_arg; - lua_argv[4] = NULL; return (char *)weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - lua_argv); + "ssss", lua_argv); } return NULL; @@ -4486,7 +4487,8 @@ weechat_lua_api_hook_info_cb (void *data, const char *info_name, const char *arguments) { struct t_script_callback *script_callback; - char *lua_argv[4], empty_arg[1] = { '\0' }; + void *lua_argv[3]; + char empty_arg[1] = { '\0' }; script_callback = (struct t_script_callback *)data; @@ -4495,12 +4497,11 @@ weechat_lua_api_hook_info_cb (void *data, const char *info_name, lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; lua_argv[1] = (info_name) ? (char *)info_name : empty_arg; lua_argv[2] = (arguments) ? (char *)arguments : empty_arg; - lua_argv[3] = NULL; return (const char *)weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - lua_argv); + "sss", lua_argv); } return NULL; @@ -4559,6 +4560,91 @@ weechat_lua_api_hook_info (lua_State *L) } /* + * weechat_lua_api_hook_info_hashtable_cb: callback for info_hashtable hooked + */ + +struct t_hashtable * +weechat_lua_api_hook_info_hashtable_cb (void *data, const char *info_name, + struct t_hashtable *hashtable) +{ + struct t_script_callback *script_callback; + void *lua_argv[3]; + char empty_arg[1] = { '\0' }; + + script_callback = (struct t_script_callback *)data; + + if (script_callback && script_callback->function && script_callback->function[0]) + { + lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; + lua_argv[1] = (info_name) ? (char *)info_name : empty_arg; + lua_argv[2] = hashtable; + + return (struct t_hashtable *)weechat_lua_exec (script_callback->script, + WEECHAT_SCRIPT_EXEC_HASHTABLE, + script_callback->function, + "ssh", lua_argv); + } + + return NULL; +} + +/* + * weechat_lua_api_hook_info_hashtable: hook an info_hashtable + */ + +static int +weechat_lua_api_hook_info_hashtable (lua_State *L) +{ + const char *info_name, *description, *args_description; + const char *output_description, *function, *data; + char *result; + int n; + + /* make C compiler happy */ + (void) L; + + if (!lua_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INIT(LUA_CURRENT_SCRIPT_NAME, "hook_info_hashtable"); + LUA_RETURN_EMPTY; + } + + info_name = NULL; + description = NULL; + args_description = NULL; + output_description = NULL; + function = NULL; + data = NULL; + + n = lua_gettop (lua_current_interpreter); + + if (n < 6) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGS(LUA_CURRENT_SCRIPT_NAME, "hook_info_hashtable"); + LUA_RETURN_EMPTY; + } + + info_name = lua_tostring (lua_current_interpreter, -6); + description = lua_tostring (lua_current_interpreter, -5); + args_description = lua_tostring (lua_current_interpreter, -4); + output_description = lua_tostring (lua_current_interpreter, -3); + function = lua_tostring (lua_current_interpreter, -2); + data = lua_tostring (lua_current_interpreter, -1); + + result = script_ptr2str (script_api_hook_info_hashtable (weechat_lua_plugin, + lua_current_script, + info_name, + description, + args_description, + output_description, + &weechat_lua_api_hook_info_hashtable_cb, + function, + data)); + + LUA_RETURN_STRING_FREE(result); +} + +/* * weechat_lua_api_hook_infolist_cb: callback for infolist hooked */ @@ -4567,7 +4653,8 @@ weechat_lua_api_hook_infolist_cb (void *data, const char *info_name, void *pointer, const char *arguments) { struct t_script_callback *script_callback; - char *lua_argv[5], empty_arg[1] = { '\0' }; + void *lua_argv[4]; + char empty_arg[1] = { '\0' }; struct t_infolist *result; script_callback = (struct t_script_callback *)data; @@ -4578,12 +4665,11 @@ weechat_lua_api_hook_infolist_cb (void *data, const char *info_name, lua_argv[1] = (info_name) ? (char *)info_name : empty_arg; lua_argv[2] = script_ptr2str (pointer); lua_argv[3] = (arguments) ? (char *)arguments : empty_arg; - lua_argv[4] = NULL; result = (struct t_infolist *)weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - lua_argv); + "ssss", lua_argv); if (lua_argv[2]) free (lua_argv[2]); @@ -4718,7 +4804,8 @@ weechat_lua_api_buffer_input_data_cb (void *data, struct t_gui_buffer *buffer, const char *input_data) { struct t_script_callback *script_callback; - char *lua_argv[4], empty_arg[1] = { '\0' }; + void *lua_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4728,12 +4815,11 @@ weechat_lua_api_buffer_input_data_cb (void *data, struct t_gui_buffer *buffer, lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; lua_argv[1] = script_ptr2str (buffer); lua_argv[2] = (input_data) ? (char *)input_data : empty_arg; - lua_argv[3] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "sss", lua_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -4759,7 +4845,8 @@ int weechat_lua_api_buffer_close_cb (void *data, struct t_gui_buffer *buffer) { struct t_script_callback *script_callback; - char *lua_argv[3], empty_arg[1] = { '\0' }; + void *lua_argv[2]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4768,12 +4855,11 @@ weechat_lua_api_buffer_close_cb (void *data, struct t_gui_buffer *buffer) { lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; lua_argv[1] = script_ptr2str (buffer); - lua_argv[2] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "ss", lua_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -5806,7 +5892,8 @@ weechat_lua_api_bar_item_build_cb (void *data, struct t_gui_bar_item *item, struct t_gui_window *window) { struct t_script_callback *script_callback; - char *lua_argv[4], empty_arg[1] = { '\0' }, *ret; + void *lua_argv[3]; + char empty_arg[1] = { '\0' }, *ret; script_callback = (struct t_script_callback *)data; @@ -5815,12 +5902,11 @@ weechat_lua_api_bar_item_build_cb (void *data, struct t_gui_bar_item *item, lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; lua_argv[1] = script_ptr2str (item); lua_argv[2] = script_ptr2str (window); - lua_argv[3] = NULL; ret = (char *)weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - lua_argv); + "sss", lua_argv); if (lua_argv[1]) free (lua_argv[1]); @@ -6226,7 +6312,7 @@ weechat_lua_api_command (lua_State *L) } /* - * weechat_lua_api_info_get: get info about WeeChat + * weechat_lua_api_info_get: get info (as string) */ static int @@ -6264,6 +6350,53 @@ weechat_lua_api_info_get (lua_State *L) } /* + * weechat_lua_api_info_get_hashtable: get info (as hashtable) + */ + +static int +weechat_lua_api_info_get_hashtable (lua_State *L) +{ + const char *info_name; + struct t_hashtable *table, *result_hashtable; + int n; + + /* make C compiler happy */ + (void) L; + + if (!lua_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INIT(LUA_CURRENT_SCRIPT_NAME, "info_get_hashtable"); + LUA_RETURN_EMPTY; + } + + info_name = NULL; + table = NULL; + + n = lua_gettop (lua_current_interpreter); + + if (n < 2) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGS(LUA_CURRENT_SCRIPT_NAME, "info_get_hashtable"); + LUA_RETURN_EMPTY; + } + + info_name = lua_tostring (lua_current_interpreter, -2); + table = weechat_lua_tohashtable (lua_current_interpreter, -1, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE); + + result_hashtable = weechat_info_get_hashtable (info_name, table); + + weechat_lua_pushhashtable (lua_current_interpreter, result_hashtable); + + if (table) + weechat_hashtable_free (table); + if (result_hashtable) + weechat_hashtable_free (result_hashtable); + + return 1; +} + +/* * weechat_lua_api_infolist_new: create new infolist */ @@ -6938,7 +7071,8 @@ weechat_lua_api_upgrade_read_cb (void *data, struct t_infolist *infolist) { struct t_script_callback *script_callback; - char *lua_argv[5], empty_arg[1] = { '\0' }, str_object_id[32]; + void *lua_argv[4]; + char empty_arg[1] = { '\0' }, str_object_id[32]; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -6951,12 +7085,11 @@ weechat_lua_api_upgrade_read_cb (void *data, lua_argv[1] = script_ptr2str (upgrade_file); lua_argv[2] = str_object_id; lua_argv[3] = script_ptr2str (infolist); - lua_argv[4] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - lua_argv); + "ssss", lua_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -7531,6 +7664,7 @@ const struct luaL_reg weechat_lua_api_funcs[] = { { "hook_modifier", &weechat_lua_api_hook_modifier }, { "hook_modifier_exec", &weechat_lua_api_hook_modifier_exec }, { "hook_info", &weechat_lua_api_hook_info }, + { "hook_info_hashtable", &weechat_lua_api_hook_info_hashtable }, { "hook_infolist", &weechat_lua_api_hook_infolist }, { "unhook", &weechat_lua_api_unhook }, { "unhook_all", &weechat_lua_api_unhook_all }, @@ -7570,6 +7704,7 @@ const struct luaL_reg weechat_lua_api_funcs[] = { { "bar_remove", &weechat_lua_api_bar_remove }, { "command", &weechat_lua_api_command }, { "info_get", &weechat_lua_api_info_get }, + { "info_get_hashtable", &weechat_lua_api_info_get_hashtable }, { "infolist_new", &weechat_lua_api_infolist_new }, { "infolist_new_item", &weechat_lua_api_infolist_new_item }, { "infolist_new_var_integer", &weechat_lua_api_infolist_new_var_integer }, diff --git a/src/plugins/scripts/lua/weechat-lua.c b/src/plugins/scripts/lua/weechat-lua.c index 10248ed21..aeea789d4 100644 --- a/src/plugins/scripts/lua/weechat-lua.c +++ b/src/plugins/scripts/lua/weechat-lua.c @@ -70,15 +70,87 @@ char *lua_action_remove_list = NULL; /* - * weechat_lua_exec: execute a Lua script + * weechat_lua_hashtable_map_cb: callback called for each key/value in a + * hashtable + */ + +void +weechat_lua_hashtable_map_cb (void *data, + struct t_hashtable *hashtable, + const void *key, + const void *value) +{ + lua_State *interpreter; + + /* make C compiler happy */ + (void) hashtable; + + interpreter = (lua_State *)data; + + lua_pushstring (interpreter, (char *)key); + lua_pushstring (interpreter, (char *)value); + lua_rawset (interpreter, -3); +} + +/* + * weechat_lua_pushhashtable: put a WeeChat hashtable on lua stack, as lua table + */ + +void +weechat_lua_pushhashtable (lua_State *interpreter, struct t_hashtable *hashtable) +{ + lua_newtable (interpreter); + + weechat_hashtable_map (hashtable, + &weechat_lua_hashtable_map_cb, + interpreter); +} + +/* + * weechat_lua_hash_to_hashtable: get WeeChat hashtable with lua hash (on stack) + * Hashtable returned has type string for + * both keys and values + * Note: hashtable has to be released after use + * with call to weechat_hashtable_free() + */ + +struct t_hashtable * +weechat_lua_tohashtable (lua_State *interpreter, int index, int hashtable_size) +{ + struct t_hashtable *hashtable; + + hashtable = weechat_hashtable_new (hashtable_size, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); + if (!hashtable) + return NULL; + + lua_pushnil (interpreter); + while (lua_next (interpreter, index - 1) != 0) + { + weechat_hashtable_set (hashtable, + (char *)lua_tostring (interpreter, -2), + (char *)lua_tostring (interpreter, -1)); + /* remove value from stack (keep key for next iteration) */ + lua_pop (interpreter, 1); + } + + return hashtable; +} + +/* + * weechat_lua_exec: execute a lua function */ void * -weechat_lua_exec (struct t_plugin_script *script, - int ret_type, const char *function, char **argv) +weechat_lua_exec (struct t_plugin_script *script, int ret_type, + const char *function, + const char *format, void **argv) { void *ret_value; - int argc, *ret_i; + int argc, i, *ret_i; struct t_plugin_script *old_lua_current_script; lua_current_interpreter = script->interpreter; @@ -87,47 +159,24 @@ weechat_lua_exec (struct t_plugin_script *script, old_lua_current_script = lua_current_script; lua_current_script = script; - + argc = 0; - if (argv && argv[0]) + if (format && format[0]) { - lua_pushstring (lua_current_interpreter, argv[0]); - argc = 1; - if (argv[1]) + argc = strlen (format); + for (i = 0; i < argc; i++) { - argc = 2; - lua_pushstring (lua_current_interpreter, argv[1]); - if (argv[2]) + switch (format[i]) { - argc = 3; - lua_pushstring (lua_current_interpreter, argv[2]); - if (argv[3]) - { - argc = 4; - lua_pushstring (lua_current_interpreter, argv[3]); - if (argv[4]) - { - argc = 5; - lua_pushstring (lua_current_interpreter, argv[4]); - if (argv[5]) - { - argc = 6; - lua_pushstring (lua_current_interpreter, argv[5]); - if (argv[6]) - { - argc = 7; - lua_pushstring (lua_current_interpreter, - argv[6]); - if (argv[7]) - { - argc = 8; - lua_pushstring (lua_current_interpreter, - argv[7]); - } - } - } - } - } + case 's': /* string */ + lua_pushstring (lua_current_interpreter, (char *)argv[i]); + break; + case 'i': /* integer */ + lua_pushnumber (lua_current_interpreter, *((int *)argv[i])); + break; + case 'h': /* hash */ + weechat_lua_pushhashtable (lua_current_interpreter, (struct t_hashtable *)argv[i]); + break; } } } @@ -154,6 +203,11 @@ weechat_lua_exec (struct t_plugin_script *script, *ret_i = lua_tonumber (lua_current_interpreter, -1); ret_value = ret_i; } + else if (ret_type == WEECHAT_SCRIPT_EXEC_HASHTABLE) + { + ret_value = weechat_lua_tohashtable (lua_current_interpreter, -1, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE); + } else { WEECHAT_SCRIPT_MSG_WRONG_ARGS(LUA_CURRENT_SCRIPT_NAME, function); @@ -166,6 +220,10 @@ weechat_lua_exec (struct t_plugin_script *script, return ret_value; } +/* + * weechat_lua_load: load a Lua script + */ + int weechat_lua_load (const char *filename) { @@ -308,7 +366,6 @@ void weechat_lua_unload (struct t_plugin_script *script) { int *r; - char *lua_argv[1] = { NULL }; void *interpreter; if ((weechat_lua_plugin->debug >= 1) || !lua_quiet) @@ -323,7 +380,7 @@ weechat_lua_unload (struct t_plugin_script *script) r = weechat_lua_exec (script, WEECHAT_SCRIPT_EXEC_INT, script->shutdown_func, - lua_argv); + NULL, NULL); if (r) free (r); } diff --git a/src/plugins/scripts/lua/weechat-lua.h b/src/plugins/scripts/lua/weechat-lua.h index fe5c11fc1..ce7460bd8 100644 --- a/src/plugins/scripts/lua/weechat-lua.h +++ b/src/plugins/scripts/lua/weechat-lua.h @@ -36,8 +36,13 @@ extern struct t_plugin_script *lua_registered_script; extern const char *lua_current_script_filename; extern lua_State *lua_current_interpreter; -extern void *weechat_lua_exec (struct t_plugin_script *script, - int ret_type, const char *function, - char **argv); +extern void weechat_lua_pushhashtable (lua_State *interpreter, + struct t_hashtable *hashtable); +extern struct t_hashtable *weechat_lua_tohashtable (lua_State *interpreter, + int index, + int hashtable_size); +extern void *weechat_lua_exec (struct t_plugin_script *script, int ret_type, + const char *function, + const char *format, void **argv); #endif /* __WEECHAT_LUA_H */ diff --git a/src/plugins/scripts/perl/weechat-perl-api.c b/src/plugins/scripts/perl/weechat-perl-api.c index e38f0a7c3..6d0e8257b 100644 --- a/src/plugins/scripts/perl/weechat-perl-api.c +++ b/src/plugins/scripts/perl/weechat-perl-api.c @@ -56,8 +56,12 @@ } \ XST_mPV (0, ""); \ XSRETURN (1) -#define PERL_RETURN_INT(__int) \ - XST_mIV (0, __int); \ +#define PERL_RETURN_INT(__int) \ + XST_mIV (0, __int); \ + XSRETURN (1); +#define PERL_RETURN_OBJ(__obj) \ + ST (0) = newRV_inc((SV *)__obj); \ + if (SvREFCNT(ST(0))) sv_2mortal(ST(0)); \ XSRETURN (1); @@ -999,7 +1003,8 @@ weechat_perl_api_config_reload_cb (void *data, struct t_config_file *config_file) { struct t_script_callback *script_callback; - char *perl_argv[3], empty_arg[1] = { '\0' }; + void *perl_argv[2]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1008,12 +1013,11 @@ weechat_perl_api_config_reload_cb (void *data, { perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = script_ptr2str (config_file); - perl_argv[2] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "ss", perl_argv); if (!rc) ret = WEECHAT_CONFIG_READ_FILE_NOT_FOUND; @@ -1081,7 +1085,8 @@ weechat_perl_api_config_section_read_cb (void *data, const char *value) { struct t_script_callback *script_callback; - char *perl_argv[6], empty_arg[1] = { '\0' }; + void *perl_argv[5]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1093,12 +1098,11 @@ weechat_perl_api_config_section_read_cb (void *data, perl_argv[2] = script_ptr2str (section); perl_argv[3] = (option_name) ? (char *)option_name : empty_arg; perl_argv[4] = (value) ? (char *)value : empty_arg; - perl_argv[5] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "sssss", perl_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_SET_ERROR; @@ -1128,7 +1132,8 @@ weechat_perl_api_config_section_write_cb (void *data, const char *section_name) { struct t_script_callback *script_callback; - char *perl_argv[4], empty_arg[1] = { '\0' }; + void *perl_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1138,12 +1143,11 @@ weechat_perl_api_config_section_write_cb (void *data, perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = script_ptr2str (config_file); perl_argv[2] = (section_name) ? (char *)section_name : empty_arg; - perl_argv[3] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "sss", perl_argv); if (!rc) ret = WEECHAT_CONFIG_WRITE_ERROR; @@ -1172,7 +1176,8 @@ weechat_perl_api_config_section_write_default_cb (void *data, const char *section_name) { struct t_script_callback *script_callback; - char *perl_argv[4], empty_arg[1] = { '\0' }; + void *perl_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1182,13 +1187,12 @@ weechat_perl_api_config_section_write_default_cb (void *data, perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = script_ptr2str (config_file); perl_argv[2] = (section_name) ? (char *)section_name : empty_arg; - perl_argv[3] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); - + "sss", perl_argv); + if (!rc) ret = WEECHAT_CONFIG_WRITE_ERROR; else @@ -1217,7 +1221,8 @@ weechat_perl_api_config_section_create_option_cb (void *data, const char *value) { struct t_script_callback *script_callback; - char *perl_argv[6], empty_arg[1] = { '\0' }; + void *perl_argv[5]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1229,12 +1234,11 @@ weechat_perl_api_config_section_create_option_cb (void *data, perl_argv[2] = script_ptr2str (section); perl_argv[3] = (option_name) ? (char *)option_name : empty_arg; perl_argv[4] = (value) ? (char *)value : empty_arg; - perl_argv[5] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "sssss", perl_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_SET_ERROR; @@ -1265,7 +1269,8 @@ weechat_perl_api_config_section_delete_option_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *perl_argv[5], empty_arg[1] = { '\0' }; + void *perl_argv[4]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1276,12 +1281,11 @@ weechat_perl_api_config_section_delete_option_cb (void *data, perl_argv[1] = script_ptr2str (config_file); perl_argv[2] = script_ptr2str (section); perl_argv[3] = script_ptr2str (option); - perl_argv[4] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "ssss", perl_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_UNSET_ERROR; @@ -1413,7 +1417,8 @@ weechat_perl_api_config_option_check_value_cb (void *data, const char *value) { struct t_script_callback *script_callback; - char *perl_argv[4], empty_arg[1] = { '\0' }; + void *perl_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1423,12 +1428,11 @@ weechat_perl_api_config_option_check_value_cb (void *data, perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = script_ptr2str (option); perl_argv[2] = (value) ? (char *)value : empty_arg; - perl_argv[3] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "sss", perl_argv); if (!rc) ret = 0; @@ -1455,7 +1459,8 @@ weechat_perl_api_config_option_change_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *perl_argv[3], empty_arg[1] = { '\0' }; + void *perl_argv[2]; + char empty_arg[1] = { '\0' }; int *rc; script_callback = (struct t_script_callback *)data; @@ -1464,12 +1469,11 @@ weechat_perl_api_config_option_change_cb (void *data, { perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = script_ptr2str (option); - perl_argv[2] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "ss", perl_argv); if (perl_argv[1]) free (perl_argv[1]); @@ -1488,7 +1492,8 @@ weechat_perl_api_config_option_delete_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *perl_argv[3], empty_arg[1] = { '\0' }; + void *perl_argv[2]; + char empty_arg[1] = { '\0' }; int *rc; script_callback = (struct t_script_callback *)data; @@ -1497,12 +1502,11 @@ weechat_perl_api_config_option_delete_cb (void *data, { perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = script_ptr2str (option); - perl_argv[2] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "ss", perl_argv); if (perl_argv[1]) free (perl_argv[1]); @@ -2741,7 +2745,8 @@ weechat_perl_api_hook_command_cb (void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { struct t_script_callback *script_callback; - char *perl_argv[4], empty_arg[1] = { '\0' }; + void *perl_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; /* make C compiler happy */ @@ -2754,12 +2759,11 @@ weechat_perl_api_hook_command_cb (void *data, struct t_gui_buffer *buffer, perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = script_ptr2str (buffer); perl_argv[2] = (argc > 1) ? argv_eol[1] : empty_arg; - perl_argv[3] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "sss", perl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2833,7 +2837,8 @@ weechat_perl_api_hook_command_run_cb (void *data, struct t_gui_buffer *buffer, const char *command) { struct t_script_callback *script_callback; - char *perl_argv[4], empty_arg[1] = { '\0' }; + void *perl_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -2843,12 +2848,11 @@ weechat_perl_api_hook_command_run_cb (void *data, struct t_gui_buffer *buffer, perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = script_ptr2str (buffer); perl_argv[2] = (command) ? (char *)command : empty_arg; - perl_argv[3] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "sss", perl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2912,7 +2916,8 @@ int weechat_perl_api_hook_timer_cb (void *data, int remaining_calls) { struct t_script_callback *script_callback; - char *perl_argv[3], str_remaining_calls[32], empty_arg[1] = { '\0' }; + void *perl_argv[2]; + char str_remaining_calls[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -2924,12 +2929,11 @@ weechat_perl_api_hook_timer_cb (void *data, int remaining_calls) perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = str_remaining_calls; - perl_argv[2] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "ss", perl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2989,7 +2993,8 @@ int weechat_perl_api_hook_fd_cb (void *data, int fd) { struct t_script_callback *script_callback; - char *perl_argv[3], str_fd[32], empty_arg[1] = { '\0' }; + void *perl_argv[2]; + char str_fd[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3000,12 +3005,11 @@ weechat_perl_api_hook_fd_cb (void *data, int fd) perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = str_fd; - perl_argv[2] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "ss", perl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3068,7 +3072,8 @@ weechat_perl_api_hook_process_cb (void *data, const char *out, const char *err) { struct t_script_callback *script_callback; - char *perl_argv[6], str_rc[32], empty_arg[1] = { '\0' }; + void *perl_argv[5]; + char str_rc[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3082,12 +3087,11 @@ weechat_perl_api_hook_process_cb (void *data, perl_argv[2] = str_rc; perl_argv[3] = (out) ? (char *)out : empty_arg; perl_argv[4] = (err) ? (char *)err : empty_arg; - perl_argv[5] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "sssss", perl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3151,7 +3155,8 @@ weechat_perl_api_hook_connect_cb (void *data, int status, int gnutls_rc, const char *error, const char *ip_address) { struct t_script_callback *script_callback; - char *perl_argv[6], str_status[32], str_gnutls_rc[32]; + void *perl_argv[5]; + char str_status[32], str_gnutls_rc[32]; char empty_arg[1] = { '\0' }; int *rc, ret; @@ -3167,12 +3172,11 @@ weechat_perl_api_hook_connect_cb (void *data, int status, int gnutls_rc, perl_argv[2] = str_gnutls_rc; perl_argv[3] = (ip_address) ? (char *)ip_address : empty_arg; perl_argv[4] = (error) ? (char *)error : empty_arg; - perl_argv[5] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "sssss", perl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3248,7 +3252,8 @@ weechat_perl_api_hook_print_cb (void *data, struct t_gui_buffer *buffer, const char *prefix, const char *message) { struct t_script_callback *script_callback; - char *perl_argv[9], empty_arg[1] = { '\0' }; + void *perl_argv[8]; + char empty_arg[1] = { '\0' }; static char timebuffer[64]; int *rc, ret; @@ -3271,12 +3276,11 @@ weechat_perl_api_hook_print_cb (void *data, struct t_gui_buffer *buffer, perl_argv[5] = (highlight) ? strdup ("1") : strdup ("0"); perl_argv[6] = (prefix) ? (char *)prefix : empty_arg; perl_argv[7] = (message) ? (char *)message : empty_arg; - perl_argv[8] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "ssssssss", perl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3352,7 +3356,8 @@ weechat_perl_api_hook_signal_cb (void *data, const char *signal, const char *typ void *signal_data) { struct t_script_callback *script_callback; - char *perl_argv[4], empty_arg[1] = { '\0' }; + void *perl_argv[3]; + char empty_arg[1] = { '\0' }; static char value_str[64]; int *rc, ret, free_needed; @@ -3380,12 +3385,11 @@ weechat_perl_api_hook_signal_cb (void *data, const char *signal, const char *typ } else perl_argv[2] = empty_arg; - perl_argv[3] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "sss", perl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3502,7 +3506,8 @@ int weechat_perl_api_hook_config_cb (void *data, const char *option, const char *value) { struct t_script_callback *script_callback; - char *perl_argv[4], empty_arg[1] = { '\0' }; + void *perl_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3512,12 +3517,11 @@ weechat_perl_api_hook_config_cb (void *data, const char *option, const char *val perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = (option) ? (char *)option : empty_arg; perl_argv[2] = (value) ? (char *)value : empty_arg; - perl_argv[3] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "sss", perl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3581,7 +3585,8 @@ weechat_perl_api_hook_completion_cb (void *data, const char *completion_item, struct t_gui_completion *completion) { struct t_script_callback *script_callback; - char *perl_argv[5], empty_arg[1] = { '\0' }; + void *perl_argv[4]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3592,12 +3597,11 @@ weechat_perl_api_hook_completion_cb (void *data, const char *completion_item, perl_argv[1] = (completion_item) ? (char *)completion_item : empty_arg; perl_argv[2] = script_ptr2str (buffer); perl_argv[3] = script_ptr2str (completion); - perl_argv[4] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "ssss", perl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3702,7 +3706,8 @@ weechat_perl_api_hook_modifier_cb (void *data, const char *modifier, const char *modifier_data, const char *string) { struct t_script_callback *script_callback; - char *perl_argv[5], empty_arg[1] = { '\0' }; + void *perl_argv[4]; + char empty_arg[1] = { '\0' }; script_callback = (struct t_script_callback *)data; @@ -3712,12 +3717,11 @@ weechat_perl_api_hook_modifier_cb (void *data, const char *modifier, perl_argv[1] = (modifier) ? (char *)modifier : empty_arg; perl_argv[2] = (modifier_data) ? (char *)modifier_data : empty_arg; perl_argv[3] = (string) ? (char *)string : empty_arg; - perl_argv[4] = NULL; return (char *)weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - perl_argv); + "ssss", perl_argv); } return NULL; @@ -3803,7 +3807,8 @@ weechat_perl_api_hook_info_cb (void *data, const char *info_name, const char *arguments) { struct t_script_callback *script_callback; - char *perl_argv[4], empty_arg[1] = { '\0' }; + void *perl_argv[3]; + char empty_arg[1] = { '\0' }; script_callback = (struct t_script_callback *)data; @@ -3812,12 +3817,11 @@ weechat_perl_api_hook_info_cb (void *data, const char *info_name, perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = (info_name) ? (char *)info_name : empty_arg; perl_argv[2] = (arguments) ? (char *)arguments : empty_arg; - perl_argv[3] = NULL; return (const char *)weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - perl_argv); + "sss", perl_argv); } return NULL; @@ -3866,6 +3870,80 @@ XS (XS_weechat_api_hook_info) } /* + * weechat_perl_api_hook_info_hashtable_cb: callback for info_hashtable hooked + */ + +struct t_hashtable * +weechat_perl_api_hook_info_hashtable_cb (void *data, const char *info_name, + struct t_hashtable *hashtable) +{ + struct t_script_callback *script_callback; + void *perl_argv[3]; + char empty_arg[1] = { '\0' }; + + script_callback = (struct t_script_callback *)data; + + if (script_callback && script_callback->function && script_callback->function[0]) + { + perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; + perl_argv[1] = (info_name) ? (char *)info_name : empty_arg; + perl_argv[2] = hashtable; + + return (struct t_hashtable *)weechat_perl_exec (script_callback->script, + WEECHAT_SCRIPT_EXEC_HASHTABLE, + script_callback->function, + "ssh", perl_argv); + } + + return NULL; +} + +/* + * weechat::hook_info_hashtable: hook an info_hashtable + */ + +XS (XS_weechat_api_hook_info_hashtable) +{ + char *result, *info_name, *description, *args_description; + char *output_description, *function, *data; + dXSARGS; + + /* make C compiler happy */ + (void) cv; + + if (!perl_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INIT(PERL_CURRENT_SCRIPT_NAME, "hook_info_hashtable"); + PERL_RETURN_EMPTY; + } + + if (items < 6) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGS(PERL_CURRENT_SCRIPT_NAME, "hook_info_hashtable"); + PERL_RETURN_EMPTY; + } + + info_name = SvPV (ST (0), PL_na); + description = SvPV (ST (1), PL_na); + args_description = SvPV (ST (2), PL_na); + output_description = SvPV (ST (3), PL_na); + function = SvPV (ST (4), PL_na); + data = SvPV (ST (5), PL_na); + + result = script_ptr2str (script_api_hook_info_hashtable (weechat_perl_plugin, + perl_current_script, + info_name, + description, + args_description, + output_description, + &weechat_perl_api_hook_info_hashtable_cb, + function, + data)); + + PERL_RETURN_STRING_FREE(result); +} + +/* * weechat_perl_api_hook_infolist_cb: callback for infolist hooked */ @@ -3874,7 +3952,8 @@ weechat_perl_api_hook_infolist_cb (void *data, const char *infolist_name, void *pointer, const char *arguments) { struct t_script_callback *script_callback; - char *perl_argv[5], empty_arg[1] = { '\0' }; + void *perl_argv[4]; + char empty_arg[1] = { '\0' }; struct t_infolist *result; script_callback = (struct t_script_callback *)data; @@ -3885,12 +3964,11 @@ weechat_perl_api_hook_infolist_cb (void *data, const char *infolist_name, perl_argv[1] = (infolist_name) ? (char *)infolist_name : empty_arg; perl_argv[2] = script_ptr2str (pointer); perl_argv[3] = (arguments) ? (char *)arguments : empty_arg; - perl_argv[4] = NULL; result = (struct t_infolist *)weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - perl_argv); + "ssss", perl_argv); if (perl_argv[2]) free (perl_argv[2]); @@ -4008,7 +4086,8 @@ weechat_perl_api_buffer_input_data_cb (void *data, struct t_gui_buffer *buffer, const char *input_data) { struct t_script_callback *script_callback; - char *perl_argv[4], empty_arg[1] = { '\0' }; + void *perl_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4018,12 +4097,11 @@ weechat_perl_api_buffer_input_data_cb (void *data, struct t_gui_buffer *buffer, perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = script_ptr2str (buffer); perl_argv[2] = (input_data) ? (char *)input_data : empty_arg; - perl_argv[3] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "sss", perl_argv); if (!rc) ret = WEECHAT_RC_ERROR; else @@ -4048,7 +4126,8 @@ int weechat_perl_api_buffer_close_cb (void *data, struct t_gui_buffer *buffer) { struct t_script_callback *script_callback; - char *perl_argv[3], empty_arg[1] = { '\0' }; + void *perl_argv[2]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4057,12 +4136,11 @@ weechat_perl_api_buffer_close_cb (void *data, struct t_gui_buffer *buffer) { perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = script_ptr2str (buffer); - perl_argv[2] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "ss", perl_argv); if (!rc) ret = WEECHAT_RC_ERROR; else @@ -4917,7 +4995,8 @@ weechat_perl_api_bar_item_build_cb (void *data, struct t_gui_bar_item *item, struct t_gui_window *window) { struct t_script_callback *script_callback; - char *perl_argv[4], empty_arg[1] = { '\0' }, *ret; + void *perl_argv[3]; + char empty_arg[1] = { '\0' }, *ret; script_callback = (struct t_script_callback *)data; @@ -4926,12 +5005,11 @@ weechat_perl_api_bar_item_build_cb (void *data, struct t_gui_bar_item *item, perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; perl_argv[1] = script_ptr2str (item); perl_argv[2] = script_ptr2str (window); - perl_argv[3] = NULL; ret = (char *)weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - perl_argv); + "sss", perl_argv); if (perl_argv[1]) free (perl_argv[1]); @@ -5255,7 +5333,7 @@ XS (XS_weechat_api_command) } /* - * weechat::info_get: get info about WeeChat + * weechat::info_get: get info (as string) */ XS (XS_weechat_api_info_get) @@ -5288,6 +5366,47 @@ XS (XS_weechat_api_info_get) } /* + * weechat::info_get_hashtable: get info (as hashtable) + */ + +XS (XS_weechat_api_info_get_hashtable) +{ + char *info_name; + struct t_hashtable *hashtable, *result_hashtable; + HV *result_hash; + dXSARGS; + + /* make C compiler happy */ + (void) cv; + + if (!perl_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INIT(PERL_CURRENT_SCRIPT_NAME, "info_get_hashtable"); + PERL_RETURN_EMPTY; + } + + if (items < 2) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGS(PERL_CURRENT_SCRIPT_NAME, "info_get_hashtable"); + PERL_RETURN_EMPTY; + } + + info_name = SvPV (ST (0), PL_na); + hashtable = weechat_perl_hash_to_hashtable (ST (1), + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE); + + result_hashtable = weechat_info_get_hashtable (info_name, hashtable); + result_hash = weechat_perl_hashtable_to_hash (result_hashtable); + + if (hashtable) + weechat_hashtable_free (hashtable); + if (result_hashtable) + weechat_hashtable_free (result_hashtable); + + PERL_RETURN_OBJ(result_hash); +} + +/* * weechat::infolist_new: create new infolist */ @@ -5841,7 +5960,8 @@ weechat_perl_api_upgrade_read_cb (void *data, struct t_infolist *infolist) { struct t_script_callback *script_callback; - char *perl_argv[5], empty_arg[1] = { '\0' }, str_object_id[32]; + void *perl_argv[4]; + char empty_arg[1] = { '\0' }, str_object_id[32]; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -5854,12 +5974,11 @@ weechat_perl_api_upgrade_read_cb (void *data, perl_argv[1] = script_ptr2str (upgrade_file); perl_argv[2] = str_object_id; perl_argv[3] = script_ptr2str (infolist); - perl_argv[4] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - perl_argv); + "ssss", perl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -6046,6 +6165,7 @@ weechat_perl_api_init (pTHX) newXS ("weechat::hook_modifier", XS_weechat_api_hook_modifier, "weechat"); newXS ("weechat::hook_modifier_exec", XS_weechat_api_hook_modifier_exec, "weechat"); newXS ("weechat::hook_info", XS_weechat_api_hook_info, "weechat"); + newXS ("weechat::hook_info_hashtable", XS_weechat_api_hook_info_hashtable, "weechat"); newXS ("weechat::hook_infolist", XS_weechat_api_hook_infolist, "weechat"); newXS ("weechat::unhook", XS_weechat_api_unhook, "weechat"); newXS ("weechat::unhook_all", XS_weechat_api_unhook_all, "weechat"); @@ -6085,6 +6205,7 @@ weechat_perl_api_init (pTHX) newXS ("weechat::bar_remove", XS_weechat_api_bar_remove, "weechat"); newXS ("weechat::command", XS_weechat_api_command, "weechat"); newXS ("weechat::info_get", XS_weechat_api_info_get, "weechat"); + newXS ("weechat::info_get_hashtable", XS_weechat_api_info_get_hashtable, "weechat"); newXS ("weechat::infolist_new", XS_weechat_api_infolist_new, "weechat"); newXS ("weechat::infolist_new_item", XS_weechat_api_infolist_new_item, "weechat"); newXS ("weechat::infolist_new_var_integer", XS_weechat_api_infolist_new_var_integer, "weechat"); diff --git a/src/plugins/scripts/perl/weechat-perl.c b/src/plugins/scripts/perl/weechat-perl.c index 7de8af730..32a7ff41a 100644 --- a/src/plugins/scripts/perl/weechat-perl.c +++ b/src/plugins/scripts/perl/weechat-perl.c @@ -127,12 +127,130 @@ char *perl_weechat_code = /* - * weechat_perl_exec: execute a Perl script + * weechat_perl_hashtable_map_cb: callback called for each key/value in a + * hashtable + */ + +void +weechat_perl_hashtable_map_cb (void *data, + struct t_hashtable *hashtable, + const void *key, + const void *value) +{ + HV *hash; + + /* make C compiler happy */ + (void) hashtable; + + hash = (HV *)data; + + (void) hv_store (hash, (char *)key, strlen ((char *)key), + newSVpv ((char *)value, 0), 0); +} + +/* + * weechat_perl_hashtable_to_hash: get perl hash with a WeeChat hashtable + */ + +HV * +weechat_perl_hashtable_to_hash (struct t_hashtable *hashtable) +{ + HV *hash; + + hash = (HV *)newHV (); + if (!hash) + return NULL; + + weechat_hashtable_map (hashtable, + &weechat_perl_hashtable_map_cb, + hash); + + return hash; +} + +/* + * weechat_perl_hash_to_hashtable: get WeeChat hashtable with perl hash + * Hashtable returned has type string for + * both keys and values + * Note: hashtable has to be released after use + * with call to weechat_hashtable_free() + */ + +struct t_hashtable * +weechat_perl_hash_to_hashtable (SV *hash, int hashtable_size) +{ + struct t_hashtable *hashtable; + HV *hash2; + SV *value; + char *str_key; + I32 retlen; + + hashtable = weechat_hashtable_new (hashtable_size, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); + if (!hashtable) + return NULL; + + if ((hash) && SvROK(hash) && SvRV(hash) && (SvTYPE(SvRV(hash)) == SVt_PVHV)) + { + hash2 = (HV *) SvRV(hash); + hv_iterinit (hash2); + while ((value = hv_iternextsv (hash2, &str_key, &retlen))) + { + weechat_hashtable_set (hashtable, str_key, SvPV (value, PL_na)); + } + } + + return hashtable; +} + +/* + * weechat_perl_exec_pv: encapsulation of call to perl_call_pv + */ + +int +weechat_perl_exec_pv (const char *func, const char *format, void **argv) +{ + int i, argc; + HV *hash; + + dSP; + + PUSHMARK(SP); + if (format && format[0]) + { + argc = strlen (format); + for (i = 0; i < argc; i++) + { + switch (format[i]) + { + case 's': /* string */ + XPUSHs(sv_2mortal(newSVpv((char *)argv[i], 0))); + break; + case 'i': /* integer */ + XPUSHs(sv_2mortal(newSViv(*((int *)argv[i])))); + break; + case 'h': /* hash */ + hash = weechat_perl_hashtable_to_hash (argv[i]); + XPUSHs(sv_2mortal((SV *)hash)); + break; + } + } + PUTBACK; + } + return perl_call_pv (func, G_EVAL | G_SCALAR); +} + +/* + * weechat_perl_exec: execute a perl function */ void * weechat_perl_exec (struct t_plugin_script *script, - int ret_type, const char *function, char **argv) + int ret_type, const char *function, + const char *format, void **argv) { char *func; unsigned int count; @@ -166,12 +284,12 @@ weechat_perl_exec (struct t_plugin_script *script, ENTER; SAVETMPS; - PUSHMARK(sp); - count = perl_call_argv (func, G_EVAL | G_SCALAR, argv); + count = weechat_perl_exec_pv (func, format, argv); + ret_value = NULL; mem_err = 1; - + SPAGAIN; if (SvTRUE (ERRSV)) @@ -209,6 +327,11 @@ weechat_perl_exec (struct t_plugin_script *script, *ret_i = POPi; ret_value = ret_i; } + else if (ret_type == WEECHAT_SCRIPT_EXEC_HASHTABLE) + { + ret_value = weechat_perl_hash_to_hashtable (POPs, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE); + } else { weechat_printf (NULL, @@ -221,7 +344,6 @@ weechat_perl_exec (struct t_plugin_script *script, } } - PUTBACK; FREETMPS; LEAVE; @@ -255,7 +377,7 @@ weechat_perl_load (const char *filename) struct t_plugin_script temp_script; int *eval; struct stat buf; - char *perl_argv[2]; + void *perl_argv[2]; #ifdef MULTIPLICITY PerlInterpreter *perl_current_interpreter; @@ -311,20 +433,22 @@ weechat_perl_load (const char *filename) perl_args_count, perl_args, NULL); eval_pv (perl_weechat_code, TRUE); - perl_argv[0] = (char *)filename; - perl_argv[1] = NULL; + perl_argv[0] = (void *)filename; + eval = weechat_perl_exec (&temp_script, + WEECHAT_SCRIPT_EXEC_INT, + "weechat_perl_load_eval_file", + "s", perl_argv); #else snprintf (pkgname, sizeof(pkgname), "%s%d", PKG_NAME_PREFIX, perl_num); perl_num++; temp_script.interpreter = "WeechatPerlScriptLoader"; - perl_argv[0] = (char *)filename; + perl_argv[0] = (void *)filename; perl_argv[1] = pkgname; - perl_argv[2] = NULL; -#endif eval = weechat_perl_exec (&temp_script, WEECHAT_SCRIPT_EXEC_INT, "weechat_perl_load_eval_file", - perl_argv); + "ss", perl_argv); +#endif if (!eval) { weechat_printf (NULL, @@ -434,7 +558,6 @@ void weechat_perl_unload (struct t_plugin_script *script) { int *r; - char *perl_argv[1] = { NULL }; void *interpreter; if ((weechat_perl_plugin->debug >= 1) || !perl_quiet) @@ -455,7 +578,7 @@ weechat_perl_unload (struct t_plugin_script *script) r = (int *) weechat_perl_exec (script, WEECHAT_SCRIPT_EXEC_INT, script->shutdown_func, - perl_argv); + NULL, NULL); if (r) free (r); } @@ -470,8 +593,11 @@ weechat_perl_unload (struct t_plugin_script *script) script); #ifdef MULTIPLICITY - perl_destruct (interpreter); - perl_free (interpreter); + if (interpreter) + { + perl_destruct (interpreter); + perl_free (interpreter); + } #else if (interpreter) free (interpreter); diff --git a/src/plugins/scripts/perl/weechat-perl.h b/src/plugins/scripts/perl/weechat-perl.h index ec75dbc1f..436b8046e 100644 --- a/src/plugins/scripts/perl/weechat-perl.h +++ b/src/plugins/scripts/perl/weechat-perl.h @@ -34,8 +34,11 @@ extern struct t_plugin_script *perl_current_script; extern struct t_plugin_script *perl_registered_script; extern const char *perl_current_script_filename; +extern HV *weechat_perl_hashtable_to_hash (struct t_hashtable *hashtable); +extern struct t_hashtable *weechat_perl_hash_to_hashtable (SV *hash, + int hashtable_size); extern void *weechat_perl_exec (struct t_plugin_script *script, int ret_type, const char *function, - char **argv); + const char *format, void **argv); #endif /* __WEECHAT_PERL_H */ diff --git a/src/plugins/scripts/python/weechat-python-api.c b/src/plugins/scripts/python/weechat-python-api.c index 5f83d4abd..058b449a2 100644 --- a/src/plugins/scripts/python/weechat-python-api.c +++ b/src/plugins/scripts/python/weechat-python-api.c @@ -1064,7 +1064,8 @@ weechat_python_api_config_reload_cb (void *data, struct t_config_file *config_file) { struct t_script_callback *script_callback; - char *python_argv[3], empty_arg[1] = { '\0' }; + void *python_argv[2]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1073,12 +1074,11 @@ weechat_python_api_config_reload_cb (void *data, { python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = script_ptr2str (config_file); - python_argv[2] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "ss", python_argv); if (!rc) ret = WEECHAT_CONFIG_READ_FILE_NOT_FOUND; @@ -1146,7 +1146,8 @@ weechat_python_api_config_read_cb (void *data, const char *option_name, const char *value) { struct t_script_callback *script_callback; - char *python_argv[6], empty_arg[1] = { '\0' }; + void *python_argv[5]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1158,12 +1159,11 @@ weechat_python_api_config_read_cb (void *data, python_argv[2] = script_ptr2str (section); python_argv[3] = (option_name) ? (char *)option_name : empty_arg; python_argv[4] = (value) ? (char *)value : empty_arg; - python_argv[5] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "sssss", python_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_SET_ERROR; @@ -1193,7 +1193,8 @@ weechat_python_api_config_section_write_cb (void *data, const char *section_name) { struct t_script_callback *script_callback; - char *python_argv[4], empty_arg[1] = { '\0' }; + void *python_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1203,12 +1204,11 @@ weechat_python_api_config_section_write_cb (void *data, python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = script_ptr2str (config_file); python_argv[2] = (section_name) ? (char *)section_name : empty_arg; - python_argv[3] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "sss", python_argv); if (!rc) ret = WEECHAT_CONFIG_WRITE_ERROR; @@ -1237,7 +1237,8 @@ weechat_python_api_config_section_write_default_cb (void *data, const char *section_name) { struct t_script_callback *script_callback; - char *python_argv[4], empty_arg[1] = { '\0' }; + void *python_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1247,12 +1248,11 @@ weechat_python_api_config_section_write_default_cb (void *data, python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = script_ptr2str (config_file); python_argv[2] = (section_name) ? (char *)section_name : empty_arg; - python_argv[3] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "sss", python_argv); if (!rc) ret = WEECHAT_CONFIG_WRITE_ERROR; @@ -1282,7 +1282,8 @@ weechat_python_api_config_section_create_option_cb (void *data, const char *value) { struct t_script_callback *script_callback; - char *python_argv[6], empty_arg[1] = { '\0' }; + void *python_argv[5]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1294,12 +1295,11 @@ weechat_python_api_config_section_create_option_cb (void *data, python_argv[2] = script_ptr2str (section); python_argv[3] = (option_name) ? (char *)option_name : empty_arg; python_argv[4] = (value) ? (char *)value : empty_arg; - python_argv[5] = NULL; - + rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "sssss", python_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_SET_ERROR; @@ -1330,7 +1330,8 @@ weechat_python_api_config_section_delete_option_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *python_argv[5], empty_arg[1] = { '\0' }; + void *python_argv[4]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1341,12 +1342,11 @@ weechat_python_api_config_section_delete_option_cb (void *data, python_argv[1] = script_ptr2str (config_file); python_argv[2] = script_ptr2str (section); python_argv[3] = script_ptr2str (option); - python_argv[4] = NULL; - + rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "ssss", python_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_UNSET_ERROR; @@ -1488,7 +1488,8 @@ weechat_python_api_config_option_check_value_cb (void *data, const char *value) { struct t_script_callback *script_callback; - char *python_argv[4], empty_arg[1] = { '\0' }; + void *python_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1498,12 +1499,11 @@ weechat_python_api_config_option_check_value_cb (void *data, python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = script_ptr2str (option); python_argv[2] = (value) ? (char *)value : empty_arg; - python_argv[3] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "sss", python_argv); if (!rc) ret = 0; @@ -1530,7 +1530,8 @@ weechat_python_api_config_option_change_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *python_argv[3], empty_arg[1] = { '\0' }; + void *python_argv[2]; + char empty_arg[1] = { '\0' }; int *rc; script_callback = (struct t_script_callback *)data; @@ -1539,12 +1540,11 @@ weechat_python_api_config_option_change_cb (void *data, { python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = script_ptr2str (option); - python_argv[2] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "ss", python_argv); if (python_argv[1]) free (python_argv[1]); @@ -1563,7 +1563,8 @@ weechat_python_api_config_option_delete_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *python_argv[3], empty_arg[1] = { '\0' }; + void *python_argv[2]; + char empty_arg[1] = { '\0' }; int *rc; script_callback = (struct t_script_callback *)data; @@ -1572,12 +1573,11 @@ weechat_python_api_config_option_delete_cb (void *data, { python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = script_ptr2str (option); - python_argv[2] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "ss", python_argv); if (python_argv[1]) free (python_argv[1]); @@ -2903,7 +2903,8 @@ weechat_python_api_hook_command_cb (void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { struct t_script_callback *script_callback; - char *python_argv[4], empty_arg[1] = { '\0' }; + void *python_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; /* make C compiler happy */ @@ -2916,12 +2917,11 @@ weechat_python_api_hook_command_cb (void *data, struct t_gui_buffer *buffer, python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = script_ptr2str (buffer); python_argv[2] = (argc > 1) ? argv_eol[1] : empty_arg; - python_argv[3] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "sss", python_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -2997,7 +2997,8 @@ weechat_python_api_hook_command_run_cb (void *data, struct t_gui_buffer *buffer, const char *command) { struct t_script_callback *script_callback; - char *python_argv[4], empty_arg[1] = { '\0' }; + void *python_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3007,12 +3008,11 @@ weechat_python_api_hook_command_run_cb (void *data, struct t_gui_buffer *buffer, python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = script_ptr2str (buffer); python_argv[2] = (command) ? (char *)command : empty_arg; - python_argv[3] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "sss", python_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3077,7 +3077,8 @@ int weechat_python_api_hook_timer_cb (void *data, int remaining_calls) { struct t_script_callback *script_callback; - char *python_argv[3], str_remaining_calls[32], empty_arg[1] = { '\0' }; + void *python_argv[2]; + char str_remaining_calls[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3089,12 +3090,11 @@ weechat_python_api_hook_timer_cb (void *data, int remaining_calls) python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = str_remaining_calls; - python_argv[2] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "ss", python_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3163,7 +3163,8 @@ int weechat_python_api_hook_fd_cb (void *data, int fd) { struct t_script_callback *script_callback; - char *python_argv[3], str_fd[32], empty_arg[1] = { '\0' }; + void *python_argv[2]; + char str_fd[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3174,12 +3175,11 @@ weechat_python_api_hook_fd_cb (void *data, int fd) python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = str_fd; - python_argv[2] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "ss", python_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3252,7 +3252,8 @@ weechat_python_api_hook_process_cb (void *data, const char *out, const char *err) { struct t_script_callback *script_callback; - char *python_argv[6], str_rc[32], empty_arg[1] = { '\0' }; + void *python_argv[5]; + char str_rc[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3266,12 +3267,11 @@ weechat_python_api_hook_process_cb (void *data, python_argv[2] = str_rc; python_argv[3] = (out) ? (char *)out : empty_arg; python_argv[4] = (err) ? (char *)err : empty_arg; - python_argv[5] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "sssss", python_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3338,8 +3338,8 @@ weechat_python_api_hook_connect_cb (void *data, int status, int gnutls_rc, const char *error, const char *ip_address) { struct t_script_callback *script_callback; - char *python_argv[6], str_status[32], str_gnutls_rc[32]; - char empty_arg[1] = { '\0' }; + void *python_argv[5]; + char str_status[32], str_gnutls_rc[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3354,12 +3354,11 @@ weechat_python_api_hook_connect_cb (void *data, int status, int gnutls_rc, python_argv[2] = str_gnutls_rc; python_argv[3] = (ip_address) ? (char *)ip_address : empty_arg; python_argv[4] = (error) ? (char *)error : empty_arg; - python_argv[5] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "sssss", python_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3441,7 +3440,8 @@ weechat_python_api_hook_print_cb (void *data, struct t_gui_buffer *buffer, const char *prefix, const char *message) { struct t_script_callback *script_callback; - char *python_argv[9], empty_arg[1] = { '\0' }; + void *python_argv[8]; + char empty_arg[1] = { '\0' }; static char timebuffer[64]; int *rc, ret; @@ -3464,12 +3464,11 @@ weechat_python_api_hook_print_cb (void *data, struct t_gui_buffer *buffer, python_argv[5] = (highlight) ? strdup ("1") : strdup ("0"); python_argv[6] = (prefix) ? (char *)prefix : empty_arg; python_argv[7] = (message) ? (char *)message : empty_arg; - python_argv[8] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "ssssssss", python_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3549,7 +3548,8 @@ weechat_python_api_hook_signal_cb (void *data, const char *signal, const char *t void *signal_data) { struct t_script_callback *script_callback; - char *python_argv[4], empty_arg[1] = { '\0' }; + void *python_argv[3]; + char empty_arg[1] = { '\0' }; static char value_str[64]; int *rc, ret, free_needed; @@ -3577,12 +3577,11 @@ weechat_python_api_hook_signal_cb (void *data, const char *signal, const char *t } else python_argv[2] = empty_arg; - python_argv[3] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "sss", python_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3701,7 +3700,8 @@ int weechat_python_api_hook_config_cb (void *data, const char *option, const char *value) { struct t_script_callback *script_callback; - char *python_argv[4], empty_arg[1] = { '\0' }; + void *python_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3711,12 +3711,11 @@ weechat_python_api_hook_config_cb (void *data, const char *option, const char *v python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = (option) ? (char *)option : empty_arg; python_argv[2] = (value) ? (char *)value : empty_arg; - python_argv[3] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "sss", python_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3781,7 +3780,8 @@ weechat_python_api_hook_completion_cb (void *data, const char *completion_item, struct t_gui_completion *completion) { struct t_script_callback *script_callback; - char *python_argv[5], empty_arg[1] = { '\0' }; + void *python_argv[4]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3792,12 +3792,11 @@ weechat_python_api_hook_completion_cb (void *data, const char *completion_item, python_argv[1] = (completion_item) ? (char *)completion_item : empty_arg; python_argv[2] = script_ptr2str (buffer); python_argv[3] = script_ptr2str (completion); - python_argv[4] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "ssss", python_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3907,7 +3906,8 @@ weechat_python_api_hook_modifier_cb (void *data, const char *modifier, const char *modifier_data, const char *string) { struct t_script_callback *script_callback; - char *python_argv[5], empty_arg[1] = { '\0' }; + void *python_argv[4]; + char empty_arg[1] = { '\0' }; script_callback = (struct t_script_callback *)data; @@ -3917,12 +3917,11 @@ weechat_python_api_hook_modifier_cb (void *data, const char *modifier, python_argv[1] = (modifier) ? (char *)modifier : empty_arg; python_argv[2] = (modifier_data) ? (char *)modifier_data : empty_arg; python_argv[3] = (string) ? (char *)string : empty_arg; - python_argv[4] = NULL; return (char *)weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - python_argv); + "ssss", python_argv); } return NULL; @@ -4010,7 +4009,8 @@ weechat_python_api_hook_info_cb (void *data, const char *info_name, const char *arguments) { struct t_script_callback *script_callback; - char *python_argv[4], empty_arg[1] = { '\0' }; + void *python_argv[3]; + char empty_arg[1] = { '\0' }; script_callback = (struct t_script_callback *)data; @@ -4019,12 +4019,11 @@ weechat_python_api_hook_info_cb (void *data, const char *info_name, python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = (info_name) ? (char *)info_name : empty_arg; python_argv[2] = (arguments) ? (char *)arguments : empty_arg; - python_argv[3] = NULL; return (const char *)weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - python_argv); + "sss", python_argv); } return NULL; @@ -4075,6 +4074,89 @@ weechat_python_api_hook_info (PyObject *self, PyObject *args) } /* + * weechat_python_api_hook_info_hashtable_cb: callback for info_hashtable hooked + */ + +struct t_hashtable * +weechat_python_api_hook_info_hashtable_cb (void *data, const char *info_name, + struct t_hashtable *hashtable) +{ + struct t_script_callback *script_callback; + void *python_argv[3]; + char empty_arg[1] = { '\0' }; + struct t_hashtable *ret_hashtable; + + script_callback = (struct t_script_callback *)data; + + if (script_callback && script_callback->function && script_callback->function[0]) + { + python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; + python_argv[1] = (info_name) ? (char *)info_name : empty_arg; + python_argv[2] = weechat_python_hashtable_to_dict (hashtable); + + ret_hashtable = weechat_python_exec (script_callback->script, + WEECHAT_SCRIPT_EXEC_HASHTABLE, + script_callback->function, + "ssO", python_argv); + + if (python_argv[2]) + Py_XDECREF(python_argv[2]); + + return ret_hashtable; + } + + return NULL; +} + +/* + * weechat_python_api_hook_info_hashtable: hook an info_hashtable + */ + +static PyObject * +weechat_python_api_hook_info_hashtable (PyObject *self, PyObject *args) +{ + char *info_name, *description, *args_description, *output_description; + char *function, *data, *result; + PyObject *object; + + /* make C compiler happy */ + (void) self; + + if (!python_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INIT(PYTHON_CURRENT_SCRIPT_NAME, "hook_info_hashtable"); + PYTHON_RETURN_EMPTY; + } + + info_name = NULL; + description = NULL; + args_description = NULL; + output_description = NULL; + function = NULL; + data = NULL; + + if (!PyArg_ParseTuple (args, "ssssss", &info_name, &description, + &args_description, &output_description, + &function, &data)) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGS(PYTHON_CURRENT_SCRIPT_NAME, "hook_info_hashtable"); + PYTHON_RETURN_EMPTY; + } + + result = script_ptr2str(script_api_hook_info_hashtable (weechat_python_plugin, + python_current_script, + info_name, + description, + args_description, + output_description, + &weechat_python_api_hook_info_hashtable_cb, + function, + data)); + + PYTHON_RETURN_STRING_FREE(result); +} + +/* * weechat_python_api_hook_infolist_cb: callback for infolist hooked */ @@ -4083,7 +4165,8 @@ weechat_python_api_hook_infolist_cb (void *data, const char *infolist_name, void *pointer, const char *arguments) { struct t_script_callback *script_callback; - char *python_argv[5], empty_arg[1] = { '\0' }; + void *python_argv[4]; + char empty_arg[1] = { '\0' }; struct t_infolist *result; script_callback = (struct t_script_callback *)data; @@ -4094,12 +4177,11 @@ weechat_python_api_hook_infolist_cb (void *data, const char *infolist_name, python_argv[1] = (infolist_name) ? (char *)infolist_name : empty_arg; python_argv[2] = script_ptr2str (pointer); python_argv[3] = (arguments) ? (char *)arguments : empty_arg; - python_argv[4] = NULL; result = (struct t_infolist *)weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - python_argv); + "ssss", python_argv); if (python_argv[2]) free (python_argv[2]); @@ -4222,7 +4304,8 @@ weechat_python_api_buffer_input_data_cb (void *data, struct t_gui_buffer *buffer const char *input_data) { struct t_script_callback *script_callback; - char *python_argv[4], empty_arg[1] = { '\0' }; + void *python_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4232,12 +4315,11 @@ weechat_python_api_buffer_input_data_cb (void *data, struct t_gui_buffer *buffer python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = script_ptr2str (buffer); python_argv[2] = (input_data) ? (char *)input_data : empty_arg; - python_argv[3] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "sss", python_argv); if (!rc) ret = WEECHAT_RC_ERROR; else @@ -4262,7 +4344,8 @@ int weechat_python_api_buffer_close_cb (void *data, struct t_gui_buffer *buffer) { struct t_script_callback *script_callback; - char *python_argv[3], empty_arg[1] = { '\0' }; + void *python_argv[2]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4271,12 +4354,11 @@ weechat_python_api_buffer_close_cb (void *data, struct t_gui_buffer *buffer) { python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = script_ptr2str (buffer); - python_argv[2] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "ss", python_argv); if (!rc) ret = WEECHAT_RC_ERROR; else @@ -5177,7 +5259,8 @@ weechat_python_api_bar_item_build_cb (void *data, struct t_gui_bar_item *item, struct t_gui_window *window) { struct t_script_callback *script_callback; - char *python_argv[4], empty_arg[1] = { '\0' }, *ret; + void *python_argv[3]; + char empty_arg[1] = { '\0' }, *ret; script_callback = (struct t_script_callback *)data; @@ -5186,12 +5269,11 @@ weechat_python_api_bar_item_build_cb (void *data, struct t_gui_bar_item *item, python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; python_argv[1] = script_ptr2str (item); python_argv[2] = script_ptr2str (window); - python_argv[3] = NULL; ret = (char *)weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - python_argv); + "sss", python_argv); if (python_argv[1]) free (python_argv[1]); @@ -5537,7 +5619,7 @@ weechat_python_api_command (PyObject *self, PyObject *args) } /* - * weechat_python_api_info_get: get info about WeeChat + * weechat_python_api_info_get: get info (as string) */ static PyObject * @@ -5569,6 +5651,47 @@ weechat_python_api_info_get (PyObject *self, PyObject *args) } /* + * weechat_python_api_info_get_hashtable: get info (as hashtable) + */ + +static PyObject * +weechat_python_api_info_get_hashtable (PyObject *self, PyObject *args) +{ + char *info_name; + struct t_hashtable *hashtable, *result_hashtable; + PyObject *dict, *result_dict; + + /* make C compiler happy */ + (void) self; + + if (!python_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INIT(PYTHON_CURRENT_SCRIPT_NAME, "info_get_hashtable"); + PYTHON_RETURN_EMPTY; + } + + info_name = NULL; + + if (!PyArg_ParseTuple (args, "sO", &info_name, &dict)) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGS(PYTHON_CURRENT_SCRIPT_NAME, "info_get_hashtable"); + PYTHON_RETURN_EMPTY; + } + hashtable = weechat_python_dict_to_hashtable (dict, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE); + + result_hashtable = weechat_info_get_hashtable (info_name, hashtable); + result_dict = weechat_python_hashtable_to_dict (result_hashtable); + + if (hashtable) + weechat_hashtable_free (hashtable); + if (result_hashtable) + weechat_hashtable_free (result_hashtable); + + return result_dict; +} + +/* * weechat_python_api_infolist_new: create new infolist */ @@ -6158,7 +6281,8 @@ weechat_python_api_upgrade_read_cb (void *data, struct t_infolist *infolist) { struct t_script_callback *script_callback; - char *python_argv[5], empty_arg[1] = { '\0' }, str_object_id[32]; + void *python_argv[4]; + char empty_arg[1] = { '\0' }, str_object_id[32]; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -6171,12 +6295,11 @@ weechat_python_api_upgrade_read_cb (void *data, python_argv[1] = script_ptr2str (upgrade_file); python_argv[2] = str_object_id; python_argv[3] = script_ptr2str (infolist); - python_argv[4] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - python_argv); + "ssss", python_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -6357,6 +6480,7 @@ PyMethodDef weechat_python_funcs[] = { "hook_modifier", &weechat_python_api_hook_modifier, METH_VARARGS, "" }, { "hook_modifier_exec", &weechat_python_api_hook_modifier_exec, METH_VARARGS, "" }, { "hook_info", &weechat_python_api_hook_info, METH_VARARGS, "" }, + { "hook_info_hashtable", &weechat_python_api_hook_info_hashtable, METH_VARARGS, "" }, { "hook_infolist", &weechat_python_api_hook_infolist, METH_VARARGS, "" }, { "unhook", &weechat_python_api_unhook, METH_VARARGS, "" }, { "unhook_all", &weechat_python_api_unhook_all, METH_VARARGS, "" }, @@ -6396,6 +6520,7 @@ PyMethodDef weechat_python_funcs[] = { "bar_remove", &weechat_python_api_bar_remove, METH_VARARGS, "" }, { "command", &weechat_python_api_command, METH_VARARGS, "" }, { "info_get", &weechat_python_api_info_get, METH_VARARGS, "" }, + { "info_get_hashtable", &weechat_python_api_info_get_hashtable, METH_VARARGS, "" }, { "infolist_new", &weechat_python_api_infolist_new, METH_VARARGS, "" }, { "infolist_new_item", &weechat_python_api_infolist_new_item, METH_VARARGS, "" }, { "infolist_new_var_integer", &weechat_python_api_infolist_new_var_integer, METH_VARARGS, "" }, diff --git a/src/plugins/scripts/python/weechat-python.c b/src/plugins/scripts/python/weechat-python.c index 110bbe0cf..fabe584da 100644 --- a/src/plugins/scripts/python/weechat-python.c +++ b/src/plugins/scripts/python/weechat-python.c @@ -68,12 +68,100 @@ char python_buffer_output[128]; /* - * weechat_python_exec: execute a Python script + * weechat_python_hashtable_map_cb: callback called for each key/value in a + * hashtable + */ + +void +weechat_python_hashtable_map_cb (void *data, + struct t_hashtable *hashtable, + const void *key, + const void *value) +{ + PyObject *dict, *dict_key, *dict_value; + + /* make C compiler happy */ + (void) hashtable; + + dict = (PyObject *)data; + + dict_key = Py_BuildValue ("s", (const char *)key); + dict_value = Py_BuildValue ("s", (const char *)value); + + PyDict_SetItem (dict, dict_key, dict_value); + + Py_DECREF (dict_key); + Py_DECREF (dict_value); +} + +/* + * weechat_python_hashtable_to_dict: get python dictionary with a WeeChat + * hashtable + */ + +PyObject * +weechat_python_hashtable_to_dict (struct t_hashtable *hashtable) +{ + PyObject *dict; + + dict = PyDict_New (); + if (!dict) + { + Py_INCREF(Py_None); + return Py_None; + } + + weechat_hashtable_map (hashtable, + &weechat_python_hashtable_map_cb, + dict); + + return dict; +} + +/* + * weechat_python_dict_to_hashtable: get WeeChat hashtable with python + * dictionary + * Hashtable returned has type string for + * both keys and values + * Note: hashtable has to be released after + * use with call to weechat_hashtable_free() + */ + +struct t_hashtable * +weechat_python_dict_to_hashtable (PyObject *dict, int hashtable_size) +{ + struct t_hashtable *hashtable; + PyObject *key, *value; + Py_ssize_t pos; + char *str_key, *str_value; + + hashtable = weechat_hashtable_new (hashtable_size, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); + if (!hashtable) + return NULL; + + pos = 0; + while (PyDict_Next (dict, &pos, &key, &value)) + { + str_key = PyString_AsString (key); + str_value = PyString_AsString (value); + weechat_hashtable_set (hashtable, (void *)str_key, (void *)str_value); + } + + return hashtable; +} + +/* + * weechat_python_exec: execute a python function */ void * weechat_python_exec (struct t_plugin_script *script, - int ret_type, const char *function, char **argv) + int ret_type, const char *function, + char *format, void **argv) { struct t_plugin_script *old_python_current_script; PyThreadState *old_interpreter; @@ -81,8 +169,8 @@ weechat_python_exec (struct t_plugin_script *script, PyObject *evDict; PyObject *evFunc; PyObject *rc; - void *ret_value; - int *ret_i; + void *argv2[16], *ret_value; + int i, argc, *ret_int; /* PyEval_AcquireLock (); */ @@ -110,78 +198,28 @@ weechat_python_exec (struct t_plugin_script *script, } python_current_script = script; - + if (argv && argv[0]) { - if (argv[1]) + argc = strlen (format); + for (i = 0; i < 16; i++) { - if (argv[2]) - { - if (argv[3]) - { - if (argv[4]) - { - if (argv[5]) - { - if (argv[6]) - { - if (argv[7]) - { - rc = PyObject_CallFunction (evFunc, "ssssssss", - argv[0], argv[1], - argv[2], argv[3], - argv[4], argv[5], - argv[6], argv[7]); - } - else - { - rc = PyObject_CallFunction (evFunc, "sssssss", - argv[0], argv[1], - argv[2], argv[3], - argv[4], argv[5], - argv[6]); - } - } - else - { - rc = PyObject_CallFunction (evFunc, "ssssss", - argv[0], argv[1], - argv[2], argv[3], - argv[4], argv[5]); - } - } - else - { - rc = PyObject_CallFunction (evFunc, "sssss", - argv[0], argv[1], - argv[2], argv[3], - argv[4]); - } - } - else - { - rc = PyObject_CallFunction (evFunc, "ssss", argv[0], - argv[1], argv[2], argv[3]); - } - } - else - { - rc = PyObject_CallFunction (evFunc, "sss", argv[0], - argv[1], argv[2]); - } - } - else - { - rc = PyObject_CallFunction (evFunc, "ss", argv[0], argv[1]); - } - } - else - { - rc = PyObject_CallFunction (evFunc, "s", argv[0]); + argv2[i] = (i < argc) ? argv[i] : NULL; } + rc = PyObject_CallFunction (evFunc, format, + argv2[0], argv2[1], + argv2[2], argv2[3], + argv2[4], argv2[5], + argv2[6], argv2[7], + argv2[8], argv2[9], + argv2[10], argv2[11], + argv2[12], argv2[13], + argv2[14], argv2[15]); } else + { rc = PyObject_CallFunction (evFunc, NULL); + } ret_value = NULL; @@ -197,22 +235,26 @@ weechat_python_exec (struct t_plugin_script *script, PyErr_Print (); Py_XDECREF(rc); } - else if (PyString_Check (rc) && (ret_type == WEECHAT_SCRIPT_EXEC_STRING)) + else if ((ret_type == WEECHAT_SCRIPT_EXEC_STRING) && (PyString_Check (rc))) { if (PyString_AsString (rc)) ret_value = strdup (PyString_AsString(rc)); else ret_value = NULL; - Py_XDECREF(rc); } - else if (PyInt_Check (rc) && (ret_type == WEECHAT_SCRIPT_EXEC_INT)) + else if ((ret_type == WEECHAT_SCRIPT_EXEC_INT) && (PyInt_Check (rc))) { - ret_i = malloc (sizeof (*ret_i)); - if (ret_i) - *ret_i = (int) PyInt_AsLong(rc); - ret_value = ret_i; - + ret_int = malloc (sizeof (*ret_int)); + if (ret_int) + *ret_int = (int) PyInt_AsLong(rc); + ret_value = ret_int; + Py_XDECREF(rc); + } + else if (ret_type == WEECHAT_SCRIPT_EXEC_HASHTABLE) + { + ret_value = weechat_python_dict_to_hashtable (rc, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE); Py_XDECREF(rc); } else @@ -241,7 +283,7 @@ weechat_python_exec (struct t_plugin_script *script, } /* - * weechat_python_output : redirection for stdout and stderr + * weechat_python_output: redirection for stdout and stderr */ static PyObject * @@ -552,7 +594,7 @@ weechat_python_unload (struct t_plugin_script *script) if (script->shutdown_func && script->shutdown_func[0]) { r = (int *) weechat_python_exec (script, WEECHAT_SCRIPT_EXEC_INT, - script->shutdown_func, NULL); + script->shutdown_func, NULL, NULL); if (r) free (r); } diff --git a/src/plugins/scripts/python/weechat-python.h b/src/plugins/scripts/python/weechat-python.h index 9a456401f..ad80fa2b6 100644 --- a/src/plugins/scripts/python/weechat-python.h +++ b/src/plugins/scripts/python/weechat-python.h @@ -35,8 +35,11 @@ extern struct t_plugin_script *python_current_script; extern struct t_plugin_script *python_registered_script; extern const char *python_current_script_filename; +extern PyObject *weechat_python_hashtable_to_dict (struct t_hashtable *hashtable); +extern struct t_hashtable *weechat_python_dict_to_hashtable (PyObject *dict, + int hashtable_size); extern void *weechat_python_exec (struct t_plugin_script *script, int ret_type, const char *function, - char **argv); + char *format, void **argv); #endif /* __WEECHAT_PYTHON_H */ diff --git a/src/plugins/scripts/ruby/weechat-ruby-api.c b/src/plugins/scripts/ruby/weechat-ruby-api.c index 0e52378a5..f06d5b758 100644 --- a/src/plugins/scripts/ruby/weechat-ruby-api.c +++ b/src/plugins/scripts/ruby/weechat-ruby-api.c @@ -1224,7 +1224,8 @@ weechat_ruby_api_config_reload_cb (void *data, struct t_config_file *config_file) { struct t_script_callback *script_callback; - char *ruby_argv[3], empty_arg[1] = { '\0' }; + void *ruby_argv[2]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1233,12 +1234,11 @@ weechat_ruby_api_config_reload_cb (void *data, { ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = script_ptr2str (config_file); - ruby_argv[2] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "ss", ruby_argv); if (!rc) ret = WEECHAT_CONFIG_READ_FILE_NOT_FOUND; @@ -1315,7 +1315,8 @@ weechat_ruby_api_config_read_cb (void *data, const char *option_name, const char *value) { struct t_script_callback *script_callback; - char *ruby_argv[6], empty_arg[1] = { '\0' }; + void *ruby_argv[5]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1327,12 +1328,11 @@ weechat_ruby_api_config_read_cb (void *data, ruby_argv[2] = script_ptr2str (section); ruby_argv[3] = (option_name) ? (char *)option_name : empty_arg; ruby_argv[4] = (value) ? (char *)value : empty_arg; - ruby_argv[5] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "sssss", ruby_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_SET_ERROR; @@ -1362,7 +1362,8 @@ weechat_ruby_api_config_section_write_cb (void *data, const char *section_name) { struct t_script_callback *script_callback; - char *ruby_argv[4], empty_arg[1] = { '\0' }; + void *ruby_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1372,12 +1373,11 @@ weechat_ruby_api_config_section_write_cb (void *data, ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = script_ptr2str (config_file); ruby_argv[2] = (section_name) ? (char *)section_name : empty_arg; - ruby_argv[3] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "sss", ruby_argv); if (!rc) ret = WEECHAT_CONFIG_WRITE_ERROR; @@ -1406,7 +1406,8 @@ weechat_ruby_api_config_section_write_default_cb (void *data, const char *section_name) { struct t_script_callback *script_callback; - char *ruby_argv[4], empty_arg[1] = { '\0' }; + void *ruby_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1416,12 +1417,11 @@ weechat_ruby_api_config_section_write_default_cb (void *data, ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = script_ptr2str (config_file); ruby_argv[2] = (section_name) ? (char *)section_name : empty_arg; - ruby_argv[3] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "sss", ruby_argv); if (!rc) ret = WEECHAT_CONFIG_WRITE_ERROR; @@ -1451,7 +1451,8 @@ weechat_ruby_api_config_section_create_option_cb (void *data, const char *value) { struct t_script_callback *script_callback; - char *ruby_argv[6], empty_arg[1] = { '\0' }; + void *ruby_argv[5]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1463,12 +1464,11 @@ weechat_ruby_api_config_section_create_option_cb (void *data, ruby_argv[2] = script_ptr2str (section); ruby_argv[3] = (option_name) ? (char *)option_name : empty_arg; ruby_argv[4] = (value) ? (char *)value : empty_arg; - ruby_argv[5] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "sssss", ruby_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_SET_ERROR; @@ -1499,7 +1499,8 @@ weechat_ruby_api_config_section_delete_option_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *ruby_argv[5], empty_arg[1] = { '\0' }; + void *ruby_argv[4]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1510,12 +1511,11 @@ weechat_ruby_api_config_section_delete_option_cb (void *data, ruby_argv[1] = script_ptr2str (config_file); ruby_argv[2] = script_ptr2str (section); ruby_argv[3] = script_ptr2str (option); - ruby_argv[4] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "ssss", ruby_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_UNSET_ERROR; @@ -1706,7 +1706,8 @@ weechat_ruby_api_config_option_check_value_cb (void *data, const char *value) { struct t_script_callback *script_callback; - char *ruby_argv[4], empty_arg[1] = { '\0' }; + void *ruby_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1716,12 +1717,11 @@ weechat_ruby_api_config_option_check_value_cb (void *data, ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = script_ptr2str (option); ruby_argv[2] = (value) ? (char *)value : empty_arg; - ruby_argv[3] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "sss", ruby_argv); if (!rc) ret = 0; @@ -1748,7 +1748,8 @@ weechat_ruby_api_config_option_change_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *ruby_argv[3], empty_arg[1] = { '\0' }; + void *ruby_argv[2]; + char empty_arg[1] = { '\0' }; int *rc; script_callback = (struct t_script_callback *)data; @@ -1757,12 +1758,11 @@ weechat_ruby_api_config_option_change_cb (void *data, { ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = script_ptr2str (option); - ruby_argv[2] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "ss", ruby_argv); if (ruby_argv[1]) free (ruby_argv[1]); @@ -1781,7 +1781,8 @@ weechat_ruby_api_config_option_delete_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *ruby_argv[3], empty_arg[1] = { '\0' }; + void *ruby_argv[2]; + char empty_arg[1] = { '\0' }; int *rc; script_callback = (struct t_script_callback *)data; @@ -1790,12 +1791,11 @@ weechat_ruby_api_config_option_delete_cb (void *data, { ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = script_ptr2str (option); - ruby_argv[2] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "ss", ruby_argv); if (ruby_argv[1]) free (ruby_argv[1]); @@ -3348,7 +3348,8 @@ weechat_ruby_api_hook_command_cb (void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { struct t_script_callback *script_callback; - char *ruby_argv[4], empty_arg[1] = { '\0' }; + void *ruby_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; /* make C compiler happy */ @@ -3361,12 +3362,11 @@ weechat_ruby_api_hook_command_cb (void *data, struct t_gui_buffer *buffer, ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = script_ptr2str (buffer); ruby_argv[2] = (argc > 1) ? argv_eol[1] : empty_arg; - ruby_argv[3] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "sss", ruby_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3461,7 +3461,8 @@ weechat_ruby_api_hook_command_run_cb (void *data, struct t_gui_buffer *buffer, const char *command) { struct t_script_callback *script_callback; - char *ruby_argv[4], empty_arg[1] = { '\0' }; + void *ruby_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3471,12 +3472,11 @@ weechat_ruby_api_hook_command_run_cb (void *data, struct t_gui_buffer *buffer, ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = script_ptr2str (buffer); ruby_argv[2] = (command) ? (char *)command : empty_arg; - ruby_argv[3] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "sss", ruby_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3550,7 +3550,8 @@ int weechat_ruby_api_hook_timer_cb (void *data, int remaining_calls) { struct t_script_callback *script_callback; - char *ruby_argv[3], str_remaining_calls[32], empty_arg[1] = { '\0' }; + void *ruby_argv[2]; + char str_remaining_calls[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3562,12 +3563,11 @@ weechat_ruby_api_hook_timer_cb (void *data, int remaining_calls) ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = str_remaining_calls; - ruby_argv[2] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "ss", ruby_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3649,7 +3649,8 @@ int weechat_ruby_api_hook_fd_cb (void *data, int fd) { struct t_script_callback *script_callback; - char *ruby_argv[3], str_fd[32], empty_arg[1] = { '\0' }; + void *ruby_argv[2]; + char str_fd[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3660,12 +3661,11 @@ weechat_ruby_api_hook_fd_cb (void *data, int fd) ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = str_fd; - ruby_argv[2] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "ss", ruby_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3753,7 +3753,8 @@ weechat_ruby_api_hook_process_cb (void *data, const char *out, const char *err) { struct t_script_callback *script_callback; - char *ruby_argv[6], str_rc[32], empty_arg[1] = { '\0' }; + void *ruby_argv[5]; + char str_rc[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3767,12 +3768,11 @@ weechat_ruby_api_hook_process_cb (void *data, ruby_argv[2] = str_rc; ruby_argv[3] = (out) ? (char *)out : empty_arg; ruby_argv[4] = (err) ? (char *)err : empty_arg; - ruby_argv[5] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "sssss", ruby_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3850,7 +3850,8 @@ weechat_ruby_api_hook_connect_cb (void *data, int status, int gnutls_rc, const char *error, const char *ip_address) { struct t_script_callback *script_callback; - char *ruby_argv[6], str_status[32], str_gnutls_rc[32]; + void *ruby_argv[5]; + char str_status[32], str_gnutls_rc[32]; char empty_arg[1] = { '\0' }; int *rc, ret; @@ -3866,12 +3867,11 @@ weechat_ruby_api_hook_connect_cb (void *data, int status, int gnutls_rc, ruby_argv[2] = str_gnutls_rc; ruby_argv[3] = (ip_address) ? (char *)ip_address : empty_arg; ruby_argv[4] = (error) ? (char *)error : empty_arg; - ruby_argv[5] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "sssss", ruby_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3975,7 +3975,8 @@ weechat_ruby_api_hook_print_cb (void *data, struct t_gui_buffer *buffer, const char *prefix, const char *message) { struct t_script_callback *script_callback; - char *ruby_argv[9], empty_arg[1] = { '\0' }; + void *ruby_argv[8]; + char empty_arg[1] = { '\0' }; static char timebuffer[64]; int *rc, ret; @@ -3998,12 +3999,11 @@ weechat_ruby_api_hook_print_cb (void *data, struct t_gui_buffer *buffer, ruby_argv[5] = (highlight) ? strdup ("1") : strdup ("0"); ruby_argv[6] = (prefix) ? (char *)prefix : empty_arg; ruby_argv[7] = (message) ? (char *)message : empty_arg; - ruby_argv[8] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "ssssssss", ruby_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -4099,7 +4099,8 @@ weechat_ruby_api_hook_signal_cb (void *data, const char *signal, const char *typ void *signal_data) { struct t_script_callback *script_callback; - char *ruby_argv[4], empty_arg[1] = { '\0' }; + void *ruby_argv[3]; + char empty_arg[1] = { '\0' }; static char value_str[64]; int *rc, ret, free_needed; @@ -4127,12 +4128,11 @@ weechat_ruby_api_hook_signal_cb (void *data, const char *signal, const char *typ } else ruby_argv[2] = empty_arg; - ruby_argv[3] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "sss", ruby_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -4268,7 +4268,8 @@ int weechat_ruby_api_hook_config_cb (void *data, const char *option, const char *value) { struct t_script_callback *script_callback; - char *ruby_argv[4], empty_arg[1] = { '\0' }; + void *ruby_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4278,12 +4279,11 @@ weechat_ruby_api_hook_config_cb (void *data, const char *option, const char *val ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = (option) ? (char *)option : empty_arg; ruby_argv[2] = (value) ? (char *)value : empty_arg; - ruby_argv[3] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "sss", ruby_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -4357,7 +4357,8 @@ weechat_ruby_api_hook_completion_cb (void *data, const char *completion_item, struct t_gui_completion *completion) { struct t_script_callback *script_callback; - char *ruby_argv[5], empty_arg[1] = { '\0' }; + void *ruby_argv[4]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4368,12 +4369,11 @@ weechat_ruby_api_hook_completion_cb (void *data, const char *completion_item, ruby_argv[1] = (completion_item) ? (char *)completion_item : empty_arg; ruby_argv[2] = script_ptr2str (buffer); ruby_argv[3] = script_ptr2str (completion); - ruby_argv[4] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "ssss", ruby_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -4507,7 +4507,8 @@ weechat_ruby_api_hook_modifier_cb (void *data, const char *modifier, const char *modifier_data, const char *string) { struct t_script_callback *script_callback; - char *ruby_argv[5], empty_arg[1] = { '\0' }; + void *ruby_argv[4]; + char empty_arg[1] = { '\0' }; script_callback = (struct t_script_callback *)data; @@ -4517,12 +4518,11 @@ weechat_ruby_api_hook_modifier_cb (void *data, const char *modifier, ruby_argv[1] = (modifier) ? (char *)modifier : empty_arg; ruby_argv[2] = (modifier_data) ? (char *)modifier_data : empty_arg; ruby_argv[3] = (string) ? (char *)string : empty_arg; - ruby_argv[4] = NULL; return (char *)weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - ruby_argv); + "ssss", ruby_argv); } return NULL; @@ -4628,7 +4628,8 @@ weechat_ruby_api_hook_info_cb (void *data, const char *info_name, const char *arguments) { struct t_script_callback *script_callback; - char *ruby_argv[4], empty_arg[1] = { '\0' }; + void *ruby_argv[3]; + char empty_arg[1] = { '\0' }; script_callback = (struct t_script_callback *)data; @@ -4637,12 +4638,11 @@ weechat_ruby_api_hook_info_cb (void *data, const char *info_name, ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = (info_name) ? (char *)info_name : empty_arg; ruby_argv[2] = (arguments) ? (char *)arguments : empty_arg; - ruby_argv[3] = NULL; return (const char *)weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - ruby_argv); + "sss", ruby_argv); } return NULL; @@ -4707,6 +4707,101 @@ weechat_ruby_api_hook_info (VALUE class, VALUE info_name, VALUE description, } /* + * weechat_ruby_api_hook_info_hashtable_cb: callback for info_hashtable hooked + */ + +struct t_hashtable * +weechat_ruby_api_hook_info_hashtable_cb (void *data, const char *info_name, + struct t_hashtable *hashtable) +{ + struct t_script_callback *script_callback; + void *ruby_argv[3]; + char empty_arg[1] = { '\0' }; + + script_callback = (struct t_script_callback *)data; + + if (script_callback && script_callback->function && script_callback->function[0]) + { + ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; + ruby_argv[1] = (info_name) ? (char *)info_name : empty_arg; + ruby_argv[2] = (void *)weechat_ruby_hashtable_to_hash (hashtable); + + return (struct t_hashtable *)weechat_ruby_exec (script_callback->script, + WEECHAT_SCRIPT_EXEC_HASHTABLE, + script_callback->function, + "ssh", ruby_argv); + } + + return NULL; +} + +/* + * weechat_ruby_api_hook_info_hashtable: hook an info_hashtable + */ + +static VALUE +weechat_ruby_api_hook_info_hashtable (VALUE class, VALUE info_name, + VALUE description, + VALUE args_description, + VALUE output_description, + VALUE function, VALUE data) +{ + char *c_info_name, *c_description, *c_args_description; + char *c_output_description, *c_function; + char *c_data, *result; + VALUE return_value; + + /* make C compiler happy */ + (void) class; + + if (!ruby_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INIT(RUBY_CURRENT_SCRIPT_NAME, "hook_info_hashtable"); + RUBY_RETURN_EMPTY; + } + + c_info_name = NULL; + c_description = NULL; + c_args_description = NULL; + c_output_description = NULL; + c_function = NULL; + c_data = NULL; + + if (NIL_P (info_name) || NIL_P (description) || NIL_P (args_description) + || NIL_P (output_description) || NIL_P (function) || NIL_P (data)) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGS(RUBY_CURRENT_SCRIPT_NAME, "hook_info_hashtable"); + RUBY_RETURN_EMPTY; + } + + Check_Type (info_name, T_STRING); + Check_Type (description, T_STRING); + Check_Type (args_description, T_STRING); + Check_Type (output_description, T_STRING); + Check_Type (function, T_STRING); + Check_Type (data, T_STRING); + + c_info_name = STR2CSTR (info_name); + c_description = STR2CSTR (description); + c_args_description = STR2CSTR (args_description); + c_output_description = STR2CSTR (output_description); + c_function = STR2CSTR (function); + c_data = STR2CSTR (data); + + result = script_ptr2str (script_api_hook_info_hashtable (weechat_ruby_plugin, + ruby_current_script, + c_info_name, + c_description, + c_args_description, + c_output_description, + &weechat_ruby_api_hook_info_hashtable_cb, + c_function, + c_data)); + + RUBY_RETURN_STRING_FREE(result); +} + +/* * weechat_ruby_api_hook_infolist_cb: callback for infolist hooked */ @@ -4715,7 +4810,8 @@ weechat_ruby_api_hook_infolist_cb (void *data, const char *infolist_name, void *pointer, const char *arguments) { struct t_script_callback *script_callback; - char *ruby_argv[5], empty_arg[1] = { '\0' }; + void *ruby_argv[4]; + char empty_arg[1] = { '\0' }; struct t_infolist *result; script_callback = (struct t_script_callback *)data; @@ -4726,12 +4822,11 @@ weechat_ruby_api_hook_infolist_cb (void *data, const char *infolist_name, ruby_argv[1] = (infolist_name) ? (char *)infolist_name : empty_arg; ruby_argv[2] = script_ptr2str (pointer); ruby_argv[3] = (arguments) ? (char *)arguments : empty_arg; - ruby_argv[4] = NULL; result = (struct t_infolist *)weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - ruby_argv); + "ssss", ruby_argv); if (ruby_argv[2]) free (ruby_argv[2]); @@ -4874,7 +4969,8 @@ weechat_ruby_api_buffer_input_data_cb (void *data, struct t_gui_buffer *buffer, const char *input_data) { struct t_script_callback *script_callback; - char *ruby_argv[4], empty_arg[1] = { '\0' }; + void *ruby_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4884,12 +4980,11 @@ weechat_ruby_api_buffer_input_data_cb (void *data, struct t_gui_buffer *buffer, ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = script_ptr2str (buffer); ruby_argv[2] = (input_data) ? (char *)input_data : empty_arg; - ruby_argv[3] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "sss", ruby_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -4915,7 +5010,8 @@ int weechat_ruby_api_buffer_close_cb (void *data, struct t_gui_buffer *buffer) { struct t_script_callback *script_callback; - char *ruby_argv[3], empty_arg[1] = { '\0' }; + void *ruby_argv[2]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4924,12 +5020,11 @@ weechat_ruby_api_buffer_close_cb (void *data, struct t_gui_buffer *buffer) { ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = script_ptr2str (buffer); - ruby_argv[2] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "ss", ruby_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -5965,7 +6060,8 @@ weechat_ruby_api_bar_item_build_cb (void *data, struct t_gui_bar_item *item, struct t_gui_window *window) { struct t_script_callback *script_callback; - char *ruby_argv[4], empty_arg[1] = { '\0' }, *ret; + void *ruby_argv[3]; + char empty_arg[1] = { '\0' }, *ret; script_callback = (struct t_script_callback *)data; @@ -5974,12 +6070,11 @@ weechat_ruby_api_bar_item_build_cb (void *data, struct t_gui_bar_item *item, ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; ruby_argv[1] = script_ptr2str (item); ruby_argv[2] = script_ptr2str (window); - ruby_argv[3] = NULL; ret = (char *)weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - ruby_argv); + "sss", ruby_argv); if (ruby_argv[1]) free (ruby_argv[1]); @@ -6392,7 +6487,7 @@ weechat_ruby_api_command (VALUE class, VALUE buffer, VALUE command) } /* - * weechat_ruby_api_info_get: get info about WeeChat + * weechat_ruby_api_info_get: get info (as string) */ static VALUE @@ -6428,6 +6523,51 @@ weechat_ruby_api_info_get (VALUE class, VALUE info_name, VALUE arguments) } /* + * weechat_ruby_api_info_get_hashtable: get info (as hashtable) + */ + +static VALUE +weechat_ruby_api_info_get_hashtable (VALUE class, VALUE info_name, + VALUE hash) +{ + char *c_info_name; + struct t_hashtable *c_hashtable, *result_hashtable; + VALUE result_hash; + + /* make C compiler happy */ + (void) class; + + if (!ruby_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INIT(RUBY_CURRENT_SCRIPT_NAME, "info_get_hashtable"); + RUBY_RETURN_EMPTY; + } + + if (NIL_P (info_name) || NIL_P (hash)) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGS(RUBY_CURRENT_SCRIPT_NAME, "info_get_hashtable"); + RUBY_RETURN_EMPTY; + } + + Check_Type (info_name, T_STRING); + Check_Type (hash, T_HASH); + + c_info_name = STR2CSTR (info_name); + c_hashtable = weechat_ruby_hash_to_hashtable (hash, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE); + + result_hashtable = weechat_info_get_hashtable (c_info_name, c_hashtable); + result_hash = weechat_ruby_hashtable_to_hash (result_hashtable); + + if (c_hashtable) + weechat_hashtable_free (c_hashtable); + if (result_hashtable) + weechat_hashtable_free (result_hashtable); + + return result_hash; +} + +/* * weechat_ruby_api_infolist_new: create new infolist */ @@ -7070,7 +7210,8 @@ weechat_ruby_api_upgrade_read_cb (void *data, struct t_infolist *infolist) { struct t_script_callback *script_callback; - char *ruby_argv[5], empty_arg[1] = { '\0' }, str_object_id[32]; + void *ruby_argv[4]; + char empty_arg[1] = { '\0' }, str_object_id[32]; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -7083,12 +7224,11 @@ weechat_ruby_api_upgrade_read_cb (void *data, ruby_argv[1] = script_ptr2str (upgrade_file); ruby_argv[2] = str_object_id; ruby_argv[3] = script_ptr2str (infolist); - ruby_argv[4] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - ruby_argv); + "ssss", ruby_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -7326,6 +7466,7 @@ weechat_ruby_api_init (VALUE ruby_mWeechat) rb_define_module_function (ruby_mWeechat, "hook_modifier", &weechat_ruby_api_hook_modifier, 3); rb_define_module_function (ruby_mWeechat, "hook_modifier_exec", &weechat_ruby_api_hook_modifier_exec, 3); rb_define_module_function (ruby_mWeechat, "hook_info", &weechat_ruby_api_hook_info, 5); + rb_define_module_function (ruby_mWeechat, "hook_info_hashtable", &weechat_ruby_api_hook_info_hashtable, 6); rb_define_module_function (ruby_mWeechat, "hook_infolist", &weechat_ruby_api_hook_infolist, 6); rb_define_module_function (ruby_mWeechat, "unhook", &weechat_ruby_api_unhook, 1); rb_define_module_function (ruby_mWeechat, "unhook_all", &weechat_ruby_api_unhook_all, 0); @@ -7365,6 +7506,7 @@ weechat_ruby_api_init (VALUE ruby_mWeechat) rb_define_module_function (ruby_mWeechat, "bar_remove", &weechat_ruby_api_bar_remove, 1); rb_define_module_function (ruby_mWeechat, "command", &weechat_ruby_api_command, 2); rb_define_module_function (ruby_mWeechat, "info_get", &weechat_ruby_api_info_get, 2); + rb_define_module_function (ruby_mWeechat, "info_get_hashtable", &weechat_ruby_api_info_get_hashtable, 2); rb_define_module_function (ruby_mWeechat, "infolist_new", &weechat_ruby_api_infolist_new, 0); rb_define_module_function (ruby_mWeechat, "infolist_new_item", &weechat_ruby_api_infolist_new_item, 1); rb_define_module_function (ruby_mWeechat, "infolist_new_var_integer", &weechat_ruby_api_infolist_new_var_integer, 3); diff --git a/src/plugins/scripts/ruby/weechat-ruby.c b/src/plugins/scripts/ruby/weechat-ruby.c index ffaf816d2..127e7fa21 100644 --- a/src/plugins/scripts/ruby/weechat-ruby.c +++ b/src/plugins/scripts/ruby/weechat-ruby.c @@ -102,6 +102,88 @@ typedef struct protect_call_arg { /* + * weechat_ruby_hashtable_map_cb: callback called for each key/value in a + * hashtable + */ + +void +weechat_ruby_hashtable_map_cb (void *data, + struct t_hashtable *hashtable, + const void *key, + const void *value) +{ + VALUE *hash; + + /* make C compiler happy */ + (void) hashtable; + + hash = (VALUE *)data; + + rb_hash_aset (hash[0], rb_str_new2 ((char *)key), rb_str_new2 ((char *)value)); +} + +/* + * weechat_ruby_hashtable_to_hash: get ruby hash with a WeeChat hashtable + */ + +VALUE +weechat_ruby_hashtable_to_hash (struct t_hashtable *hashtable) +{ + VALUE hash; + + hash = rb_hash_new (); + if (NIL_P (hash)) + return Qnil; + + weechat_hashtable_map (hashtable, + &weechat_ruby_hashtable_map_cb, + &hash); + + return hash; +} + +int +weechat_ruby_hash_foreach_cb (VALUE key, VALUE value, void *arg) +{ + struct t_hashtable *hashtable; + + hashtable = (struct t_hashtable *)arg; + if ((TYPE(key) == T_STRING) && (TYPE(value) == T_STRING)) + { + weechat_hashtable_set (hashtable, STR2CSTR(key), STR2CSTR(value)); + } + return 0; +} + +/* + * weechat_ruby_hash_to_hashtable: get WeeChat hashtable with ruby hashtable + * Hashtable returned has type string for + * both keys and values + * Note: hashtable has to be released after use + * with call to weechat_hashtable_free() + */ + +struct t_hashtable * +weechat_ruby_hash_to_hashtable (VALUE hash, int hashtable_size) +{ + struct t_hashtable *hashtable; + struct st_table *st; + + hashtable = weechat_hashtable_new (hashtable_size, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); + if (!hashtable) + return NULL; + + st = RHASH_TBL(hash); + rb_hash_foreach (hash, &weechat_ruby_hash_foreach_cb, (unsigned long)hashtable); + + return hashtable; +} + +/* * protect_funcall0 : used to protect a function call */ @@ -115,32 +197,19 @@ protect_funcall0 (VALUE arg) } /* - * rb_protect_funcall : function call in protect mode + * rb_protect_funcall: function call in protect mode */ VALUE -rb_protect_funcall (VALUE recv, ID mid, int *state, int argc, ...) +rb_protect_funcall (VALUE recv, ID mid, int *state, int argc, VALUE *argv) { - va_list ap; - VALUE *argv; struct protect_call_arg arg; - - if (argc > 0) - { - int i; - argv = ALLOCA_N(VALUE, argc); - va_start(ap, argc); - for (i = 0; i < argc; i++) - argv[i] = va_arg(ap, VALUE); - va_end(ap); - } - else - argv = 0; + arg.recv = recv; arg.mid = mid; arg.argc = argc; arg.argv = argv; - return rb_protect(protect_funcall0, (VALUE) &arg, state); + return rb_protect (protect_funcall0, (VALUE) &arg, state); } /* @@ -159,13 +228,13 @@ weechat_ruby_print_exception (VALUE err) char* err_class; backtrace = rb_protect_funcall (err, rb_intern("backtrace"), - &ruby_error, 0); + &ruby_error, 0, NULL); err_msg = STR2CSTR(rb_protect_funcall(err, rb_intern("message"), - &ruby_error, 0)); + &ruby_error, 0, NULL)); err_class = STR2CSTR(rb_protect_funcall(rb_protect_funcall(err, rb_intern("class"), - &ruby_error, 0), - rb_intern("name"), &ruby_error, 0)); + &ruby_error, 0, NULL), + rb_intern("name"), &ruby_error, 0, NULL)); if (strcmp (err_class, "SyntaxError") == 0) { @@ -222,122 +291,55 @@ weechat_ruby_print_exception (VALUE err) } /* - * weechat_ruby_exec: call a ruby command + * weechat_ruby_exec: execute a ruby function */ void * weechat_ruby_exec (struct t_plugin_script *script, - int ret_type, const char *function, char **argv) + int ret_type, const char *function, + const char *format, void **argv) { VALUE rc, err; - int ruby_error, *ret_i; + int ruby_error, i, argc, *ret_i; + VALUE argv2[16]; void *ret_value; struct t_plugin_script *old_ruby_current_script; - + old_ruby_current_script = ruby_current_script; ruby_current_script = script; - if (argv && argv[0]) + argc = 0; + if (format && format[0]) { - if (argv[1]) + argc = strlen (format); + for (i = 0; i < argc; i++) { - if (argv[2]) - { - if (argv[3]) - { - if (argv[4]) - { - if (argv[5]) - { - if (argv[6]) - { - if (argv[7]) - { - rc = rb_protect_funcall ((VALUE) script->interpreter, rb_intern(function), - &ruby_error, 8, - rb_str_new2(argv[0]), - rb_str_new2(argv[1]), - rb_str_new2(argv[2]), - rb_str_new2(argv[3]), - rb_str_new2(argv[4]), - rb_str_new2(argv[5]), - rb_str_new2(argv[6]), - rb_str_new2(argv[7])); - } - else - { - rc = rb_protect_funcall ((VALUE) script->interpreter, rb_intern(function), - &ruby_error, 7, - rb_str_new2(argv[0]), - rb_str_new2(argv[1]), - rb_str_new2(argv[2]), - rb_str_new2(argv[3]), - rb_str_new2(argv[4]), - rb_str_new2(argv[5]), - rb_str_new2(argv[6])); - } - } - else - { - rc = rb_protect_funcall ((VALUE) script->interpreter, rb_intern(function), - &ruby_error, 6, - rb_str_new2(argv[0]), - rb_str_new2(argv[1]), - rb_str_new2(argv[2]), - rb_str_new2(argv[3]), - rb_str_new2(argv[4]), - rb_str_new2(argv[5])); - } - } - else - { - rc = rb_protect_funcall ((VALUE) script->interpreter, rb_intern(function), - &ruby_error, 5, - rb_str_new2(argv[0]), - rb_str_new2(argv[1]), - rb_str_new2(argv[2]), - rb_str_new2(argv[3]), - rb_str_new2(argv[4])); - } - } - else - { - rc = rb_protect_funcall ((VALUE) script->interpreter, rb_intern(function), - &ruby_error, 4, - rb_str_new2(argv[0]), - rb_str_new2(argv[1]), - rb_str_new2(argv[2]), - rb_str_new2(argv[3])); - } - } - else - { - rc = rb_protect_funcall ((VALUE) script->interpreter, rb_intern(function), - &ruby_error, 3, - rb_str_new2(argv[0]), - rb_str_new2(argv[1]), - rb_str_new2(argv[2])); - } - } - else + switch (format[i]) { - rc = rb_protect_funcall ((VALUE) script->interpreter, rb_intern(function), - &ruby_error, 2, - rb_str_new2(argv[0]), - rb_str_new2(argv[1])); + case 's': /* string */ + argv2[i] = rb_str_new2 ((char *)argv[i]); + break; + case 'i': /* integer */ + argv2[i] = INT2FIX (*((int *)argv[i])); + break; + case 'h': /* hash */ + argv2[i] = (VALUE)argv[i]; + break; } } - else - { - rc = rb_protect_funcall ((VALUE) script->interpreter, rb_intern(function), - &ruby_error, 1, - rb_str_new2(argv[0])); - } + } + + if (argc > 0) + { + rc = rb_protect_funcall ((VALUE) script->interpreter, + rb_intern(function), + &ruby_error, argc, argv2); } else { - rc = rb_protect_funcall ((VALUE) script->interpreter, rb_intern(function), - &ruby_error, 0); + rc = rb_protect_funcall ((VALUE) script->interpreter, + rb_intern(function), + &ruby_error, 0, NULL); } if (ruby_error) @@ -366,6 +368,11 @@ weechat_ruby_exec (struct t_plugin_script *script, *ret_i = NUM2INT(rc); ret_value = ret_i; } + else if (ret_type == WEECHAT_SCRIPT_EXEC_HASHTABLE) + { + ret_value = weechat_ruby_hash_to_hashtable (rc, + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE); + } else { weechat_printf (NULL, @@ -451,7 +458,6 @@ weechat_ruby_output_flush (VALUE self) return Qnil; } - /* * weechat_ruby_load: load a Ruby script */ @@ -460,7 +466,7 @@ int weechat_ruby_load (const char *filename) { char modname[64]; - VALUE curModule, ruby_retcode, err; + VALUE curModule, ruby_retcode, err, argv[1]; int ruby_error; struct stat buf; @@ -488,9 +494,10 @@ weechat_ruby_load (const char *filename) curModule = rb_define_module(modname); ruby_current_script_filename = filename; - + + argv[0] = rb_str_new2 (filename); ruby_retcode = rb_protect_funcall (curModule, rb_intern("load_eval_file"), - &ruby_error, 1, rb_str_new2(filename)); + &ruby_error, 1, argv); if (ruby_retcode == Qnil) { @@ -536,7 +543,7 @@ weechat_ruby_load (const char *filename) } ruby_retcode = rb_protect_funcall (curModule, rb_intern("weechat_init"), - &ruby_error, 0); + &ruby_error, 0, NULL); if (ruby_error) { @@ -595,7 +602,6 @@ void weechat_ruby_unload (struct t_plugin_script *script) { int *r; - char *ruby_argv[1] = { NULL }; void *interpreter; if ((weechat_ruby_plugin->debug >= 1) || !ruby_quiet) @@ -610,7 +616,7 @@ weechat_ruby_unload (struct t_plugin_script *script) r = (int *) weechat_ruby_exec (script, WEECHAT_SCRIPT_EXEC_INT, script->shutdown_func, - ruby_argv); + 0, NULL); if (r) free (r); } diff --git a/src/plugins/scripts/ruby/weechat-ruby.h b/src/plugins/scripts/ruby/weechat-ruby.h index 2ef5cbbf4..49ab461be 100644 --- a/src/plugins/scripts/ruby/weechat-ruby.h +++ b/src/plugins/scripts/ruby/weechat-ruby.h @@ -35,8 +35,11 @@ extern struct t_plugin_script *ruby_current_script; extern struct t_plugin_script *ruby_registered_script; extern const char *ruby_current_script_filename; -extern void *weechat_ruby_exec (struct t_plugin_script *script, - int ret_type, const char *function, - char **argv); +extern VALUE weechat_ruby_hashtable_to_hash (struct t_hashtable *hashtable); +extern struct t_hashtable *weechat_ruby_hash_to_hashtable (VALUE dict, + int hashtable_size); +void *weechat_ruby_exec (struct t_plugin_script *script, + int ret_type, const char *function, + const char *format, void **argv); #endif /* __WEECHAT_RUBY_H */ diff --git a/src/plugins/scripts/script-api.c b/src/plugins/scripts/script-api.c index 04b8b5951..1a56807d7 100644 --- a/src/plugins/scripts/script-api.c +++ b/src/plugins/scripts/script-api.c @@ -1203,6 +1203,50 @@ script_api_hook_info (struct t_weechat_plugin *weechat_plugin, } /* + * script_api_hook_info_hashtable: hook an info_hashtable + * return new hook, NULL if error + */ + +struct t_hook * +script_api_hook_info_hashtable (struct t_weechat_plugin *weechat_plugin, + struct t_plugin_script *script, + const char *info_name, + const char *description, + const char *args_description, + const char *output_description, + struct t_hashtable *(*callback)(void *data, + const char *info_name, + struct t_hashtable *hashtable), + const char *function, + const char *data) +{ + struct t_script_callback *new_script_callback; + struct t_hook *new_hook; + + new_script_callback = script_callback_alloc (); + if (!new_script_callback) + return NULL; + + new_hook = weechat_hook_info_hashtable (info_name, description, + args_description, + output_description, + callback, new_script_callback); + if (!new_hook) + { + script_callback_free_data (new_script_callback); + free (new_script_callback); + return NULL; + } + + script_callback_init (new_script_callback, script, function, data); + new_script_callback->hook = new_hook; + + script_callback_add (script, new_script_callback); + + return new_hook; +} + +/* * script_api_hook_infolist: hook an infolist * return new hook, NULL if error */ diff --git a/src/plugins/scripts/script-api.h b/src/plugins/scripts/script-api.h index 94be78410..f7d8b312f 100644 --- a/src/plugins/scripts/script-api.h +++ b/src/plugins/scripts/script-api.h @@ -243,6 +243,17 @@ extern struct t_hook *script_api_hook_info (struct t_weechat_plugin *weechat_plu const char *arguments), const char *function, const char *data); +extern struct t_hook *script_api_hook_info_hashtable (struct t_weechat_plugin *weechat_plugin, + struct t_plugin_script *script, + const char *info_name, + const char *description, + const char *args_description, + const char *output_description, + struct t_hashtable *(*callback)(void *data, + const char *info_name, + struct t_hashtable *hashtable), + const char *function, + const char *data); extern struct t_hook *script_api_hook_infolist (struct t_weechat_plugin *weechat_plugin, struct t_plugin_script *script, const char *infolist_name, diff --git a/src/plugins/scripts/script.h b/src/plugins/scripts/script.h index 767259d9c..9b8bfb1ea 100644 --- a/src/plugins/scripts/script.h +++ b/src/plugins/scripts/script.h @@ -21,8 +21,15 @@ #define __WEECHAT_SCRIPT_H 1 /* constants which defines return types for weechat_<lang>_exec functions */ -#define WEECHAT_SCRIPT_EXEC_INT 1 -#define WEECHAT_SCRIPT_EXEC_STRING 2 + +enum t_weechat_script_exec_type +{ + WEECHAT_SCRIPT_EXEC_INT = 0, + WEECHAT_SCRIPT_EXEC_STRING, + WEECHAT_SCRIPT_EXEC_HASHTABLE, +}; + +#define WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE 16 #define WEECHAT_SCRIPT_MSG_NOT_INIT(__current_script, \ __function) \ diff --git a/src/plugins/scripts/tcl/weechat-tcl-api.c b/src/plugins/scripts/tcl/weechat-tcl-api.c index 0688652a9..538ce29ec 100644 --- a/src/plugins/scripts/tcl/weechat-tcl-api.c +++ b/src/plugins/scripts/tcl/weechat-tcl-api.c @@ -156,6 +156,11 @@ Tcl_SetIntObj (objp, __int); \ return TCL_OK; \ } +#define TCL_RETURN_OBJ(__obj) \ + { \ + Tcl_SetObjResult (interp, __obj); \ + return TCL_OK; \ + } /* @@ -1229,7 +1234,8 @@ weechat_tcl_api_config_reload_cb (void *data, struct t_config_file *config_file) { struct t_script_callback *script_callback; - char *tcl_argv[3], empty_arg[1] = { '\0' }; + void *tcl_argv[2]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1239,12 +1245,11 @@ weechat_tcl_api_config_reload_cb (void *data, { tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = script_ptr2str (config_file); - tcl_argv[2] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, - WEECHAT_SCRIPT_EXEC_INT, - script_callback->function, - tcl_argv); + WEECHAT_SCRIPT_EXEC_INT, + script_callback->function, + "ss", tcl_argv); if (!rc) ret = WEECHAT_CONFIG_READ_FILE_NOT_FOUND; @@ -1315,7 +1320,8 @@ weechat_tcl_api_config_section_read_cb (void *data, const char *option_name, const char *value) { struct t_script_callback *script_callback; - char *tcl_argv[6], empty_arg[1] = { '\0' }; + void *tcl_argv[5]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1327,12 +1333,11 @@ weechat_tcl_api_config_section_read_cb (void *data, tcl_argv[2] = script_ptr2str (section); tcl_argv[3] = (option_name) ? (char *)option_name : empty_arg; tcl_argv[4] = (value) ? (char *)value : empty_arg; - tcl_argv[5] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, - WEECHAT_SCRIPT_EXEC_INT, - script_callback->function, - tcl_argv); + WEECHAT_SCRIPT_EXEC_INT, + script_callback->function, + "sssss", tcl_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_SET_ERROR; @@ -1362,7 +1367,8 @@ weechat_tcl_api_config_section_write_cb (void *data, const char *section_name) { struct t_script_callback *script_callback; - char *tcl_argv[4], empty_arg[1] = { '\0' }; + void *tcl_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1372,12 +1378,11 @@ weechat_tcl_api_config_section_write_cb (void *data, tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = script_ptr2str (config_file); tcl_argv[2] = (section_name) ? (char *)section_name : empty_arg; - tcl_argv[3] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "sss", tcl_argv); if (!rc) ret = WEECHAT_CONFIG_WRITE_ERROR; @@ -1406,7 +1411,8 @@ weechat_tcl_api_config_section_write_default_cb (void *data, const char *section_name) { struct t_script_callback *script_callback; - char *tcl_argv[4], empty_arg[1] = { '\0' }; + void *tcl_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1416,12 +1422,11 @@ weechat_tcl_api_config_section_write_default_cb (void *data, tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = script_ptr2str (config_file); tcl_argv[2] = (section_name) ? (char *)section_name : empty_arg; - tcl_argv[3] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "sss", tcl_argv); if (!rc) ret = WEECHAT_CONFIG_WRITE_ERROR; @@ -1452,7 +1457,8 @@ weechat_tcl_api_config_section_create_option_cb (void *data, const char *value) { struct t_script_callback *script_callback; - char *tcl_argv[6], empty_arg[1] = { '\0' }; + void *tcl_argv[5]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1464,12 +1470,11 @@ weechat_tcl_api_config_section_create_option_cb (void *data, tcl_argv[2] = script_ptr2str (section); tcl_argv[3] = (option_name) ? (char *)option_name : empty_arg; tcl_argv[4] = (value) ? (char *)value : empty_arg; - tcl_argv[5] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "sssss", tcl_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_SET_ERROR; @@ -1501,7 +1506,8 @@ weechat_tcl_api_config_section_delete_option_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *tcl_argv[5], empty_arg[1] = { '\0' }; + void *tcl_argv[4]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1512,12 +1518,11 @@ weechat_tcl_api_config_section_delete_option_cb (void *data, tcl_argv[1] = script_ptr2str (config_file); tcl_argv[2] = script_ptr2str (section); tcl_argv[3] = script_ptr2str (option); - tcl_argv[4] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "ssss", tcl_argv); if (!rc) ret = WEECHAT_CONFIG_OPTION_UNSET_ERROR; @@ -1663,7 +1668,8 @@ weechat_tcl_api_config_option_check_value_cb (void *data, const char *value) { struct t_script_callback *script_callback; - char *tcl_argv[4], empty_arg[1] = { '\0' }; + void *tcl_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -1673,12 +1679,11 @@ weechat_tcl_api_config_option_check_value_cb (void *data, tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = script_ptr2str (option); tcl_argv[2] = (value) ? (char *)value : empty_arg; - tcl_argv[3] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "sss", tcl_argv); if (!rc) ret = 0; @@ -1705,7 +1710,8 @@ weechat_tcl_api_config_option_change_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *tcl_argv[3], empty_arg[1] = { '\0' }; + void *tcl_argv[2]; + char empty_arg[1] = { '\0' }; int *rc; script_callback = (struct t_script_callback *)data; @@ -1714,12 +1720,11 @@ weechat_tcl_api_config_option_change_cb (void *data, { tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = script_ptr2str (option); - tcl_argv[2] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "ss", tcl_argv); if (tcl_argv[1]) free (tcl_argv[1]); @@ -1738,7 +1743,8 @@ weechat_tcl_api_config_option_delete_cb (void *data, struct t_config_option *option) { struct t_script_callback *script_callback; - char *tcl_argv[3], empty_arg[1] = { '\0' }; + void *tcl_argv[2]; + char empty_arg[1] = { '\0' }; int *rc; script_callback = (struct t_script_callback *)data; @@ -1747,12 +1753,11 @@ weechat_tcl_api_config_option_delete_cb (void *data, { tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = script_ptr2str (option); - tcl_argv[2] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "ss", tcl_argv); if (tcl_argv[1]) free (tcl_argv[1]); @@ -3141,7 +3146,8 @@ weechat_tcl_api_hook_command_cb (void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) { struct t_script_callback *script_callback; - char *tcl_argv[4], empty_arg[1] = { '\0' }; + void *tcl_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; /* make C compiler happy */ @@ -3154,12 +3160,11 @@ weechat_tcl_api_hook_command_cb (void *data, struct t_gui_buffer *buffer, tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = script_ptr2str (buffer); tcl_argv[2] = (argc > 1) ? argv_eol[1] : empty_arg; - tcl_argv[3] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "sss", tcl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3236,7 +3241,8 @@ weechat_tcl_api_hook_command_run_cb (void *data, struct t_gui_buffer *buffer, const char *command) { struct t_script_callback *script_callback; - char *tcl_argv[4], empty_arg[1] = { '\0' }; + void *tcl_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3246,12 +3252,11 @@ weechat_tcl_api_hook_command_run_cb (void *data, struct t_gui_buffer *buffer, tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = script_ptr2str (buffer); tcl_argv[2] = (command) ? (char *)command : empty_arg; - tcl_argv[3] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "sss", tcl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3318,7 +3323,8 @@ int weechat_tcl_api_hook_timer_cb (void *data, int remaining_calls) { struct t_script_callback *script_callback; - char *tcl_argv[3], str_remaining_calls[32], empty_arg[1] = { '\0' }; + void *tcl_argv[2]; + char str_remaining_calls[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3330,12 +3336,11 @@ weechat_tcl_api_hook_timer_cb (void *data, int remaining_calls) tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = str_remaining_calls; - tcl_argv[2] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "ss", tcl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3407,7 +3412,8 @@ int weechat_tcl_api_hook_fd_cb (void *data, int fd) { struct t_script_callback *script_callback; - char *tcl_argv[3], str_fd[32], empty_arg[1] = { '\0' }; + void *tcl_argv[2]; + char str_fd[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3418,12 +3424,11 @@ weechat_tcl_api_hook_fd_cb (void *data, int fd) tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = str_fd; - tcl_argv[2] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "ss", tcl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3498,7 +3503,8 @@ weechat_tcl_api_hook_process_cb (void *data, const char *out, const char *err) { struct t_script_callback *script_callback; - char *tcl_argv[6], str_rc[32], empty_arg[1] = { '\0' }; + void *tcl_argv[5]; + char str_rc[32], empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3512,12 +3518,11 @@ weechat_tcl_api_hook_process_cb (void *data, tcl_argv[2] = str_rc; tcl_argv[3] = (out) ? (char *)out : empty_arg; tcl_argv[4] = (err) ? (char *)err : empty_arg; - tcl_argv[5] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "sssss", tcl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3590,7 +3595,8 @@ weechat_tcl_api_hook_connect_cb (void *data, int status, int gnutls_rc, const char *error, const char *ip_address) { struct t_script_callback *script_callback; - char *tcl_argv[6], str_status[32], str_gnutls_rc[32]; + void *tcl_argv[5]; + char str_status[32], str_gnutls_rc[32]; char empty_arg[1] = { '\0' }; int *rc, ret; @@ -3606,12 +3612,11 @@ weechat_tcl_api_hook_connect_cb (void *data, int status, int gnutls_rc, tcl_argv[2] = str_gnutls_rc; tcl_argv[3] = (ip_address) ? (char *)ip_address : empty_arg; tcl_argv[4] = (error) ? (char *)error : empty_arg; - tcl_argv[5] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "sssss", tcl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3698,7 +3703,8 @@ weechat_tcl_api_hook_print_cb (void *data, struct t_gui_buffer *buffer, const char *prefix, const char *message) { struct t_script_callback *script_callback; - char *tcl_argv[9], empty_arg[1] = { '\0' }; + void *tcl_argv[8]; + char empty_arg[1] = { '\0' }; static char timebuffer[64]; int *rc, ret; @@ -3721,12 +3727,11 @@ weechat_tcl_api_hook_print_cb (void *data, struct t_gui_buffer *buffer, tcl_argv[5] = (highlight) ? strdup ("1") : strdup ("0"); tcl_argv[6] = (prefix) ? (char *)prefix : empty_arg; tcl_argv[7] = (message) ? (char *)message : empty_arg; - tcl_argv[8] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "ssssssss", tcl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3811,7 +3816,8 @@ weechat_tcl_api_hook_signal_cb (void *data, const char *signal, const char *type void *signal_data) { struct t_script_callback *script_callback; - char *tcl_argv[4], empty_arg[1] = { '\0' }; + void *tcl_argv[3]; + char empty_arg[1] = { '\0' }; static char value_str[64]; int *rc, ret, free_needed; @@ -3839,12 +3845,11 @@ weechat_tcl_api_hook_signal_cb (void *data, const char *signal, const char *type } else tcl_argv[2] = empty_arg; - tcl_argv[3] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "sss", tcl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -3970,7 +3975,8 @@ int weechat_tcl_api_hook_config_cb (void *data, const char *option, const char *value) { struct t_script_callback *script_callback; - char *tcl_argv[4], empty_arg[1] = { '\0' }; + void *tcl_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -3980,12 +3986,11 @@ weechat_tcl_api_hook_config_cb (void *data, const char *option, const char *valu tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = (option) ? (char *)option : empty_arg; tcl_argv[2] = (value) ? (char *)value : empty_arg; - tcl_argv[3] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "sss", tcl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -4052,7 +4057,8 @@ weechat_tcl_api_hook_completion_cb (void *data, const char *completion_item, struct t_gui_completion *completion) { struct t_script_callback *script_callback; - char *tcl_argv[5], empty_arg[1] = { '\0' }; + void *tcl_argv[4]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4063,12 +4069,11 @@ weechat_tcl_api_hook_completion_cb (void *data, const char *completion_item, tcl_argv[1] = (completion_item) ? (char *)completion_item : empty_arg; tcl_argv[2] = script_ptr2str (buffer); tcl_argv[3] = script_ptr2str (completion); - tcl_argv[4] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "ssss", tcl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -4185,7 +4190,8 @@ weechat_tcl_api_hook_modifier_cb (void *data, const char *modifier, const char *modifier_data, const char *string) { struct t_script_callback *script_callback; - char *tcl_argv[5], empty_arg[1] = { '\0' }; + void *tcl_argv[4]; + char empty_arg[1] = { '\0' }; script_callback = (struct t_script_callback *)data; @@ -4195,12 +4201,11 @@ weechat_tcl_api_hook_modifier_cb (void *data, const char *modifier, tcl_argv[1] = (modifier) ? (char *)modifier : empty_arg; tcl_argv[2] = (modifier_data) ? (char *)modifier_data : empty_arg; tcl_argv[3] = (string) ? (char *)string : empty_arg; - tcl_argv[4] = NULL; return (char *)weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - tcl_argv); + "ssss", tcl_argv); } return NULL; @@ -4292,7 +4297,8 @@ weechat_tcl_api_hook_info_cb (void *data, const char *info_name, const char *arguments) { struct t_script_callback *script_callback; - char *tcl_argv[4], empty_arg[1] = { '\0' }; + void *tcl_argv[3]; + char empty_arg[1] = { '\0' }; script_callback = (struct t_script_callback *)data; @@ -4301,12 +4307,11 @@ weechat_tcl_api_hook_info_cb (void *data, const char *info_name, tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = (info_name) ? (char *)info_name : empty_arg; tcl_argv[2] = (arguments) ? (char *)arguments : empty_arg; - tcl_argv[3] = NULL; return (const char *)weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - tcl_argv); + "sss", tcl_argv); } return NULL; @@ -4358,6 +4363,83 @@ weechat_tcl_api_hook_info (ClientData clientData, Tcl_Interp *interp, } /* + * weechat_tcl_api_hook_info_hashtable_cb: callback for info_hashtable hooked + */ + +struct t_hashtable * +weechat_tcl_api_hook_info_hashtable_cb (void *data, const char *info_name, + struct t_hashtable *hashtable) +{ + struct t_script_callback *script_callback; + void *tcl_argv[3]; + char empty_arg[1] = { '\0' }; + + script_callback = (struct t_script_callback *)data; + + if (script_callback && script_callback->function && script_callback->function[0]) + { + tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; + tcl_argv[1] = (info_name) ? (char *)info_name : empty_arg; + tcl_argv[2] = hashtable; + + return (struct t_hashtable *)weechat_tcl_exec (script_callback->script, + WEECHAT_SCRIPT_EXEC_HASHTABLE, + script_callback->function, + "ssh", tcl_argv); + } + + return NULL; +} + +/* + * weechat_tcl_api_hook_info_hashtable: hook an info_hashtable + */ + +static int +weechat_tcl_api_hook_info_hashtable (ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + Tcl_Obj *objp; + char *result, *info_name, *description, *args_description; + char *output_description, *function, *data; + int i; + + /* make C compiler happy */ + (void) clientData; + + if (!tcl_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INIT(TCL_CURRENT_SCRIPT_NAME, "hook_info_hashtable"); + TCL_RETURN_EMPTY; + } + + if (objc < 7) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGS(TCL_CURRENT_SCRIPT_NAME, "hook_info_hashtable"); + TCL_RETURN_EMPTY; + } + + info_name = Tcl_GetStringFromObj (objv[1], &i); + description = Tcl_GetStringFromObj (objv[2], &i); + args_description = Tcl_GetStringFromObj (objv[3], &i); + output_description = Tcl_GetStringFromObj (objv[4], &i); + function = Tcl_GetStringFromObj (objv[5], &i); + data = Tcl_GetStringFromObj (objv[6], &i); + + result = script_ptr2str (script_api_hook_info_hashtable (weechat_tcl_plugin, + tcl_current_script, + info_name, + description, + args_description, + output_description, + &weechat_tcl_api_hook_info_hashtable_cb, + function, + data)); + + TCL_RETURN_STRING_FREE(result); +} + +/* * weechat_tcl_api_hook_infolist_cb: callback for infolist hooked */ @@ -4366,7 +4448,8 @@ weechat_tcl_api_hook_infolist_cb (void *data, const char *infolist_name, void *pointer, const char *arguments) { struct t_script_callback *script_callback; - char *tcl_argv[5], empty_arg[1] = { '\0' }; + void *tcl_argv[4]; + char empty_arg[1] = { '\0' }; struct t_infolist *result; script_callback = (struct t_script_callback *)data; @@ -4377,12 +4460,11 @@ weechat_tcl_api_hook_infolist_cb (void *data, const char *infolist_name, tcl_argv[1] = (infolist_name) ? (char *)infolist_name : empty_arg; tcl_argv[2] = script_ptr2str (pointer); tcl_argv[3] = (arguments) ? (char *)arguments : empty_arg; - tcl_argv[4] = NULL; result = (struct t_infolist *)weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - tcl_argv); + "ssss", tcl_argv); if (tcl_argv[2]) free (tcl_argv[2]); @@ -4509,7 +4591,8 @@ weechat_tcl_api_buffer_input_data_cb (void *data, struct t_gui_buffer *buffer, const char *input_data) { struct t_script_callback *script_callback; - char *tcl_argv[4], empty_arg[1] = { '\0' }; + void *tcl_argv[3]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4519,12 +4602,11 @@ weechat_tcl_api_buffer_input_data_cb (void *data, struct t_gui_buffer *buffer, tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = script_ptr2str (buffer); tcl_argv[2] = (input_data) ? (char *)input_data : empty_arg; - tcl_argv[3] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "sss", tcl_argv); if (!rc) ret = WEECHAT_RC_ERROR; else @@ -4549,7 +4631,8 @@ int weechat_tcl_api_buffer_close_cb (void *data, struct t_gui_buffer *buffer) { struct t_script_callback *script_callback; - char *tcl_argv[3], empty_arg[1] = { '\0' }; + void *tcl_argv[2]; + char empty_arg[1] = { '\0' }; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -4558,12 +4641,11 @@ weechat_tcl_api_buffer_close_cb (void *data, struct t_gui_buffer *buffer) { tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = script_ptr2str (buffer); - tcl_argv[2] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, script_callback->function, - tcl_argv); + "ss", tcl_argv); if (!rc) ret = WEECHAT_RC_ERROR; else @@ -5518,7 +5600,8 @@ weechat_tcl_api_bar_item_build_cb (void *data, struct t_gui_bar_item *item, struct t_gui_window *window) { struct t_script_callback *script_callback; - char *tcl_argv[4], empty_arg[1] = { '\0' }, *ret; + void *tcl_argv[3]; + char empty_arg[1] = { '\0' }, *ret; script_callback = (struct t_script_callback *)data; @@ -5527,12 +5610,11 @@ weechat_tcl_api_bar_item_build_cb (void *data, struct t_gui_bar_item *item, tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg; tcl_argv[1] = script_ptr2str (item); tcl_argv[2] = script_ptr2str (window); - tcl_argv[3] = NULL; ret = (char *)weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_STRING, script_callback->function, - tcl_argv); + "sss", tcl_argv); if (tcl_argv[1]) free (tcl_argv[1]); @@ -5883,7 +5965,7 @@ weechat_tcl_api_command (ClientData clientData, Tcl_Interp *interp, } /* - * weechat_tcl_api_info_get: get info about WeeChat + * weechat_tcl_api_info_get: get info (as string) */ static int @@ -5916,6 +5998,48 @@ weechat_tcl_api_info_get (ClientData clientData, Tcl_Interp *interp, } /* + * weechat_tcl_api_info_get_hashtable: get info (as hashtable) + */ + +static int +weechat_tcl_api_info_get_hashtable (ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + Tcl_Obj *objp, *result_dict; + struct t_hashtable *hashtable, *result_hashtable; + int i; + + /* make C compiler happy */ + (void) clientData; + + if (!tcl_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INIT(TCL_CURRENT_SCRIPT_NAME, "info_get_hashtable"); + TCL_RETURN_EMPTY; + } + + if (objc < 3) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGS(TCL_CURRENT_SCRIPT_NAME, "info_get_hashtable"); + TCL_RETURN_EMPTY; + } + + hashtable = weechat_tcl_dict_to_hashtable (interp, objv[2], + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE); + + result_hashtable = weechat_info_get_hashtable (Tcl_GetStringFromObj (objv[1], &i), + hashtable); + result_dict = weechat_tcl_hashtable_to_dict (interp, result_hashtable); + + if (hashtable) + weechat_hashtable_free (hashtable); + if (result_hashtable) + weechat_hashtable_free (result_hashtable); + + TCL_RETURN_OBJ(result_dict); +} + +/* * weechat_tcl_api_infolist_new: create a new infolist */ @@ -6529,7 +6653,8 @@ weechat_tcl_api_upgrade_read_cb (void *data, struct t_infolist *infolist) { struct t_script_callback *script_callback; - char *tcl_argv[5], empty_arg[1] = { '\0' }, str_object_id[32]; + void *tcl_argv[4]; + char empty_arg[1] = { '\0' }, str_object_id[32]; int *rc, ret; script_callback = (struct t_script_callback *)data; @@ -6542,12 +6667,11 @@ weechat_tcl_api_upgrade_read_cb (void *data, tcl_argv[1] = script_ptr2str (upgrade_file); tcl_argv[2] = str_object_id; tcl_argv[3] = script_ptr2str (infolist); - tcl_argv[4] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, - WEECHAT_SCRIPT_EXEC_INT, - script_callback->function, - tcl_argv); + WEECHAT_SCRIPT_EXEC_INT, + script_callback->function, + "ssss", tcl_argv); if (!rc) ret = WEECHAT_RC_ERROR; @@ -6917,6 +7041,8 @@ void weechat_tcl_api_init (Tcl_Interp *interp) weechat_tcl_api_hook_modifier_exec, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand (interp, "weechat::hook_info", weechat_tcl_api_hook_info, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); + Tcl_CreateObjCommand (interp, "weechat::hook_info_hashtable", + weechat_tcl_api_hook_info_hashtable, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand (interp, "weechat::hook_infolist", weechat_tcl_api_hook_infolist, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand (interp, "weechat::unhook", @@ -6995,6 +7121,8 @@ void weechat_tcl_api_init (Tcl_Interp *interp) weechat_tcl_api_command, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand (interp, "weechat::info_get", weechat_tcl_api_info_get, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); + Tcl_CreateObjCommand (interp, "weechat::info_get_hashtable", + weechat_tcl_api_info_get_hashtable, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand (interp, "weechat::infolist_new", weechat_tcl_api_infolist_new, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); Tcl_CreateObjCommand (interp, "weechat::infolist_new_item", diff --git a/src/plugins/scripts/tcl/weechat-tcl.c b/src/plugins/scripts/tcl/weechat-tcl.c index f874c83b5..540e6391b 100644 --- a/src/plugins/scripts/tcl/weechat-tcl.c +++ b/src/plugins/scripts/tcl/weechat-tcl.c @@ -72,14 +72,106 @@ Tcl_Interp* cinterp; /* - * weechat_tcl_exec: execute a Tcl script + * weechat_tcl_hashtable_map_cb: callback called for each key/value in a + * hashtable + */ + +void +weechat_tcl_hashtable_map_cb (void *data, + struct t_hashtable *hashtable, + const void *key, + const void *value) +{ + void **data_array; + Tcl_Interp *interp; + Tcl_Obj *dict; + + /* make C compiler happy */ + (void) hashtable; + + data_array = (void **)data; + interp = data_array[0]; + dict = data_array[1]; + + Tcl_DictObjPut (interp, dict, + Tcl_NewStringObj ((char *)key, -1), + Tcl_NewStringObj ((char *)value, -1)); +} + +/* + * weechat_tcl_hashtable_to_dict: get tcl dict with a WeeChat hashtable + */ + +Tcl_Obj * +weechat_tcl_hashtable_to_dict (Tcl_Interp *interp, + struct t_hashtable *hashtable) +{ + Tcl_Obj *dict; + void *data[2]; + + dict = Tcl_NewDictObj (); + if (!dict) + return NULL; + + data[0] = interp; + data[1] = dict; + + weechat_hashtable_map (hashtable, + &weechat_tcl_hashtable_map_cb, + data); + + return dict; +} + +/* + * weechat_tcl_dict_to_hashtable: get WeeChat hashtable with tcl dict + * Hashtable returned has type string for + * both keys and values + * Note: hashtable has to be released after + * use with call to weechat_hashtable_free() + */ + +struct t_hashtable * +weechat_tcl_dict_to_hashtable (Tcl_Interp *interp, Tcl_Obj *dict, + int hashtable_size) +{ + struct t_hashtable *hashtable; + Tcl_DictSearch search; + Tcl_Obj *key, *value; + int done; + + hashtable = weechat_hashtable_new (hashtable_size, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); + if (!hashtable) + return NULL; + + if (Tcl_DictObjFirst (interp, dict, &search, &key, &value, &done) == TCL_OK) + { + for (; !done ; Tcl_DictObjNext(&search, &key, &value, &done)) + { + weechat_hashtable_set (hashtable, + (void *)Tcl_GetString (key), + (void *)Tcl_GetString (value)); + } + } + Tcl_DictObjDone(&search); + + return hashtable; +} + +/* + * weechat_tcl_exec: execute a tcl function */ void * weechat_tcl_exec (struct t_plugin_script *script, - int ret_type, const char *function, char **argv) + int ret_type, const char *function, + const char *format, void **argv) { - int i, llength; + int argc, i, llength; int *ret_i; char *ret_cv; void *ret_val; @@ -90,12 +182,12 @@ weechat_tcl_exec (struct t_plugin_script *script, old_tcl_script = tcl_current_script; tcl_current_script = script; interp = (Tcl_Interp*)script->interpreter; - + if (function && function[0]) { - cmdlist = Tcl_NewListObj(0,NULL); - Tcl_IncrRefCount(cmdlist); /* +1 */ - Tcl_ListObjAppendElement(interp,cmdlist,Tcl_NewStringObj(function,-1)); + cmdlist = Tcl_NewListObj (0, NULL); + Tcl_IncrRefCount (cmdlist); /* +1 */ + Tcl_ListObjAppendElement (interp, cmdlist, Tcl_NewStringObj (function,-1)); } else { @@ -103,20 +195,35 @@ weechat_tcl_exec (struct t_plugin_script *script, return NULL; } - if (argv) + if (format && format[0]) { - for (i = 0; argv[i]; i++) + argc = strlen (format); + for (i = 0; i < argc; i++) { - Tcl_ListObjAppendElement(interp,cmdlist,Tcl_NewStringObj(argv[i],-1)); + switch (format[i]) + { + case 's': /* string */ + Tcl_ListObjAppendElement (interp, cmdlist, + Tcl_NewStringObj (argv[i], -1)); + break; + case 'i': /* integer */ + Tcl_ListObjAppendElement (interp, cmdlist, + Tcl_NewStringObj (argv[i], -1)); + break; + case 'h': /* hash */ + Tcl_ListObjAppendElement (interp, cmdlist, + weechat_tcl_hashtable_to_dict (interp, argv[i])); + break; + } } } - - if (Tcl_ListObjLength(interp,cmdlist,&llength) != TCL_OK) + + if (Tcl_ListObjLength (interp, cmdlist, &llength) != TCL_OK) llength = 0; - + if (Tcl_EvalObjEx (interp, cmdlist, TCL_EVAL_DIRECT) == TCL_OK) { - Tcl_ListObjReplace(interp,cmdlist,0,llength,0,NULL); /* remove elements, decrement their ref count */ + Tcl_ListObjReplace (interp, cmdlist, 0, llength, 0, NULL); /* remove elements, decrement their ref count */ Tcl_DecrRefCount (cmdlist); /* -1 */ ret_val = NULL; if (ret_type == WEECHAT_SCRIPT_EXEC_STRING) @@ -135,6 +242,12 @@ weechat_tcl_exec (struct t_plugin_script *script, *ret_i = i; ret_val = (void *)ret_i; } + else if (ret_type == WEECHAT_SCRIPT_EXEC_HASHTABLE) + { + ret_val = weechat_tcl_dict_to_hashtable (interp, + Tcl_GetObjResult (interp), + WEECHAT_SCRIPT_HASHTABLE_DEFAULT_SIZE); + } tcl_current_script = old_tcl_script; if (ret_val) @@ -147,8 +260,8 @@ weechat_tcl_exec (struct t_plugin_script *script, return NULL; } - Tcl_ListObjReplace(interp,cmdlist,0,llength,0,NULL); /* remove elements, decrement their ref count */ - Tcl_DecrRefCount(cmdlist); /* -1 */ + Tcl_ListObjReplace (interp, cmdlist, 0, llength, 0, NULL); /* remove elements, decrement their ref count */ + Tcl_DecrRefCount (cmdlist); /* -1 */ weechat_printf (NULL, weechat_gettext ("%s%s: unable to run function \"%s\": %s"), weechat_prefix ("error"), TCL_PLUGIN_NAME, function, @@ -258,7 +371,7 @@ weechat_tcl_unload (struct t_plugin_script *script) pointer = weechat_tcl_exec (script, WEECHAT_SCRIPT_EXEC_INT, script->shutdown_func, - NULL); + NULL, NULL); if (pointer) free (pointer); } diff --git a/src/plugins/scripts/tcl/weechat-tcl.h b/src/plugins/scripts/tcl/weechat-tcl.h index 78972233e..d3a7fd312 100644 --- a/src/plugins/scripts/tcl/weechat-tcl.h +++ b/src/plugins/scripts/tcl/weechat-tcl.h @@ -35,8 +35,13 @@ extern struct t_plugin_script *tcl_current_script; extern struct t_plugin_script *tcl_registered_script; extern const char *tcl_current_script_filename; +extern Tcl_Obj *weechat_tcl_hashtable_to_dict (Tcl_Interp *interp, + struct t_hashtable *hashtable); +extern struct t_hashtable *weechat_tcl_dict_to_hashtable (Tcl_Interp *interp, + Tcl_Obj *dict, + int hashtable_size); extern void *weechat_tcl_exec (struct t_plugin_script *script, - int ret_type, const char *function, - char **argv); + int ret_type, const char *function, + const char *format, void **argv); #endif /* __WEECHAT_TCL_H */ diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h index 9765c31e4..abdea3f52 100644 --- a/src/plugins/weechat-plugin.h +++ b/src/plugins/weechat-plugin.h @@ -45,7 +45,7 @@ struct timeval; */ /* API version (used to check that plugin has same API and can be loaded) */ -#define WEECHAT_PLUGIN_API_VERSION "20100717-01" +#define WEECHAT_PLUGIN_API_VERSION "20100827-01" /* macros for defining plugin infos */ #define WEECHAT_PLUGIN_NAME(__name) \ @@ -273,6 +273,8 @@ struct t_weechat_plugin void *callback_map_data); int (*hashtable_get_integer) (struct t_hashtable *hashtable, const char *property); + const char *(*hashtable_get_string) (struct t_hashtable *hashtable, + const char *property); int (*hashtable_add_to_infolist) (struct t_hashtable *hashtable, struct t_infolist_item *infolist_item, const char *prefix); @@ -521,6 +523,15 @@ struct t_weechat_plugin const char *info_name, const char *arguments), void *callback_data); + struct t_hook *(*hook_info_hashtable) (struct t_weechat_plugin *plugin, + const char *info_name, + const char *description, + const char *args_description, + const char *output_description, + struct t_hashtable *(*callback)(void *data, + const char *info_name, + struct t_hashtable *hashtable), + void *callback_data); struct t_hook *(*hook_infolist) (struct t_weechat_plugin *plugin, const char *infolist_name, const char *description, @@ -643,6 +654,9 @@ struct t_weechat_plugin const char *(*info_get) (struct t_weechat_plugin *plugin, const char *info_name, const char *arguments); + struct t_hashtable *(*info_get_hashtable) (struct t_weechat_plugin *plugin, + const char *info_name, + struct t_hashtable *hashtable); /* infolists */ struct t_infolist *(*infolist_new) (); @@ -886,6 +900,8 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); weechat_plugin->hashtable_map(__hashtable, __cb_map, __cb_map_data) #define weechat_hashtable_get_integer(__hashtable, __property) \ weechat_plugin->hashtable_get_integer(__hashtable, __property) +#define weechat_hashtable_get_string(__hashtable, __property) \ + weechat_plugin->hashtable_get_string(__hashtable, __property) #define weechat_hashtable_add_to_infolist(__hashtable, __infolist_item, \ __prefix) \ weechat_plugin->hashtable_add_to_infolist(__hashtable, \ @@ -1117,6 +1133,16 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); weechat_plugin->hook_info(weechat_plugin, __info_name, \ __description, __args_description, \ __callback, __data) +#define weechat_hook_info_hashtable(__info_name, __description, \ + __args_description, \ + __output_description, \ + __callback, \ + __data) \ + weechat_plugin->hook_info_hashtable(weechat_plugin, __info_name, \ + __description, \ + __args_description, \ + __output_description, \ + __callback, __data) #define weechat_hook_infolist(__infolist_name, __description, \ __pointer_description, \ __args_description, __callback, __data) \ @@ -1243,6 +1269,9 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); /* infos */ #define weechat_info_get(__info_name, __arguments) \ weechat_plugin->info_get(weechat_plugin, __info_name, __arguments) +#define weechat_info_get_hashtable(__info_name, __hashtable) \ + weechat_plugin->info_get_hashtable(weechat_plugin, __info_name, \ + __hashtable) /* infolists */ #define weechat_infolist_new() \ |