# HG changeset patch # User Myhailo Danylenko # Date 1235354705 -7200 # Node ID 7d87d323c8893f9d2e2f2f96dc91e2740fbe383e # Parent 65cbecad22b4184bb0fc53734e6588f28bacc56c Fixes and improvement * style changed * documentation * various fixes * unregistering commands (see TODO) diff -r 65cbecad22b4 -r 7d87d323c889 CMakeLists.txt --- a/CMakeLists.txt Sun Feb 22 23:14:24 2009 +0200 +++ b/CMakeLists.txt Mon Feb 23 04:05:05 2009 +0200 @@ -4,7 +4,7 @@ ## User options option(DEBUG "Enable debugging output" ON) -option(MCABBER_INCLUDE_DIR "Path to mcabber include files" "/home/isbear/src/mcabber/hglm/mcabber/src") +set(MCABBER_INCLUDE_DIR "/home/isbear/src/mcabber/hglm/mcabber/src" CACHE FILEPATH "Path to mcabber headers") ## Define targets add_library(mcabber-lua MODULE main.c util.c) @@ -38,19 +38,20 @@ find_package(PkgConfig REQUIRED) pkg_check_modules(GLIB REQUIRED glib-2.0) pkg_check_modules(GMODULE REQUIRED gmodule-2.0) -#find_package(Perl) +pkg_check_modules(LM REQUIRED loudmouth-1.0) +find_package(Perl) ## Set up compiler configure_file(config.h.in config.h) -include_directories(SYSTEM ${LUA_INCLUDE_DIR} ${GLIB_INCLUDE_DIRS} ${GMODULE_INCLUDE_DIRS}) +include_directories(SYSTEM ${LUA_INCLUDE_DIR} ${GLIB_INCLUDE_DIRS} ${GMODULE_INCLUDE_DIRS} ${LM_INCLUDE_DIRS}) target_link_libraries(mcabber-lua ${LUA_LIBRARIES} ${GLIB_LIBRARIES} ${GMODULE_LIBRARIES}) include_directories(${mcabber-lua_SOURCE_DIR} ${mcabber-lua_BINARY_DIR} ${MCABBER_INCLUDE_DIR}) ## Extra targets -#if(PERL_FOUND) -# add_custom_command(OUTPUT ${lua-lm_BINARY_DIR}/loudmouth.html COMMAND ${PERL_EXECUTABLE} ${lua-lm_SOURCE_DIR}/docgen.pl ${lua-lm_SOURCES} > ${lua-lm_BINARY_DIR}/loudmouth.html DEPENDS ${lua-lm_SOURCE_DIR}/docgen.pl ${lua-lm_SOURCES} WORKING_DIRECTORY ${lua-lm_SOURCE_DIR}) -# add_custom_target(doc ALL DEPENDS ${lua-lm_BINARY_DIR}/loudmouth.html) -#endif() +if(PERL_FOUND) + add_custom_command(OUTPUT ${mcabber-lua_BINARY_DIR}/mcabber-lua.html COMMAND ${PERL_EXECUTABLE} ${mcabber-lua_SOURCE_DIR}/docgen.pl ${mcabber-lua_SOURCES} > ${mcabber-lua_BINARY_DIR}/mcabber-lua.html DEPENDS ${mcabber-lua_SOURCE_DIR}/docgen.pl ${mcabber-lua_SOURCES} WORKING_DIRECTORY ${mcabber-lua_SOURCE_DIR}) + add_custom_target(doc ALL DEPENDS ${mcabber-lua_BINARY_DIR}/mcabber-lua.html) +endif() #add_custom_target(test COMMAND env "LUA_PATH=${lua-lm_SOURCE_DIR}/?.lua;${LUA_PATH}" "LUA_CPATH=${lua-lm_SOURCE_DIR}/?.so;${lua-lm_BINARY_DIR}/?.so;${LUA_CPATH}" lua ${lua-lm_SOURCE_DIR}/test.lua DEPENDS loudmouth VERBATIM) #add_custom_target(test1 COMMAND env "LUA_PATH=${lua-lm_SOURCE_DIR}/?.lua;${LUA_PATH}" "LUA_CPATH=${lua-lm_SOURCE_DIR}/?.so;${lua-lm_BINARY_DIR}/?.so;${LUA_CPATH}" lua ${lua-lm_BINARY_DIR}/test.lua DEPENDS loudmouth VERBATIM) @@ -58,9 +59,9 @@ install(TARGETS mcabber-lua DESTINATION lib/mcabber) #install(FILES lm.lua DESTINATION share/lua/5.1) #install(FILES test.lua DESTINATION share/doc/${CPACK_PACKAGE_NAME}/examples) -#if(PERL_FOUND) -# install(FILES ${lua-lm_BINARY_DIR}/loudmouth.html DESTINATION share/doc/${CPACK_PACKAGE_NAME}) -#endif() +if(PERL_FOUND) + install(FILES ${mcabber-lua_BINARY_DIR}/mcabber-lua.html DESTINATION share/doc/${CPACK_PACKAGE_NAME}) +endif() install(FILES README DESTINATION share/doc/${CPACK_PACKAGE_NAME}) install(FILES TODO DESTINATION share/doc/${CPACK_PACKAGE_NAME}) install(FILES COPYING DESTINATION share/doc/${CPACK_PACKAGE_NAME}) diff -r 65cbecad22b4 -r 7d87d323c889 TODO --- a/TODO Sun Feb 22 23:14:24 2009 +0200 +++ b/TODO Mon Feb 23 04:05:05 2009 +0200 @@ -1,8 +1,8 @@ -improve global print to work on other types. or improve types :) +print should allow other types to be printed finish roster list information -implement dopath() thing instead of main.config_file() settings list? non-setting settings? -... +set package searching paths? +register commands inside of lua object too, then unregister them on exit diff -r 65cbecad22b4 -r 7d87d323c889 config.h.in --- a/config.h.in Sun Feb 22 23:14:24 2009 +0200 +++ b/config.h.in Mon Feb 23 04:05:05 2009 +0200 @@ -5,6 +5,9 @@ // define this to enable debugging output #cmakedefine DEBUG +// hack for mcabber headers +#define MODULES_ENABLE + #ifdef DEBUG # include diff -r 65cbecad22b4 -r 7d87d323c889 docgen.pl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docgen.pl Mon Feb 23 04:05:05 2009 +0200 @@ -0,0 +1,108 @@ +#! /usr/bin/perl + +use strict; +use warnings; + +my %docs; +my @tags; +my $inside; +my $harvest; +my @values; + +foreach my $file (@ARGV) { + if ( not open SOURCE, '<', $file ) { + print STDERR "Cannot open $file\n"; + next; + } + + my $chunk = 0; + + while () { + if ( $inside ) { + if ( not /^\/\/\// ) { + $inside = 0; + $chunk++; + } elsif ( /^\/\/\/ G:/ ) { + $inside = 0; + $harvest = 'V: ' . substr ( $_, 6 ); + } else { + push @{$docs{$file}[$chunk]}, substr ( $_, 4 ); + } + } elsif ( $harvest ) { + if ( /\{\s*NULL.*\}/ ) { + push @{$docs{$file}[$chunk]}, $harvest . ' ' . join ( ', ', @values ); + $harvest = undef; + @values = (); + $chunk++; + } elsif ( /\{\s*"(.+)".*\}/ ) { + push @values, $1; + } + } else { + next if not /^\/\/\//; + + $inside = 1; + my $tag = substr $_, 4; + chomp $tag; + push @{$docs{$file}[$chunk]}, $tag; + # hack to allow twoword objects be written in text with spaces + # now it matches "lm message" instead of "lm message node" -.- + # and even if tag list will be reverse sorted by length, + # it will produce nested links... + # well, that all is now solved, but in not too impressive way.. + $tag =~ s/_/./g; + push @tags, $tag; + } + } + + close SOURCE; +} + +print <
+lua-loudmouth docs + +HEADER +; + +@tags = reverse sort { length $a <=> length $b } @tags; +# TODO preserve original order +foreach my $file ( sort keys %docs ) { + print "
"; + foreach my $chunk ( @{$docs{$file}} ) { + my $head = shift @$chunk; + my $tag = $head; + my $list = undef; + $tag =~ s/_/./g; + print "

$head

"; + foreach ( @$chunk ) { + s/^A: /Arguments: /; + s/^R: /Return values: /; + s/^V: /Values: /; + if ( $list ) { + if ( /^\* / ) { + s/^\* /<\/li>

  • /; + } else { + s/^/<\/li><\/ul> /; + $list = undef; + } + } elsif ( /^\* / ) { + s/^\* /" if $list; + print "

    " + } + print "
    "; +} + +print "" + +# The end diff -r 65cbecad22b4 -r 7d87d323c889 main.c --- a/main.c Sun Feb 22 23:14:24 2009 +0200 +++ b/main.c Mon Feb 23 04:05:05 2009 +0200 @@ -4,41 +4,41 @@ #include #include #include -#include // popen, pclose, fileno +#include +#include // getenv -#include "logprint.h" // scr_LogPrint -#include "screen.h" // scr_Beep, scr_WriteIncomingMessage -#include "hbuf.h" // HBB_PREFIX_INFO -#include "commands.h" // process_command -#include "xmpp.h" // xmpp_getstatus, xmpp_getstatusmsg, lconnection -#include "roster.h" // imstatus2char, foreach_buddy, buddy_*, current_buddy, BUDDATA, ROSTER_TYPE_* -#include "utils.h" // from_utf8 -#include "lua_util.h" // mcabber_config_file, string2enum -#include "hooks.h" -#include "settings.h" +#include "util.h" +#include "logprint.h" // scr_LogPrint +#include "screen.h" // scr_Beep, scr_WriteIncomingMessage +#include "hbuf.h" // HBB_PREFIX_INFO +#include "commands.h" // process_command, cmd_add, cmd_del +#include "xmpp.h" // xmpp_getstatus, xmpp_getstatusmsg, lconnection, xmpp_add_feature, xmpp_del_feature +#include "roster.h" // imstatus2char, foreach_buddy, buddy_*, current_buddy, BUDDATA, ROSTER_TYPE_* +#include "utils.h" // from_utf8, jidtodisp +#include "hooks.h" // hk_add_handler, hk_del_handler +#include "settings.h" // settings_set, settings_del, settings_get -lua_State *lua = NULL; // global lua state object +// global lua state object, necessary for uninitialization function +static lua_State *lua = NULL; +// caller sould g_free result char *mcabber_config_filename (const char *file) { - char *home = getenv("HOME"); - if (!home) - return NULL; - return g_strconcat (home, "/.mcabber/", file ? file : "", NULL); + const char *home = getenv ("HOME"); + if (!home) + return NULL; + return g_strconcat (home, "/.mcabber/", file ? file : "", NULL); } /// print -/// Prints it's arguments to log with default priority. -/// A: message, message... +/// Prints its arguments to log with default priority. +/// A: string/number, ... static int lua_global_print (lua_State *L) { - const char *message; - lua_concat (L, lua_gettop (L)); - message = lua_tostring (L, -1); - scr_LogPrint (LPRINT_LOGNORM, message); - lua_pop (L, 1); - return 0; + lua_concat (L, lua_gettop (L)); + scr_LogPrint (LPRINT_LOGNORM, lua_tostring (L, -1)); + return 0; } /// dopath @@ -46,47 +46,62 @@ /// A: string (filename, without ".lua") static int lua_global_dopath (lua_State *L) { - // const char *name = luaL_checkstring (L, 1); - // FIXME - return 0; + const char *name = luaL_checkstring (L, 1); + size_t size = lua_objlen (L, 1); + char *path; + if (!strncmp (name + size - 4, ".lua", 4)) + path = mcabber_config_filename (name); + else { + char *fname = g_strconcat (name, ".lua", NULL); + path = mcabber_config_filename (fname); + g_free (fname); + } + + if (luaL_loadfile (L, path)) + scr_LogPrint (LPRINT_LOGNORM, "lua: Unable to compile file %s: %s", path, lua_tostring (L, -1)); + else if (lua_pcall (lua, 0, LUA_MULTRET, 0)) + scr_LogPrint(LPRINT_LOGNORM, "lua: Runtime error in file %s: %s", path, lua_tostring (L, -1)); + + g_free (path); + return 0; } /// main.config_file /// Adds mcabber default config location path to config file name. -/// Note: not sure, that this function will stay alive long. +/// Note: deprecated, use dopath. /// A: string (filename) /// R: string (full path) static int lua_main_config_file (lua_State *L) { - char *home = mcabber_config_filename (lua_isstring (L, 1) ? - lua_tostring (L, 1) : NULL); - lua_pop (L, 1); - if (!home) { - lua_pushstring (L, "Cannot find home dir!"); - lua_error (L); - } - lua_pushstring (L, home); - g_free (home); // XXX - return 1; + char *home = mcabber_config_filename (luaL_checkstring (L, 1)); + if (!home) { + lua_pushstring (L, "Cannot find home dir!"); + lua_error (L); + } + lua_pushstring (L, home); + g_free (home); + return 1; } /// log print type -/// V: normal, log, debug, notutf8, lognorm +/// G: static const string2enum_t lua_lprint[] = { - { "normal", LPRINT_NORMAL }, - { "log", LPRINT_LOG }, - { "debug", LPRINT_DEBUG }, - { "notutf0", LPRINT_NOTUTF8 }, - { NULL, 0 }, + { "normal", LPRINT_NORMAL }, + { "log", LPRINT_LOG }, + { "debug", LPRINT_DEBUG }, + { "notutf0", LPRINT_NOTUTF8 }, + { NULL, 0 }, }; +/// roster type +/// G: static const string2enum_t lua_roster_type[] = { - { "user", ROSTER_TYPE_USER }, - { "group", ROSTER_TYPE_GROUP }, - { "agent", ROSTER_TYPE_AGENT }, - { "room", ROSTER_TYPE_ROOM }, - { "special", ROSTER_TYPE_SPECIAL }, - { NULL, 0 }, + { "user", ROSTER_TYPE_USER }, + { "group", ROSTER_TYPE_GROUP }, + { "agent", ROSTER_TYPE_AGENT }, + { "room", ROSTER_TYPE_ROOM }, + { "special", ROSTER_TYPE_SPECIAL }, + { NULL, 0 }, }; /// main.log @@ -94,12 +109,10 @@ /// A: log print type, message, message... static int lua_main_log (lua_State *L) { - const char *message; - int type = luaL_checkenum_multi (L, 1, lua_lprint); - lua_concat (L, lua_gettop (L) - 1); - message = lua_tostring (L, -1); - scr_LogPrint (type, message); - return 0; + int type = luaL_checkenum_multi (L, 1, lua_lprint); + lua_concat (L, lua_gettop (L) - 1); + scr_LogPrint (type, lua_tostring (L, -1)); + return 0; } /// main.option @@ -110,23 +123,23 @@ /// R: string (value, optional) static int lua_main_option (lua_State *L) { - const char *name = luaL_checkstring (L, 1); - if (lua_gettop (L) > 1) { // Set - if (lua_type (L, 2) == LUA_TNIL) - settings_del (SETTINGS_TYPE_OPTION, name); - else { - const char *value = luaL_checkstring (L, 2); - settings_set (SETTINGS_TYPE_OPTION, name, value); - } - return 0; - } else { - const char *value = settings_get (SETTINGS_TYPE_OPTION, name); - if (value) - lua_pushstring (L, value); - else - lua_pushnil (L); - return 1; - } + const char *name = luaL_checkstring (L, 1); + if (lua_gettop (L) > 1) { // Set + if (lua_type (L, 2) == LUA_TNIL) // Unset + settings_del (SETTINGS_TYPE_OPTION, name); + else { // Set + const char *value = luaL_checkstring (L, 2); + settings_set (SETTINGS_TYPE_OPTION, name, value); + } + return 0; + } else { // Get + const char *value = settings_get (SETTINGS_TYPE_OPTION, name); + if (value) + lua_pushstring (L, value); + else + lua_pushnil (L); + return 1; + } } /// main.connection @@ -135,60 +148,74 @@ /// R: lightuserdata static int lua_main_connection (lua_State *L) { - lua_pushlightuserdata (L, lconnection); - return 1; + lua_pushlightuserdata (L, lconnection); + return 1; } -// Well, for now -// I cannot get how -// To use caps. - /// main.add_feature +/// Adds xmlns to disco#info features list. /// A: string (xmlns) static int lua_main_add_feature (lua_State *L) { -// xmpp_add_feature (luaL_checkstring (L, 1)); - return 0; + xmpp_add_feature (luaL_checkstring (L, 1)); + return 0; } /// main.del_feature +/// Removes xmlns from disco#info features list. /// A: stirng (xmlns) static int lua_main_del_feature (lua_State *L) { -// xmpp_del_feature (luaL_checkstring (L, 1)); - return 0; + xmpp_del_feature (luaL_checkstring (L, 1)); + return 0; } typedef struct { - int reference; - lua_State *L; + int reference; + lua_State *L; } lua_command_callback_t; /// command function -/// A: argument string +/// Function to handle newly registered command. +/// A: string (arguments) void lua_main_command_handler (char *args, lua_command_callback_t *cb) { - lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); - lua_pushstring (cb->L, args); - if (lua_pcall (cb->L, 1, 0, 0)) { - scr_LogPrint (LPRINT_LOGNORM, "lua: Command execution error: %s", - lua_tostring (cb->L, -1)); - lua_pop (cb->L, 1); - } + lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); + lua_pushstring (cb->L, args); + if (lua_pcall (cb->L, 1, 0, 0)) { + scr_LogPrint (LPRINT_LOGNORM, "lua: Command execution error: %s", lua_tostring (cb->L, -1)); + lua_pop (cb->L, 1); + } } /// main.add_command +/// Associates mcabber command name with lua function. /// A: string (command name), command function static int lua_main_add_command (lua_State *L) { - const char *name = luaL_checkstring (L, 1); - lua_command_callback_t *cb; - luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected"); - cb = luaL_malloc (L, sizeof (lua_command_callback_t)); - cb->reference = luaL_ref (L, LUA_REGISTRYINDEX); - cb->L = L; - cmd_add (name, "", 0, 0, (void (*) (char *p)) lua_main_command_handler, cb); - return 0; + const char *name = luaL_checkstring (L, 1); + lua_command_callback_t *cb; + luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected"); + + cb = luaL_malloc (L, sizeof (lua_command_callback_t)); + cb->reference = luaL_ref (L, LUA_REGISTRYINDEX); + cb->L = L; + cmd_add (name, "", 0, 0, (void (*) (char *p)) lua_main_command_handler, cb); + return 0; +} + +/// main.del_command +/// Removes command from a list of commands. +/// A: string (command name) +static int lua_main_del_command (lua_State *L) +{ + const char *name = luaL_checkstring (L, 1); + lua_command_callback_t *cb = cmd_del (name); + if (cb) { + luaL_unref (L, LUA_REGISTRYINDEX, cb->reference); + luaL_free (L, cb); + } + return 0; } /// main.print_info @@ -196,19 +223,18 @@ /// A: string (jid), string (message) static int lua_main_print_info (lua_State *L) { - char *to = jidtodisp (luaL_checkstring (L, 1)); - const char *message = luaL_checkstring (L, 2); - scr_WriteIncomingMessage (to, message, 0, HBB_PREFIX_INFO, 0); - g_free (to); - return 0; + char *to = jidtodisp (luaL_checkstring (L, 1)); + scr_WriteIncomingMessage (to, luaL_checkstring (L, 2), 0, HBB_PREFIX_INFO, 0); + g_free (to); + return 0; } /// main.beep /// Beeps with system speaker. static int lua_main_beep (lua_State *L) { - scr_Beep (); - return 0; + scr_Beep (); + return 0; } /// main.run @@ -216,29 +242,28 @@ /// A: string static int lua_main_run (lua_State *L) { - const char *command = luaL_checkstring (L, 1); - process_command (command, TRUE); - return 0; + process_command (luaL_checkstring (L, 1), TRUE); + return 0; } /// main.status /// Returns your current status. -/// R: char (status letter), string (status message) +/// R: string (status letter), string (status message) static int lua_main_status (lua_State *L) { - char *sm = from_utf8 (xmpp_getstatusmsg ()); - lua_pushlstring (L, &imstatus2char[xmpp_getstatus ()], 1); - lua_pushstring (L, sm); - g_free (sm); - return 2; + char *sm = from_utf8 (xmpp_getstatusmsg ()); + lua_pushlstring (L, &imstatus2char[xmpp_getstatus ()], 1); + lua_pushstring (L, sm); + g_free (sm); + return 2; } -// expects table on top! +// expects table on top static void lua_rosterlist_callback (gpointer buddy, lua_State *L) { - lua_pushnumber (L, lua_objlen (L, -1) + 1); - lua_pushstring (L, buddy_getjid (buddy)); - lua_settable (L, -3); + lua_pushnumber (L, lua_objlen (L, -1) + 1); + lua_pushstring (L, buddy_getjid (buddy)); + lua_settable (L, -3); } /// main.roster @@ -246,9 +271,9 @@ /// R: table static int lua_main_roster (lua_State *L) { - lua_newtable (L); - foreach_buddy (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM, (void (*) (gpointer buddy, void *data))lua_rosterlist_callback, L); - return 1; + lua_newtable (L); + foreach_buddy (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM, (void (*) (gpointer buddy, void *data))lua_rosterlist_callback, L); + return 1; } /// main.current_buddy @@ -256,30 +281,30 @@ /// R: string static int lua_main_current_buddy (lua_State *L) { - lua_pushstring (L, buddy_getjid (BUDDATA (current_buddy))); - return 1; + lua_pushstring (L, buddy_getjid (BUDDATA (current_buddy))); + return 1; } typedef struct { - lua_State *L; - gpointer buddy; + lua_State *L; + gpointer buddy; } lua_state_and_buddy_t; // :) // expects table on top! static void lua_buddy_resources_callback (gpointer resource, lua_state_and_buddy_t *d) { - lua_pushstring (d->L, resource); - lua_createtable (d->L, 0, 3); - lua_pushstring (d->L, "priority"); - lua_pushnumber (d->L, buddy_getresourceprio (d->buddy, resource)); - lua_settable (d->L, -3); - lua_pushstring (d->L, "status"); - lua_pushlstring (d->L, &imstatus2char[buddy_getstatus (d->buddy, resource)], 1); - lua_settable (d->L, -3); - lua_pushstring (d->L, "message"); - lua_pushstring (d->L, buddy_getstatusmsg (d->buddy, resource)); - lua_settable (d->L, -3); - lua_settable (d->L, -3); + lua_pushstring (d->L, resource); + lua_createtable (d->L, 0, 3); + lua_pushstring (d->L, "priority"); + lua_pushnumber (d->L, buddy_getresourceprio (d->buddy, resource)); + lua_settable (d->L, -3); + lua_pushstring (d->L, "status"); + lua_pushlstring (d->L, &imstatus2char[buddy_getstatus (d->buddy, resource)], 1); + lua_settable (d->L, -3); + lua_pushstring (d->L, "message"); + lua_pushstring (d->L, buddy_getstatusmsg (d->buddy, resource)); + lua_settable (d->L, -3); + lua_settable (d->L, -3); } /// main.buddy_info @@ -292,37 +317,34 @@ /// R: table static int lua_main_buddy_info (lua_State *L) { - char *jid = jidtodisp (luaL_checkstring (L, 1)); - GSList *buddy = roster_find (jid, jidsearch, - ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM); - lua_state_and_buddy_t snb; - g_free (jid); + char *jid = jidtodisp (luaL_checkstring (L, 1)); + GSList *buddy = roster_find (jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM); + lua_state_and_buddy_t snb; + g_free (jid); + + if (!buddy) { + lua_pushnil (L); + return 1; + } - if (!buddy) { - lua_pushnil (L); - return 1; - } - - lua_createtable (L, 0, 3); - lua_pushstring (L, "type"); - lua_pushstring (L, enum2string (buddy_gettype (BUDDATA (buddy)), - lua_roster_type)); - lua_settable (L, -3); - lua_pushstring (L, "name"); - lua_pushstring (L, buddy_getname (BUDDATA (buddy))); - lua_settable (L, -3); - lua_pushstring (L, "onserver"); - lua_pushboolean (L, buddy_getonserverflag (BUDDATA (buddy))); - lua_settable (L, -3); - lua_pushstring (L, "resources"); - lua_createtable (L, 0, 0); - snb.L = L; - snb.buddy = BUDDATA (buddy); - g_slist_foreach (buddy_getresources (BUDDATA (buddy)), - (GFunc)lua_buddy_resources_callback, &snb); - lua_settable (L, -3); - - return 1; + lua_createtable (L, 0, 3); + lua_pushstring (L, "type"); + luaL_pushenum (L, buddy_gettype (BUDDATA (buddy)), lua_roster_type); + lua_settable (L, -3); + lua_pushstring (L, "name"); + lua_pushstring (L, buddy_getname (BUDDATA (buddy))); + lua_settable (L, -3); + lua_pushstring (L, "onserver"); + lua_pushboolean (L, buddy_getonserverflag (BUDDATA (buddy))); + lua_settable (L, -3); + lua_pushstring (L, "resources"); + lua_createtable (L, 0, 0); + snb.L = L; + snb.buddy = BUDDATA (buddy); + g_slist_foreach (buddy_getresources (BUDDATA (buddy)), (GFunc) lua_buddy_resources_callback, &snb); + lua_settable (L, -3); + + return 1; } // TIMER @@ -330,14 +352,14 @@ #define LUA_TIMER_PRIORITY ( G_PRIORITY_HIGH_IDLE ) typedef struct { - int reference; - lua_State *L; + int reference; + lua_State *L; } lua_timer_callback_t; static void lua_timer_callback_destroy (lua_timer_callback_t *cb) { - luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference); - luaL_free (cb->L, cb); + luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference); + luaL_free (cb->L, cb); } /// timer function @@ -345,17 +367,16 @@ /// R: boolean static gboolean lua_timer_callback (lua_timer_callback_t *cb) { - int ret; - lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); - if (lua_pcall (cb->L, 0, 1, 0)) { - scr_LogPrint (LPRINT_LOGNORM, "lua: Timer callback execution error: %s", - lua_tostring (cb->L, -1)); - lua_pop (cb->L, 1); - return FALSE; - } - ret = lua_toboolean (cb->L, -1); - lua_pop (cb->L, 1); - return ret; + int ret; + lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); + if (lua_pcall (cb->L, 0, 1, 0)) { + scr_LogPrint (LPRINT_LOGNORM, "lua: Timer callback execution error: %s", lua_tostring (cb->L, -1)); + lua_pop (cb->L, 1); + return FALSE; + } + ret = lua_toboolean (cb->L, -1); + lua_pop (cb->L, 1); + return ret; } /// main.timer @@ -363,18 +384,16 @@ /// A: integer (interval, seconds), timer function static int lua_main_timer (lua_State *L) { - int interval = luaL_checkint (L, 1); - lua_timer_callback_t *cb; - luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected"); + int interval = luaL_checkint (L, 1); + lua_timer_callback_t *cb; + luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected"); - cb = luaL_malloc (L, sizeof (lua_timer_callback_t)); - cb->reference = luaL_ref (L, LUA_REGISTRYINDEX); - cb->L = L; + cb = luaL_malloc (L, sizeof (lua_timer_callback_t)); + cb->reference = luaL_ref (L, LUA_REGISTRYINDEX); + cb->L = L; - g_timeout_add_seconds_full (LUA_TIMER_PRIORITY, interval, - (GSourceFunc)lua_timer_callback, cb, - (GDestroyNotify)lua_timer_callback_destroy); - return 0; + g_timeout_add_seconds_full (LUA_TIMER_PRIORITY, interval, (GSourceFunc) lua_timer_callback, cb, (GDestroyNotify) lua_timer_callback_destroy); + return 0; } // BACKGROUND PIPE READING @@ -382,18 +401,18 @@ #define LUA_BGREAD_BUFFER ( 4096 ) typedef struct { - lua_State *L; - FILE *fd; - int reference; + lua_State *L; + FILE *fd; + int reference; } lua_bgread_callback_t; static gchar lua_bgread_buffer[LUA_BGREAD_BUFFER]; static void lua_bgread_callback_destroy (lua_bgread_callback_t *cb) { - luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference); - pclose (cb->fd); - luaL_free (cb->L, cb); + luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference); + pclose (cb->fd); + luaL_free (cb->L, cb); } /// background reading function @@ -401,205 +420,196 @@ /// A: string (data) or nil (eof) /// R: boolean (false if reading should be terminated) static gboolean -lua_bgread_callback (GIOChannel *source, GIOCondition condition, - lua_bgread_callback_t *cb) +lua_bgread_callback (GIOChannel *source, GIOCondition condition, lua_bgread_callback_t *cb) { - int ret = TRUE; + int ret = TRUE; - if (condition | G_IO_IN) { // data - while (TRUE) { - gsize read = 0; - g_io_channel_read_chars(source, lua_bgread_buffer, LUA_BGREAD_BUFFER, - &read, NULL); - if (!read) // exausted - break; + if (condition | G_IO_IN) { // data + while (TRUE) { + gsize read = 0; + g_io_channel_read_chars (source, lua_bgread_buffer, LUA_BGREAD_BUFFER, &read, NULL); + if (!read) // exausted + break; - lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); - lua_pushlstring (cb->L, lua_bgread_buffer, read); - if (lua_pcall (cb->L, 1, 1, 0)) { - scr_LogPrint (LPRINT_LOGNORM, - "lua: Bgread callback execution error: %s", - lua_tostring (cb->L, -1)); - lua_pop (cb->L, 1); - return FALSE; - } - ret = lua_toboolean (cb->L, -1); - lua_pop (cb->L, 1); - if (!ret) // enough - return FALSE; - } - } + lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); + lua_pushlstring (cb->L, lua_bgread_buffer, read); + if (lua_pcall (cb->L, 1, 1, 0)) { + scr_LogPrint (LPRINT_LOGNORM, "lua: Bgread callback execution error: %s", lua_tostring (cb->L, -1)); + lua_pop (cb->L, 1); + return FALSE; + } + ret = lua_toboolean (cb->L, -1); + lua_pop (cb->L, 1); + if (!ret) // enough + return FALSE; + } + } - if (condition & ~G_IO_IN) { // err or hup - lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); - lua_pushnil (cb->L); - if (lua_pcall (cb->L, 1, 1, 0)) { - scr_LogPrint (LPRINT_LOGNORM, "lua: Bgread callback execution error: %s", - lua_tostring (cb->L, -1)); - lua_pop (cb->L, 1); - return FALSE; - } - ret = lua_toboolean (cb->L, -1); - lua_pop (cb->L, 1); - } + if (condition & ~G_IO_IN) { // err or hup + lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); + lua_pushnil (cb->L); + if (lua_pcall (cb->L, 1, 1, 0)) { + scr_LogPrint (LPRINT_LOGNORM, "lua: Bgread callback execution error: %s", lua_tostring (cb->L, -1)); + lua_pop (cb->L, 1); + return FALSE; + } + ret = lua_toboolean (cb->L, -1); + lua_pop (cb->L, 1); + } - return ret; + return ret; } /// main.bgread -/// Runs specified command and passes it's output to given function. +/// Runs specified command and passes its output to a given function. /// A: string (command), background reading function static int lua_main_bgread (lua_State *L) { - const char *command = luaL_checkstring (L, 1); - lua_bgread_callback_t *cb; - FILE *fd; - GIOChannel *channel; - const char *charset = NULL; - luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected"); + const char *command = luaL_checkstring (L, 1); + lua_bgread_callback_t *cb; + FILE *fd; + GIOChannel *channel; + const char *charset = NULL; + luaL_argcheck (L, lua_isfunction (L, 2), 2, "function expected"); - fd = popen (command, "r"); - if (!fd) { - lua_pushstring (L, "Error opening pipe"); - lua_error (L); - } + fd = popen (command, "r"); + if (!fd) { + lua_pushstring (L, "Error opening pipe"); + lua_error (L); + } - channel = g_io_channel_unix_new (fileno (fd)); -// We, most likely, need this, -// But we cannot use this, -// It will block. -//if (!g_get_charset (&charset)) - g_io_channel_set_encoding (channel, charset, NULL); - g_io_channel_set_buffered (channel, FALSE); - g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL); - g_io_channel_set_close_on_unref (channel, TRUE); + channel = g_io_channel_unix_new (fileno (fd)); + // We, most likely, need this, + // But we cannot use this, + // It will block. + //if (!g_get_charset (&charset)) + g_io_channel_set_encoding (channel, charset, NULL); + g_io_channel_set_buffered (channel, FALSE); + g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL); + g_io_channel_set_close_on_unref (channel, TRUE); - cb = luaL_malloc (L, sizeof (lua_bgread_callback_t)); - cb->reference = luaL_ref (L, LUA_REGISTRYINDEX); - cb->L = L; - cb->fd = fd; + cb = luaL_malloc (L, sizeof (lua_bgread_callback_t)); + cb->reference = luaL_ref (L, LUA_REGISTRYINDEX); + cb->L = L; + cb->fd = fd; - g_io_add_watch_full (channel, G_PRIORITY_HIGH_IDLE, - G_IO_IN|G_IO_HUP|G_IO_ERR, - (GIOFunc)lua_bgread_callback, cb, - (GDestroyNotify)lua_bgread_callback_destroy); - return 0; + g_io_add_watch_full (channel, G_PRIORITY_HIGH_IDLE, G_IO_IN|G_IO_HUP|G_IO_ERR, (GIOFunc) lua_bgread_callback, cb, (GDestroyNotify) lua_bgread_callback_destroy); + return 0; } // MAIN INITIALIZATION CODE -static void *lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { - if (nsize == 0) { - g_free (ptr); - return NULL; - } else - return g_realloc (ptr, nsize); -} +#define LUA_HOOK_NAME ( "hook_handler" ) static void lua_hook (hk_arg_t *args, lua_State *L) { - hk_arg_t *arg = args; - lua_getglobal (lua, "hook_handler"); - if (!lua_isfunction (lua, -1)) { - lua_pop (lua, 1); - return; - } - lua_newtable (L); - while (arg->name != NULL) { - lua_pushstring (L, arg->name); - lua_pushstring (L, arg->value); - lua_settable (L, -3); - arg++; - } - if (lua_pcall (lua, 1, 0, 0)) { - scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook_handler: %s", - lua_tostring (lua, -1)); - lua_pop (lua, 1); - } + hk_arg_t *arg = args; + lua_getglobal (lua, LUA_HOOK_NAME); + if (!lua_isfunction (lua, -1)) { + lua_pop (lua, 1); + return; + } + lua_newtable (L); + while (arg->name != NULL) { + lua_pushstring (L, arg->name); + lua_pushstring (L, arg->value); + lua_settable (L, -3); + arg++; + } + if (lua_pcall (lua, 1, 0, 0)) { + scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook_handler: %s", lua_tostring (lua, -1)); + lua_pop (lua, 1); + } +} + +static void *lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { + if (nsize == 0) { + g_free (ptr); + return NULL; + } else + return g_realloc (ptr, nsize); } static const luaL_Reg lua_reg_main[] = { - { "config_file", lua_main_config_file }, - { "connection", lua_main_connection }, - { "log", lua_main_log }, - { "option", lua_main_option }, - { "add_feature", lua_main_add_feature }, - { "del_feature", lua_main_del_feature }, - { "add_command", lua_main_add_command }, - { "print_info", lua_main_print_info }, - { "beep", lua_main_beep }, - { "run", lua_main_run }, - { "status", lua_main_status }, - { "roster", lua_main_roster }, - { "current_buddy", lua_main_current_buddy }, - { "buddy_info", lua_main_buddy_info }, - { "timer", lua_main_timer }, - { "bgread", lua_main_bgread }, - { NULL, NULL }, // end + { "config_file", lua_main_config_file }, + { "connection", lua_main_connection }, + { "log", lua_main_log }, + { "option", lua_main_option }, + { "add_feature", lua_main_add_feature }, + { "del_feature", lua_main_del_feature }, + { "add_command", lua_main_add_command }, + { "del_command", lua_main_del_command }, + { "print_info", lua_main_print_info }, + { "beep", lua_main_beep }, + { "run", lua_main_run }, + { "status", lua_main_status }, + { "roster", lua_main_roster }, + { "current_buddy", lua_main_current_buddy }, + { "buddy_info", lua_main_buddy_info }, + { "timer", lua_main_timer }, + { "bgread", lua_main_bgread }, + { NULL, NULL }, }; const gchar *g_module_check_init (GModule *module) { - char *initfile; + char *initfile; - lua = lua_newstate(lua_alloc, NULL); - if (!lua) { - scr_LogPrint(LPRINT_LOGNORM, "lua: Initialization error"); - return; - } + lua = lua_newstate (lua_alloc, NULL); + if (!lua) { + scr_LogPrint (LPRINT_LOGNORM, "lua: Initialization error"); + return "Lua initialization error"; + } - luaL_openlibs(lua); + luaL_openlibs (lua); - luaL_register(lua, "main", lua_reg_main); - lua_pop (lua, 1); -// lua_register(lua, "dopath", lua_global_dopath); - lua_register(lua, "print", lua_global_print); - - initfile = mcabber_config_filename ("mcabberrc.lua"); - if (!initfile) - scr_LogPrint(LPRINT_LOGNORM, "lua: Cannot determine config file name"); - else { - int err = luaL_loadfile(lua, initfile); - if (err) - scr_LogPrint(LPRINT_LOGNORM, "lua: Unable to compile rc file (%d)", err); - else if (lua_pcall(lua, 0, LUA_MULTRET, 0)) { - scr_LogPrint(LPRINT_LOGNORM, "lua: Runtime error in rc file: %s", - lua_tostring(lua, -1)); - lua_pop (lua, 1); - } else - scr_LogPrint(LPRINT_LOGNORM, "Loaded mcabberrc.lua"); - g_free(initfile); // XXX - } + luaL_register (lua, "main", lua_reg_main); + lua_pop (lua, 1); // XXX + lua_register (lua, "dopath", lua_global_dopath); + lua_register (lua, "print", lua_global_print ); + + initfile = mcabber_config_filename ("mcabberrc.lua"); + if (!initfile) + scr_LogPrint (LPRINT_LOGNORM, "lua: Cannot determine config file name"); + else { + if (luaL_loadfile(lua, initfile)) { + scr_LogPrint (LPRINT_LOGNORM, "lua: Unable to compile rc file: %s", lua_tostring (lua, -1)); + lua_pop (lua, 1); + } else if (lua_pcall (lua, 0, LUA_MULTRET, 0)) { + scr_LogPrint (LPRINT_LOGNORM, "lua: Runtime error in rc file: %s", lua_tostring(lua, -1)); + lua_pop (lua, 1); + } else + scr_LogPrint (LPRINT_LOGNORM, "Loaded mcabberrc.lua"); + g_free (initfile); + } - hk_add_handler ((hk_handler_t) lua_hook, lua); + hk_add_handler ((hk_handler_t) lua_hook, lua); - lua_getglobal (lua, "hook_start"); - if (!lua_isfunction (lua, -1)) - lua_pop (lua, 1); - else if (lua_pcall (lua, 0, 0, 0)) { - scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook_start: %s", - lua_tostring (lua, -1)); - lua_pop (lua, 1); - } + lua_getglobal (lua, "hook_start"); + if (!lua_isfunction (lua, -1)) + lua_pop (lua, 1); + else if (lua_pcall (lua, 0, 0, 0)) { + scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook_start: %s", lua_tostring (lua, -1)); + lua_pop (lua, 1); + } + return NULL; } void g_module_unload (GModule *module) { - if (lua) { - lua_getglobal (lua, "hook_quit"); - if (!lua_isfunction (lua, -1)) - lua_pop (lua, 1); - else if (lua_pcall (lua, 0, 0, 0)) { - scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook_quit: %s", - lua_tostring (lua, -1)); - lua_pop (lua, 1); - } - - hk_del_handler ((hk_handler_t) lua_hook, lua); + if (lua) { + lua_getglobal (lua, "hook_quit"); + if (!lua_isfunction (lua, -1)) + lua_pop (lua, 1); + else if (lua_pcall (lua, 0, 0, 0)) { + scr_LogPrint (LPRINT_NORMAL, "lua: Error in hook_quit: %s", lua_tostring (lua, -1)); + lua_pop (lua, 1); + } + + hk_del_handler ((hk_handler_t) lua_hook, lua); - lua_close (lua); - lua = NULL; - } + lua_close (lua); + lua = NULL; + } } -/* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */