summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Davis <loafier@gmail.com>2006-06-24 03:10:40 +0000
committerChristopher Davis <loafier@gmail.com>2006-06-24 03:10:40 +0000
commitd75ad2cebb61a3cb46570cecbc257693c528da0b (patch)
tree863b5ebfaca07d0c4ad140ce58e35d90916d78b7
parent4d33c04f15e60e21a537edd635c9ac130312a3cb (diff)
downloadirssi-python-d75ad2cebb61a3cb46570cecbc257693c528da0b.tar.gz
irssi-python-d75ad2cebb61a3cb46570cecbc257693c528da0b.tar.xz
irssi-python-d75ad2cebb61a3cb46570cecbc257693c528da0b.zip
Worked more on signal handler. Got variable signals
working (IE: event *) Still need to get signal emit, register, unregister, cmd unbind, sig remove and a few others. git-svn-id: http://svn.irssi.org/repos/irssi-python@4290 dbcabf3a-b0e7-0310-adc4-f8d773084564
-rw-r--r--irssi.py30
-rw-r--r--pysigmap.h6
-rw-r--r--pysignals.c132
-rw-r--r--pysignals.h3
-rw-r--r--sig2code.py9
5 files changed, 122 insertions, 58 deletions
diff --git a/irssi.py b/irssi.py
index 9b0ef6f..68a7074 100644
--- a/irssi.py
+++ b/irssi.py
@@ -35,34 +35,10 @@ MSGLEVEL_NO_ACT = 0x2000000
MSGLEVEL_NEVER = 0x4000000
MSGLEVEL_LASTLOG = 0x8000000
-"""
-#Link Irssi functions and objects
-get_script = _irssi.get_script
-prnt = _irssi.prnt
-chatnets = _irssi.chatnets
-servers = _irssi.servers
-reconnects = _irssi.reconnects
-chatnet_find = _irssi.chatnet_find
-windows = _irssi.windows
-
-Script = _irssi.Script
-Channel = _irssi.Channel
-Query = _irssi.Query
-WindowItem = _irssi.WindowItem
-Window = _irssi.Window
-Server = _irssi.Server
-Connect = _irssi.Connect
-IrcServer = _irssi.IrcServer
-IrcConnect = _irssi.IrcConnect
-IrcChannel = _irssi.IrcChannel
-Ban = _irssi.Ban
-Nick = _irssi.Nick
-Chatnet = _irssi.Chatnet
-Reconnect = _irssi.Reconnect
-"""
-
def command_bind(*args, **kwargs):
""" see Script.command_bind """
get_script().command_bind(*args, **kwargs)
-
+def signal_add(*args, **kwargs):
+ """ see Script.signal_add """
+ get_script().signal_add(*args, **kwargs)
diff --git a/pysigmap.h b/pysigmap.h
index 0e37935..b6c3278 100644
--- a/pysigmap.h
+++ b/pysigmap.h
@@ -58,17 +58,21 @@ static PY_SIGNAL_SPEC_REC py_sigmap[] = {
{"channel sync", "C", 0, 0, 0},
{"channel topic changed", "C", 0, 0, 0},
{"ctcp msg", "Sssss", 0, 0, 0},
+ {"ctcp msg ", "Sssss", 0, 0, 1},
{"default ctcp msg", "Sssss", 0, 0, 0},
{"ctcp reply", "Sssss", 0, 0, 0},
+ {"ctcp reply ", "Sssss", 0, 0, 1},
{"default ctcp reply", "Sssss", 0, 0, 0},
{"ctcp action", "Sssss", 0, 0, 0},
{"awaylog show", "lii", 0, 0, 0},
{"server nick changed", "S", 0, 0, 0},
{"event connected", "S", 0, 0, 0},
{"server event", "Ssss", 0, 0, 0},
+ {"event ", "Ssss", 0, 0, 1},
{"default event", "Ssss", 0, 0, 0},
{"whois default event", "Ssss", 0, 0, 0},
{"server incoming", "Ss", 0, 0, 0},
+ {"redir ", "Ssss", 0, 0, 1},
{"server lag", "S", 0, 0, 0},
{"server lag disconnect", "S", 0, 0, 0},
{"massjoin", "CL", 0, 0, 0},
@@ -82,8 +86,10 @@ static PY_SIGNAL_SPEC_REC py_sigmap[] = {
{"netsplit server remove", "Se", 0, 0, 0},
{"netsplit new", "N", 0, 0, 0},
{"netsplit remove", "N", 0, 0, 0},
+ {"dcc ctcp ", "sd", 0, 0, 1},
{"default dcc ctcp", "sd", 0, 0, 0},
{"dcc unknown ctcp", "sss", 0, 0, 0},
+ {"dcc reply ", "sd", 0, 0, 1},
{"default dcc reply", "sd", 0, 0, 0},
{"dcc unknown reply", "sss", 0, 0, 0},
{"dcc chat message", "ds", 0, 0, 0},
diff --git a/pysignals.c b/pysignals.c
index fb4a3d9..58cc6d4 100644
--- a/pysignals.c
+++ b/pysignals.c
@@ -14,20 +14,20 @@
* scripts can no longer bind to it.
*/
-//FIXME: does not handle binding of signals with varying <cmd> text
-
typedef struct _PY_SIGNAL_SPEC_REC
{
char *name;
char *arglist;
- int id;
int refcount;
int dynamic;
+ int is_var; /* is this entry a prefix for a variable signal? */
} PY_SIGNAL_SPEC_REC;
#include "pysigmap.h"
+/* hashtable for normal signals, tree for variable signal prefixes. */
static GHashTable *py_sighash = NULL;
+static GTree *py_sigtree = NULL;
static void py_run_handler(PY_SIGNAL_REC *rec, void **args);
static void py_sig_proxy(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6);
@@ -39,6 +39,9 @@ static void py_signal_rec_destroy(PY_SIGNAL_REC *sig);
static PyObject *py_mkstrlist(void *iobj);
static PyObject *py_i2py(char code, void *iobj);
static void py_getstrlist(GList **list, PyObject *pylist);
+static int precmp(const char *spec, const char *test);
+static PY_SIGNAL_SPEC_REC *py_signal_lookup(const char *name);
+static void py_signal_remove(PY_SIGNAL_SPEC_REC *sig);
PY_SIGNAL_REC *pysignals_command_bind(const char *cmd, PyObject *func,
const char *category, int priority)
@@ -56,18 +59,21 @@ PY_SIGNAL_REC *pysignals_command_bind(const char *cmd, PyObject *func,
PY_SIGNAL_REC *pysignals_signal_add(const char *signal, PyObject *func, int priority)
{
PY_SIGNAL_REC *rec = py_signal_rec_new(signal, func, NULL);
-
+ char *name;
+
if (rec == NULL)
return NULL;
+
+ name = rec->command? rec->command : rec->signal->name;
- signal_add_full_id(MODULE_NAME, priority, rec->signal->id,
- (SIGNAL_FUNC)py_sig_proxy, rec);
+ signal_add_full(MODULE_NAME, priority, name, (SIGNAL_FUNC)py_sig_proxy, rec);
return rec;
}
void pysignals_command_unbind(PY_SIGNAL_REC *rec)
{
+ g_return_if_fail(rec->is_signal == FALSE);
g_return_if_fail(rec->command != NULL);
command_unbind_full(rec->command, (SIGNAL_FUNC)py_sig_proxy, rec);
@@ -76,18 +82,22 @@ void pysignals_command_unbind(PY_SIGNAL_REC *rec)
void pysignals_signal_remove(PY_SIGNAL_REC *rec)
{
- g_return_if_fail(rec->command == NULL);
+ char *name;
- signal_remove_id(rec->signal->id, (SIGNAL_FUNC)py_sig_proxy, rec);
+ g_return_if_fail(rec->is_signal == TRUE);
+
+ name = rec->command? rec->command : rec->signal->name;
+
+ signal_remove_full(name, (SIGNAL_FUNC)py_sig_proxy, rec);
py_signal_rec_destroy(rec);
}
void pysignals_remove_generic(PY_SIGNAL_REC *rec)
{
- if (rec->command)
- pysignals_command_unbind(rec);
- else
+ if (rec->is_signal)
pysignals_signal_remove(rec);
+ else
+ pysignals_command_unbind(rec);
}
static PyObject *py_mkstrlist(void *iobj)
@@ -303,16 +313,30 @@ static PY_SIGNAL_REC *py_signal_rec_new(const char *signal, PyObject *func, cons
g_return_val_if_fail(func != NULL, NULL);
- spec = g_hash_table_lookup(py_sighash, signal);
+ spec = py_signal_lookup(signal);
if (!spec)
return NULL;
- rec = g_new(PY_SIGNAL_REC, 1);
- rec->command = g_strdup(command);
+ rec = g_new0(PY_SIGNAL_REC, 1);
rec->signal = spec;
rec->handler = func;
Py_INCREF(func);
+ if (command)
+ {
+ rec->is_signal = FALSE;
+ rec->command = g_strdup(command);
+ }
+ else
+ {
+ rec->is_signal = TRUE;
+ /* handle variable signal. requested signal will be longer than spec->name, ie
+ * signal = "var signal POOOM", spec->name = "var signal "
+ */
+ if (strcmp(signal, spec->name) != 0)
+ rec->command = g_strdup(signal);
+ }
+
py_signal_ref(spec);
return rec;
@@ -329,7 +353,51 @@ static void py_signal_rec_destroy(PY_SIGNAL_REC *sig)
static void py_signal_add(PY_SIGNAL_SPEC_REC *sig)
{
- g_hash_table_insert(py_sighash, sig->name, sig);
+ if (sig->is_var)
+ g_tree_insert(py_sigtree, sig->name, sig);
+ else
+ g_hash_table_insert(py_sighash, sig->name, sig);
+}
+
+static void py_signal_remove(PY_SIGNAL_SPEC_REC *sig)
+{
+ int ret;
+
+ if (sig->is_var)
+ g_tree_remove(py_sigtree, sig->name);
+ else
+ {
+ ret = g_hash_table_remove(py_sighash, sig->name);
+ g_return_if_fail(ret != FALSE);
+ }
+}
+
+static int precmp(const char *spec, const char *test)
+{
+ //printf("precmp(spec,test) -> '%s', '%s'\n", spec, test);
+
+ while (*spec == *test++)
+ if (*spec++ == '\0')
+ return 0;
+
+ /* Variable event prefix matches (spec must never be empty string)*/
+ /* precmp("var event ", "var event POOOM") -> 0 */
+ if (*spec == '\0' && *(spec-1) == ' ')
+ return 0;
+
+ return *(const unsigned char *)(test - 1) - *(const unsigned char *)spec;
+}
+
+static PY_SIGNAL_SPEC_REC *py_signal_lookup(const char *name)
+{
+ PY_SIGNAL_SPEC_REC *ret;
+
+ /* First check the normal signals hash, then check the variable signal prefixes in the tree */
+ ret = g_hash_table_lookup(py_sighash, name);
+ if (!ret)
+ ret = g_tree_search(py_sigtree, (GCompareFunc)precmp, name);
+
+ return ret;
}
static void py_signal_ref(PY_SIGNAL_SPEC_REC *sig)
@@ -342,6 +410,7 @@ static void py_signal_ref(PY_SIGNAL_SPEC_REC *sig)
static int py_signal_unref(PY_SIGNAL_SPEC_REC *sig)
{
g_return_val_if_fail(sig->refcount >= 1, 0);
+ g_return_val_if_fail(sig->refcount > 1 || !sig->dynamic, 0);
sig->refcount--;
@@ -349,7 +418,7 @@ static int py_signal_unref(PY_SIGNAL_SPEC_REC *sig)
{
if (sig->dynamic)
{
- g_hash_table_remove(py_sighash, sig->name);
+ py_signal_remove(sig);
/* freeing name also takes care of the key */
g_free(sig->name);
@@ -365,22 +434,22 @@ static int py_signal_unref(PY_SIGNAL_SPEC_REC *sig)
return 0;
}
-/* returns 0 when signal already exists, but with different args */
+/* returns 0 when signal already exists, but with different args. */
int pysignals_register(const char *name, const char *arglist)
{
PY_SIGNAL_SPEC_REC *spec;
- spec = g_hash_table_lookup(py_sighash, name);
+ spec = py_signal_lookup(name);
if (!spec)
{
spec = g_new0(PY_SIGNAL_SPEC_REC, 1);
+ spec->is_var = name[strlen(name)-1] == ' '; /* trailing space means signal prefix */
spec->dynamic = 1;
spec->refcount = 0;
spec->name = g_strdup(name);
spec->arglist = g_strdup(arglist);
- spec->id = signal_get_uniq_id(name);
-
- g_hash_table_insert(py_sighash, spec->name, spec);
+
+ py_signal_add(spec);
}
else if (strcmp(spec->arglist, arglist) != 0)
return 0;
@@ -395,7 +464,7 @@ int pysignals_unregister(const char *name)
{
PY_SIGNAL_SPEC_REC *spec;
- spec = g_hash_table_lookup(py_sighash, name);
+ spec = py_signal_lookup(name);
if (!spec)
return 0;
@@ -408,14 +477,15 @@ void pysignals_init(void)
int i;
g_return_if_fail(py_sighash == NULL);
+ g_return_if_fail(py_sigtree == NULL);
- py_sighash = g_hash_table_new((GHashFunc)g_str_hash, (GCompareFunc)g_str_equal);
+ py_sigtree = g_tree_new((GCompareFunc)strcmp);
+ py_sighash = g_hash_table_new(g_str_hash, g_str_equal);
for (i = 0; i < py_sigmap_len(); i++)
{
py_sigmap[i].refcount = 1;
py_sigmap[i].dynamic = 0;
- py_sigmap[i].id = signal_get_uniq_id(py_sigmap[i].name);
py_signal_add(&py_sigmap[i]);
}
}
@@ -425,16 +495,22 @@ static int py_check_sig(char *key, PY_SIGNAL_SPEC_REC *value, void *data)
/* shouldn't need to deallocate any script recs -- all remaining at
this point should not be dynamic. non dynamic signals should have
no outstanding references */
- g_return_val_if_fail(value->dynamic == 0, TRUE);
- g_return_val_if_fail(value->refcount == 1, TRUE);
+ g_return_val_if_fail(value->dynamic == 0, FALSE);
+ g_return_val_if_fail(value->refcount == 1, FALSE);
- return TRUE;
+ return FALSE;
}
void pysignals_deinit(void)
{
g_return_if_fail(py_sighash != NULL);
- g_hash_table_foreach_remove(py_sighash, (GHRFunc)py_check_sig, NULL);
+ g_return_if_fail(py_sigtree != NULL);
+
+ g_tree_foreach(py_sigtree, (GTraverseFunc)py_check_sig, NULL);
+ g_hash_table_foreach_remove(py_sighash, (GHRFunc)py_check_sig, NULL);
+
+ g_tree_destroy(py_sigtree);
g_hash_table_destroy(py_sighash);
+ py_sigtree = NULL;
py_sighash = NULL;
}
diff --git a/pysignals.h b/pysignals.h
index f9ace24..a069482 100644
--- a/pysignals.h
+++ b/pysignals.h
@@ -8,8 +8,9 @@ struct _PY_SIGNAL_SPEC_REC;
typedef struct _PY_SIGNAL_REC
{
struct _PY_SIGNAL_SPEC_REC *signal;
- char *command; /* NULL if this is signal */
+ char *command; /* used for command and variable signal */
PyObject *handler;
+ int is_signal;
} PY_SIGNAL_REC;
PY_SIGNAL_REC *pysignals_command_bind(const char *cmd, PyObject *func,
diff --git a/sig2code.py b/sig2code.py
index 48cee71..4798e87 100644
--- a/sig2code.py
+++ b/sig2code.py
@@ -102,17 +102,22 @@ def main():
for ln in sys.stdin:
ln = ln.strip()
- m = re.match('^\"([^\"]+)\",(.*)$', ln)
+ m = re.match('^\"([^\"]+)\"[^,]*,(.*)$', ln)
if not m: continue
signal, args = m.groups()
if signal.startswith('script '): continue
+ if signal == 'command ': continue
argv = [transcode(a.strip()) for a in args.split(',')]
argv = ''.join(argv)
- print ' {"%s", "%s", 0, 0, 0},' % (signal, argv)
+ is_var = 0
+ if signal[-1] == ' ':
+ is_var = 1
+
+ print ' {"%s", "%s", 0, 0, %d},' % (signal, argv, is_var)
print " {NULL}"
print "};"