diff options
author | Christopher Davis <loafier@gmail.com> | 2006-06-24 03:10:40 +0000 |
---|---|---|
committer | Christopher Davis <loafier@gmail.com> | 2006-06-24 03:10:40 +0000 |
commit | d75ad2cebb61a3cb46570cecbc257693c528da0b (patch) | |
tree | 863b5ebfaca07d0c4ad140ce58e35d90916d78b7 | |
parent | 4d33c04f15e60e21a537edd635c9ac130312a3cb (diff) | |
download | irssi-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.py | 30 | ||||
-rw-r--r-- | pysigmap.h | 6 | ||||
-rw-r--r-- | pysignals.c | 132 | ||||
-rw-r--r-- | pysignals.h | 3 | ||||
-rw-r--r-- | sig2code.py | 9 |
5 files changed, 122 insertions, 58 deletions
@@ -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) @@ -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 "};" |