cvs: embed /php-irssi channel.c ext-irssi.c gensignals.php nick.c php-core.c server.c /php-irssi/examples command.php
| From: | Wez Furlong | Date: | Sun, 02 Feb 2003 21:05:26 +0000 |
| Subject: | cvs: embed /php-irssi channel.c ext-irssi.c gensignals.php nick.c php-core.c server.c /php-irssi/examples command.php | ||
| Groups: | php.embed.cvs | ||
| Request: | Send a blank email to php-embed-cvs+get-21@lists.php.net to get a copy of this message | ||
wez Sun Feb 2 16:05:26 2003 EDT
Added files:
/embed/php-irssi/examples command.php
Modified files:
/embed/php-irssi channel.c ext-irssi.c gensignals.php nick.c
php-core.c server.c
Log:
Implement command binding.
Add an example.
Allow NULL channel/server/nick objects when mapping to PHP-space.
Index: embed/php-irssi/channel.c diff -u embed/php-irssi/channel.c:1.4 embed/php-irssi/channel.c:1.5 --- embed/php-irssi/channel.c:1.4 Sun Feb 2 13:26:52 2003 +++ embed/php-irssi/channel.c Sun Feb 2 16:05:25 2003 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ | Author: Wez Furlong <wez@php.net> | +----------------------------------------------------------------------+ - $Id: channel.c,v 1.4 2003/02/02 18:26:52 wez Exp $ + $Id: channel.c,v 1.5 2003/02/02 21:05:25 wez Exp $ */ #include "php-irssi.h" #define PHP_IRSSI_PROTOS_ONLY @@ -27,6 +27,11 @@ { struct php_irssi_obj_ref *ref; + if (cr == NULL) { + ZVAL_NULL(obj); + return; + } + php_irssi_create_wrapper(&ref, "CHANNEL", obj TSRMLS_CC); if (ref) { ref->idents[IDX_CHANNEL] = estrdup(cr->name); Index: embed/php-irssi/ext-irssi.c diff -u embed/php-irssi/ext-irssi.c:1.13 embed/php-irssi/ext-irssi.c:1.14 --- embed/php-irssi/ext-irssi.c:1.13 Sun Feb 2 14:18:27 2003 +++ embed/php-irssi/ext-irssi.c Sun Feb 2 16:05:25 2003 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ | Author: Wez Furlong <wez@php.net> | +----------------------------------------------------------------------+ - $Id: ext-irssi.c,v 1.13 2003/02/02 19:18:27 wez Exp $ + $Id: ext-irssi.c,v 1.14 2003/02/02 21:05:25 wez Exp $ */ #include "php-irssi.h" #include "php-signals-list.h" /* generated by php during make */ @@ -29,7 +29,8 @@ struct sig_record { zval *handler; zval *arg; - enum { SIG_REC_TYPE_SIGNAL, SIG_REC_TYPE_TIMEOUT } type; + enum { SIG_REC_TYPE_SIGNAL, SIG_REC_TYPE_TIMEOUT, SIG_REC_TYPE_COMMAND} type; + struct php_irssi_signal_args *sigargs; union { struct { int signal_id; @@ -38,6 +39,9 @@ int tag; int one_shot; } timeout; + struct { + char *command; + } cmd; } v; }; @@ -60,7 +64,7 @@ /* Signals */ -static char *signal_hash_key(char *signame, zval *callback TSRMLS_DC) +static char *signal_hash_key(char *signame, zval *callback, char *prefix TSRMLS_DC) { char *key = NULL; @@ -77,17 +81,17 @@ convert_to_string_ex(func); if (Z_TYPE_PP(obj) == IS_OBJECT) { - spprintf(&key, 0, "%s@%d@%s", signame, (*obj)->value.obj.handle, Z_STRVAL_PP(func)); + spprintf(&key, 0, "%s@%s@%d@%s", prefix, signame, (*obj)->value.obj.handle, Z_STRVAL_PP(func)); return key; } /* class name */ convert_to_string_ex(obj); - spprintf(&key, 0, "%s@%s@%s", signame, Z_STRVAL_PP(obj), Z_STRVAL_PP(func)); + spprintf(&key, 0, "%s@%s@%s@%s", prefix, signame, Z_STRVAL_PP(obj), Z_STRVAL_PP(func)); return key; } if (Z_TYPE_P(callback) == IS_STRING) { - spprintf(&key, 0, "%s@%s", signame, Z_STRVAL_P(callback)); + spprintf(&key, 0, "%s@%s@%s", prefix, signame, Z_STRVAL_P(callback)); return key; } return NULL; @@ -148,64 +152,60 @@ const void *args[6]; int sigid = signal_get_emitted_id(); struct sig_record *rec = (struct sig_record*)signal_get_user_data(); - struct php_irssi_signal_args *sigargs; zval ***zargs; zval *val, *retval = NULL, *func_name = NULL; - int i, call_result; + int i, argc = 0, call_result; args[0] = p1; args[1] = p2; args[2] = p3; args[3] = p4; args[4] = p5; args[5] = p6; - /* first, find out which signal it is */ - sigargs = sigid_to_args(sigid); - - if (sigargs == NULL) - return; - func_name = rec->handler; - - zargs = emalloc(sigargs->argc * sizeof(zval **)); - - for (i = 0; i < sigargs->argc; i++) { - /* TODO: would be nice to replace this with php_irssi_C_to_PHP(), - * but we need to make some assumptions and optimizations here - * for the NICK records */ - - zargs[i] = emalloc(sizeof(zval *)); - MAKE_STD_ZVAL(*zargs[i]); - val = *zargs[i]; - switch(sigargs->argtypes[i]) { - case PIAT_STRING: - ZVAL_STRING(val, (char *)args[i], 1); - break; - case PIAT_SERVER: - php_irssi_export_SERVER(val, (SERVER_REC*)args[i] TSRMLS_CC); - break; - case PIAT_CHANNEL: - php_irssi_export_CHANNEL(val, (CHANNEL_REC*)args[i] TSRMLS_CC); - break; - case PIAT_NICK: - /* a NICK only ever follows a channel */ - php_irssi_export_NICK(val, (CHANNEL_REC*)args[i-1], (NICK_REC*)args[i] TSRMLS_CC); - break; - case PIAT_INT: - ZVAL_LONG(val, *(int *)args[i]); - break; - case PIAT_ULONG: - ZVAL_LONG(val, *(ulong *)args[i]); - break; - case PIAT_WI_ITEM: - php_irssi_export_WI_ITEM(val, (WI_ITEM_REC*)args[i] TSRMLS_CC); - break; - case PIAT_WINDOW: - php_irssi_export_WINDOW(val, (WINDOW_REC*)args[i] TSRMLS_CC); - break; - case PIAT_ARRAY_OF_STRING: - php_irssi_export_GList(val, (GSList*)args[i], PIAT_STRING TSRMLS_CC); - break; - default: - ZVAL_NULL(val); + if (rec->sigargs) { + zargs = emalloc(rec->sigargs->argc * sizeof(zval **)); + + for (i = 0; i < rec->sigargs->argc; i++) { + /* TODO: would be nice to replace this with php_irssi_C_to_PHP(), + * but we need to make some assumptions and optimizations here + * for the NICK records */ + + zargs[i] = emalloc(sizeof(zval *)); + MAKE_STD_ZVAL(*zargs[i]); + val = *zargs[i]; + argc++; + + switch(rec->sigargs->argtypes[i]) { + case PIAT_STRING: + ZVAL_STRING(val, (char *)args[i], 1); + break; + case PIAT_SERVER: + php_irssi_export_SERVER(val, (SERVER_REC*)args[i] TSRMLS_CC); + break; + case PIAT_CHANNEL: + php_irssi_export_CHANNEL(val, (CHANNEL_REC*)args[i] TSRMLS_CC); + break; + case PIAT_NICK: + /* a NICK only ever follows a channel */ + php_irssi_export_NICK(val, (CHANNEL_REC*)args[i-1], (NICK_REC*)args[i] TSRMLS_CC); + break; + case PIAT_INT: + ZVAL_LONG(val, *(int *)args[i]); + break; + case PIAT_ULONG: + ZVAL_LONG(val, *(ulong *)args[i]); + break; + case PIAT_WI_ITEM: + php_irssi_export_WI_ITEM(val, (WI_ITEM_REC*)args[i] TSRMLS_CC); + break; + case PIAT_WINDOW: + php_irssi_export_WINDOW(val, (WINDOW_REC*)args[i] TSRMLS_CC); + break; + case PIAT_ARRAY_OF_STRING: + php_irssi_export_GList(val, (GSList*)args[i], PIAT_STRING TSRMLS_CC); + break; + default: + ZVAL_NULL(val); + } } } @@ -214,7 +214,7 @@ NULL, func_name, &retval, - sigargs->argc, + argc, zargs, 0, NULL TSRMLS_CC); @@ -234,7 +234,7 @@ zval_ptr_dtor(&retval); /* release those zvals */ - for (i = 0; i < sigargs->argc; i++) { + for (i = 0; i < argc; i++) { zval_ptr_dtor(zargs[i]); efree(zargs[i]); } @@ -456,6 +456,64 @@ RETURN_BOOL(signal_is_stopped(sigid)); } +/* proto void irssi_command_bind(string command, mixed callback, [long priority, mixed cmdarg]) + Binds a function to a command. priority is one of the IRSSI_PRIORITY_XXX constants */ +PHP_FUNCTION(irssi_command_bind) +{ + zval *sigarg = NULL, *funcname, *tmp; + char *signame; + long signame_len; + long priority = SIGNAL_PRIORITY_DEFAULT; + int sigid; + struct sig_record *rec; + char *sighash = NULL; + struct php_irssi_signal_args *sigargs; + + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|lz!", + &signame, &signame_len, + &funcname, + &priority, + &sigarg + )) { + return; + } + + sigid = signal_get_uniq_id("default command"); + sigargs = sigid_to_args(sigid); + + sighash = signal_hash_key(signame, funcname, "command" TSRMLS_CC); + if (sighash == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to hash command handler"); + } + + rec = emalloc(sizeof(struct sig_record)); + rec->type = SIG_REC_TYPE_COMMAND; + rec->v.cmd.command = estrdup(signame); + + MAKE_STD_ZVAL(rec->handler); + *(rec->handler) = *funcname; + zval_copy_ctor(rec->handler); + + if (sigarg) { + MAKE_STD_ZVAL(rec->arg); + *(rec->arg) = *sigarg; + zval_copy_ctor(rec->arg); + } else { + rec->arg = NULL; + } + + rec->sigargs = sigargs; + + if (sighash) { + zend_hash_update(bound_signals, sighash, strlen(sighash)+1, &rec, sizeof(rec), NULL); + efree(sighash); + } else { + zend_hash_next_index_insert(bound_signals, &rec, sizeof(rec), NULL); + } + + command_bind_full(MODULE_NAME, priority, signame, -1, NULL, sig_func, rec); +} + /* proto void irssi_signal_add(string signalname, mixed callback, [long priority, mixed sigarg]) Binds a function to a signal. priority is one of the IRSSI_PRIORITY_XXX constants */ PHP_FUNCTION(irssi_signal_add) @@ -467,6 +525,7 @@ int sigid; struct sig_record *rec; char *sighash = NULL; + struct php_irssi_signal_args *sigargs; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|lz!", &signame, &signame_len, @@ -477,7 +536,10 @@ return; } - sighash = signal_hash_key(signame, funcname TSRMLS_CC); + sigid = signal_get_uniq_id(signame); + sigargs = sigid_to_args(sigid); + + sighash = signal_hash_key(signame, funcname, "signal" TSRMLS_CC); if (sighash == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to hash signal handler"); } @@ -485,8 +547,6 @@ rec = emalloc(sizeof(struct sig_record)); rec->type = SIG_REC_TYPE_SIGNAL; - sigid = signal_get_uniq_id(signame); - MAKE_STD_ZVAL(rec->handler); *(rec->handler) = *funcname; zval_copy_ctor(rec->handler); @@ -501,6 +561,8 @@ rec->arg = NULL; } + rec->sigargs = sigargs; + if (sighash) { zend_hash_update(bound_signals, sighash, strlen(sighash)+1, &rec, sizeof(rec), NULL); efree(sighash); @@ -606,7 +668,7 @@ return; } - sighash = signal_hash_key(signame, funcname TSRMLS_CC); + sighash = signal_hash_key(signame, funcname, "signal" TSRMLS_CC); if (sighash == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to hash signal handler"); RETURN_FALSE; @@ -624,14 +686,59 @@ RETURN_TRUE; } +PHP_FUNCTION(irssi_command_unbind) +{ + zval *sigarg = NULL, *funcname, *tmp; + char *signame; + long signame_len; + int sigid; + struct sig_record **rec; + char *sighash = NULL; + + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|z!", + &signame, &signame_len, + &funcname, + &sigarg + )) { + return; + } + + sighash = signal_hash_key(signame, funcname, "command" TSRMLS_CC); + if (sighash == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to hash command handler"); + RETURN_FALSE; + } + + if (FAILURE == zend_hash_find(bound_signals, sighash, strlen(sighash)+1, (void**)&rec)) { + /* Could not find this handler in our list */ + RETURN_FALSE; + } + + zend_hash_del(bound_signals, sighash, strlen(sighash)+1); + + efree(sighash); + + RETURN_TRUE; +} + + + + static void sig_rec_dtor(void *pDest) { struct sig_record *rec = *(struct sig_record **)pDest; - - if (rec->type == SIG_REC_TYPE_SIGNAL) { - signal_remove_id(rec->v.sig.signal_id, sig_func, rec); - } else { - g_source_remove(rec->v.timeout.tag); + + switch(rec->type) { + case SIG_REC_TYPE_SIGNAL: + signal_remove_id(rec->v.sig.signal_id, sig_func, rec); + break; + case SIG_REC_TYPE_COMMAND: + command_unbind_full(rec->v.cmd.command, sig_func, rec); + efree(rec->v.cmd.command); + break; + case SIG_REC_TYPE_TIMEOUT: + g_source_remove(rec->v.timeout.tag); + break; } if (rec->handler) { @@ -721,6 +828,8 @@ PHP_FE(irssi_timeout_remove, NULL) PHP_FE(irssi_window_get_active, NULL) PHP_FE(irssi_window_find_name, NULL) + PHP_FE(irssi_command_bind, NULL) + PHP_FE(irssi_command_unbind, NULL) NULL, NULL, NULL }; Index: embed/php-irssi/gensignals.php diff -u embed/php-irssi/gensignals.php:1.3 embed/php-irssi/gensignals.php:1.4 --- embed/php-irssi/gensignals.php:1.3 Thu Jan 30 07:12:20 2003 +++ embed/php-irssi/gensignals.php Sun Feb 2 16:05:26 2003 @@ -15,7 +15,7 @@ +----------------------------------------------------------------------+ | Author: Wez Furlong <wez@php.net> | +----------------------------------------------------------------------+ - $Id: gensignals.php,v 1.3 2003/01/30 12:12:20 wez Exp $ + $Id: gensignals.php,v 1.4 2003/02/02 21:05:26 wez Exp $ */ /* Generate signal information from the signals.txt file in the docs @@ -36,8 +36,8 @@ $signal = $matches[1]; $thing = $matches[2]; - if ($thing) - return; +// if ($thing) +// return; $args = explode(", ", $matches[3]); Index: embed/php-irssi/nick.c diff -u embed/php-irssi/nick.c:1.3 embed/php-irssi/nick.c:1.4 --- embed/php-irssi/nick.c:1.3 Thu Jan 30 10:42:47 2003 +++ embed/php-irssi/nick.c Sun Feb 2 16:05:26 2003 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ | Author: Wez Furlong <wez@php.net> | +----------------------------------------------------------------------+ - $Id: nick.c,v 1.3 2003/01/30 15:42:47 wez Exp $ + $Id: nick.c,v 1.4 2003/02/02 21:05:26 wez Exp $ */ #include "php-irssi.h" #define PHP_IRSSI_PROTOS_ONLY @@ -73,6 +73,11 @@ { struct php_irssi_obj_ref *ref; + if (nr == NULL) { + ZVAL_NULL(obj); + return; + } + php_irssi_create_wrapper(&ref, "NICK", obj TSRMLS_CC); if (ref) { ref->idents[IDX_SERVER] = estrdup(cr->server->tag); Index: embed/php-irssi/php-core.c diff -u embed/php-irssi/php-core.c:1.8 embed/php-irssi/php-core.c:1.9 --- embed/php-irssi/php-core.c:1.8 Sun Feb 2 14:18:27 2003 +++ embed/php-irssi/php-core.c Sun Feb 2 16:05:26 2003 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ | Author: Wez Furlong <wez@php.net> | +----------------------------------------------------------------------+ - $Id: php-core.c,v 1.8 2003/02/02 19:18:27 wez Exp $ + $Id: php-core.c,v 1.9 2003/02/02 21:05:26 wez Exp $ */ #define MODULE_NAME "php/core" #include "common.h" @@ -134,7 +134,7 @@ } /* Handler for "/php" command */ -static void cmd_php(const char *data, SERVER_REC *server, void *item) +static void cmd_php(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { if (*data == '\0') { data = "help"; Index: embed/php-irssi/server.c diff -u embed/php-irssi/server.c:1.3 embed/php-irssi/server.c:1.4 --- embed/php-irssi/server.c:1.3 Sat Feb 1 22:27:16 2003 +++ embed/php-irssi/server.c Sun Feb 2 16:05:26 2003 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ | Author: Wez Furlong <wez@php.net> | +----------------------------------------------------------------------+ - $Id: server.c,v 1.3 2003/02/02 03:27:16 wez Exp $ + $Id: server.c,v 1.4 2003/02/02 21:05:26 wez Exp $ */ #include "php-irssi.h" @@ -28,6 +28,11 @@ { struct php_irssi_obj_ref *ref; + if (srv == NULL) { + ZVAL_NULL(obj); + return; + } + php_irssi_create_wrapper(&ref, "SERVER", obj TSRMLS_CC); if (ref) { ref->idents[IDX_SERVER] = estrdup(srv->tag); Index: embed/php-irssi/examples/command.php +++ embed/php-irssi/examples/command.php <?php /* $Id: command.php,v 1.1 2003/02/02 21:05:26 wez Exp $ * * Commands. * * This sample demonstrates how to map "/foo bar baz" as a valid * irssi command and have your own PHP code handle it. * * Just like any callback made from irssi, you should not hang around for * too long; long delays can cause irssi to drop network connections to * your chatnets. */ /* $command_text is the text that the user typed after the command. * so, for "/foo bar baz", $command_text will be "bar baz". * $server is the server object associated with the window in which * the user typed the command. It may be NULL if there is no server. * $windowitem is the associated windowitem. It may be NULL, just * like the server. Use get_class($windowitem) to determine which * item it actually represents - it will typically be a channel object. */ function the_foo_command($command_text, $server, $windowitem) { echo "You typed $command_text"; } irssi_command_bind("foo", "the_foo_command"); /* Load this script and then type "/foo bar baz" at the irssi prompt */ ?>
Index: embed/php-irssi/channel.c diff -u embed/php-irssi/channel.c:1.4 embed/php-irssi/channel.c:1.5 --- embed/php-irssi/channel.c:1.4 Sun Feb 2 13:26:52 2003 +++ embed/php-irssi/channel.c Sun Feb 2 16:05:25 2003 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ | Author: Wez Furlong <wez@php.net> | +----------------------------------------------------------------------+ - $Id: channel.c,v 1.4 2003/02/02 18:26:52 wez Exp $ + $Id: channel.c,v 1.5 2003/02/02 21:05:25 wez Exp $ */ #include "php-irssi.h" #define PHP_IRSSI_PROTOS_ONLY @@ -27,6 +27,11 @@ { struct php_irssi_obj_ref *ref; + if (cr == NULL) { + ZVAL_NULL(obj); + return; + } + php_irssi_create_wrapper(&ref, "CHANNEL", obj TSRMLS_CC); if (ref) { ref->idents[IDX_CHANNEL] = estrdup(cr->name); Index: embed/php-irssi/ext-irssi.c diff -u embed/php-irssi/ext-irssi.c:1.13 embed/php-irssi/ext-irssi.c:1.14 --- embed/php-irssi/ext-irssi.c:1.13 Sun Feb 2 14:18:27 2003 +++ embed/php-irssi/ext-irssi.c Sun Feb 2 16:05:25 2003 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ | Author: Wez Furlong <wez@php.net> | +----------------------------------------------------------------------+ - $Id: ext-irssi.c,v 1.13 2003/02/02 19:18:27 wez Exp $ + $Id: ext-irssi.c,v 1.14 2003/02/02 21:05:25 wez Exp $ */ #include "php-irssi.h" #include "php-signals-list.h" /* generated by php during make */ @@ -29,7 +29,8 @@ struct sig_record { zval *handler; zval *arg; - enum { SIG_REC_TYPE_SIGNAL, SIG_REC_TYPE_TIMEOUT } type; + enum { SIG_REC_TYPE_SIGNAL, SIG_REC_TYPE_TIMEOUT, SIG_REC_TYPE_COMMAND} type; + struct php_irssi_signal_args *sigargs; union { struct { int signal_id; @@ -38,6 +39,9 @@ int tag; int one_shot; } timeout; + struct { + char *command; + } cmd; } v; }; @@ -60,7 +64,7 @@ /* Signals */ -static char *signal_hash_key(char *signame, zval *callback TSRMLS_DC) +static char *signal_hash_key(char *signame, zval *callback, char *prefix TSRMLS_DC) { char *key = NULL; @@ -77,17 +81,17 @@ convert_to_string_ex(func); if (Z_TYPE_PP(obj) == IS_OBJECT) { - spprintf(&key, 0, "%s@%d@%s", signame, (*obj)->value.obj.handle, Z_STRVAL_PP(func)); + spprintf(&key, 0, "%s@%s@%d@%s", prefix, signame, (*obj)->value.obj.handle, Z_STRVAL_PP(func)); return key; } /* class name */ convert_to_string_ex(obj); - spprintf(&key, 0, "%s@%s@%s", signame, Z_STRVAL_PP(obj), Z_STRVAL_PP(func)); + spprintf(&key, 0, "%s@%s@%s@%s", prefix, signame, Z_STRVAL_PP(obj), Z_STRVAL_PP(func)); return key; } if (Z_TYPE_P(callback) == IS_STRING) { - spprintf(&key, 0, "%s@%s", signame, Z_STRVAL_P(callback)); + spprintf(&key, 0, "%s@%s@%s", prefix, signame, Z_STRVAL_P(callback)); return key; } return NULL; @@ -148,64 +152,60 @@ const void *args[6]; int sigid = signal_get_emitted_id(); struct sig_record *rec = (struct sig_record*)signal_get_user_data(); - struct php_irssi_signal_args *sigargs; zval ***zargs; zval *val, *retval = NULL, *func_name = NULL; - int i, call_result; + int i, argc = 0, call_result; args[0] = p1; args[1] = p2; args[2] = p3; args[3] = p4; args[4] = p5; args[5] = p6; - /* first, find out which signal it is */ - sigargs = sigid_to_args(sigid); - - if (sigargs == NULL) - return; - func_name = rec->handler; - - zargs = emalloc(sigargs->argc * sizeof(zval **)); - - for (i = 0; i < sigargs->argc; i++) { - /* TODO: would be nice to replace this with php_irssi_C_to_PHP(), - * but we need to make some assumptions and optimizations here - * for the NICK records */ - - zargs[i] = emalloc(sizeof(zval *)); - MAKE_STD_ZVAL(*zargs[i]); - val = *zargs[i]; - switch(sigargs->argtypes[i]) { - case PIAT_STRING: - ZVAL_STRING(val, (char *)args[i], 1); - break; - case PIAT_SERVER: - php_irssi_export_SERVER(val, (SERVER_REC*)args[i] TSRMLS_CC); - break; - case PIAT_CHANNEL: - php_irssi_export_CHANNEL(val, (CHANNEL_REC*)args[i] TSRMLS_CC); - break; - case PIAT_NICK: - /* a NICK only ever follows a channel */ - php_irssi_export_NICK(val, (CHANNEL_REC*)args[i-1], (NICK_REC*)args[i] TSRMLS_CC); - break; - case PIAT_INT: - ZVAL_LONG(val, *(int *)args[i]); - break; - case PIAT_ULONG: - ZVAL_LONG(val, *(ulong *)args[i]); - break; - case PIAT_WI_ITEM: - php_irssi_export_WI_ITEM(val, (WI_ITEM_REC*)args[i] TSRMLS_CC); - break; - case PIAT_WINDOW: - php_irssi_export_WINDOW(val, (WINDOW_REC*)args[i] TSRMLS_CC); - break; - case PIAT_ARRAY_OF_STRING: - php_irssi_export_GList(val, (GSList*)args[i], PIAT_STRING TSRMLS_CC); - break; - default: - ZVAL_NULL(val); + if (rec->sigargs) { + zargs = emalloc(rec->sigargs->argc * sizeof(zval **)); + + for (i = 0; i < rec->sigargs->argc; i++) { + /* TODO: would be nice to replace this with php_irssi_C_to_PHP(), + * but we need to make some assumptions and optimizations here + * for the NICK records */ + + zargs[i] = emalloc(sizeof(zval *)); + MAKE_STD_ZVAL(*zargs[i]); + val = *zargs[i]; + argc++; + + switch(rec->sigargs->argtypes[i]) { + case PIAT_STRING: + ZVAL_STRING(val, (char *)args[i], 1); + break; + case PIAT_SERVER: + php_irssi_export_SERVER(val, (SERVER_REC*)args[i] TSRMLS_CC); + break; + case PIAT_CHANNEL: + php_irssi_export_CHANNEL(val, (CHANNEL_REC*)args[i] TSRMLS_CC); + break; + case PIAT_NICK: + /* a NICK only ever follows a channel */ + php_irssi_export_NICK(val, (CHANNEL_REC*)args[i-1], (NICK_REC*)args[i] TSRMLS_CC); + break; + case PIAT_INT: + ZVAL_LONG(val, *(int *)args[i]); + break; + case PIAT_ULONG: + ZVAL_LONG(val, *(ulong *)args[i]); + break; + case PIAT_WI_ITEM: + php_irssi_export_WI_ITEM(val, (WI_ITEM_REC*)args[i] TSRMLS_CC); + break; + case PIAT_WINDOW: + php_irssi_export_WINDOW(val, (WINDOW_REC*)args[i] TSRMLS_CC); + break; + case PIAT_ARRAY_OF_STRING: + php_irssi_export_GList(val, (GSList*)args[i], PIAT_STRING TSRMLS_CC); + break; + default: + ZVAL_NULL(val); + } } } @@ -214,7 +214,7 @@ NULL, func_name, &retval, - sigargs->argc, + argc, zargs, 0, NULL TSRMLS_CC); @@ -234,7 +234,7 @@ zval_ptr_dtor(&retval); /* release those zvals */ - for (i = 0; i < sigargs->argc; i++) { + for (i = 0; i < argc; i++) { zval_ptr_dtor(zargs[i]); efree(zargs[i]); } @@ -456,6 +456,64 @@ RETURN_BOOL(signal_is_stopped(sigid)); } +/* proto void irssi_command_bind(string command, mixed callback, [long priority, mixed cmdarg]) + Binds a function to a command. priority is one of the IRSSI_PRIORITY_XXX constants */ +PHP_FUNCTION(irssi_command_bind) +{ + zval *sigarg = NULL, *funcname, *tmp; + char *signame; + long signame_len; + long priority = SIGNAL_PRIORITY_DEFAULT; + int sigid; + struct sig_record *rec; + char *sighash = NULL; + struct php_irssi_signal_args *sigargs; + + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|lz!", + &signame, &signame_len, + &funcname, + &priority, + &sigarg + )) { + return; + } + + sigid = signal_get_uniq_id("default command"); + sigargs = sigid_to_args(sigid); + + sighash = signal_hash_key(signame, funcname, "command" TSRMLS_CC); + if (sighash == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to hash command handler"); + } + + rec = emalloc(sizeof(struct sig_record)); + rec->type = SIG_REC_TYPE_COMMAND; + rec->v.cmd.command = estrdup(signame); + + MAKE_STD_ZVAL(rec->handler); + *(rec->handler) = *funcname; + zval_copy_ctor(rec->handler); + + if (sigarg) { + MAKE_STD_ZVAL(rec->arg); + *(rec->arg) = *sigarg; + zval_copy_ctor(rec->arg); + } else { + rec->arg = NULL; + } + + rec->sigargs = sigargs; + + if (sighash) { + zend_hash_update(bound_signals, sighash, strlen(sighash)+1, &rec, sizeof(rec), NULL); + efree(sighash); + } else { + zend_hash_next_index_insert(bound_signals, &rec, sizeof(rec), NULL); + } + + command_bind_full(MODULE_NAME, priority, signame, -1, NULL, sig_func, rec); +} + /* proto void irssi_signal_add(string signalname, mixed callback, [long priority, mixed sigarg]) Binds a function to a signal. priority is one of the IRSSI_PRIORITY_XXX constants */ PHP_FUNCTION(irssi_signal_add) @@ -467,6 +525,7 @@ int sigid; struct sig_record *rec; char *sighash = NULL; + struct php_irssi_signal_args *sigargs; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|lz!", &signame, &signame_len, @@ -477,7 +536,10 @@ return; } - sighash = signal_hash_key(signame, funcname TSRMLS_CC); + sigid = signal_get_uniq_id(signame); + sigargs = sigid_to_args(sigid); + + sighash = signal_hash_key(signame, funcname, "signal" TSRMLS_CC); if (sighash == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to hash signal handler"); } @@ -485,8 +547,6 @@ rec = emalloc(sizeof(struct sig_record)); rec->type = SIG_REC_TYPE_SIGNAL; - sigid = signal_get_uniq_id(signame); - MAKE_STD_ZVAL(rec->handler); *(rec->handler) = *funcname; zval_copy_ctor(rec->handler); @@ -501,6 +561,8 @@ rec->arg = NULL; } + rec->sigargs = sigargs; + if (sighash) { zend_hash_update(bound_signals, sighash, strlen(sighash)+1, &rec, sizeof(rec), NULL); efree(sighash); @@ -606,7 +668,7 @@ return; } - sighash = signal_hash_key(signame, funcname TSRMLS_CC); + sighash = signal_hash_key(signame, funcname, "signal" TSRMLS_CC); if (sighash == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to hash signal handler"); RETURN_FALSE; @@ -624,14 +686,59 @@ RETURN_TRUE; } +PHP_FUNCTION(irssi_command_unbind) +{ + zval *sigarg = NULL, *funcname, *tmp; + char *signame; + long signame_len; + int sigid; + struct sig_record **rec; + char *sighash = NULL; + + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|z!", + &signame, &signame_len, + &funcname, + &sigarg + )) { + return; + } + + sighash = signal_hash_key(signame, funcname, "command" TSRMLS_CC); + if (sighash == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to hash command handler"); + RETURN_FALSE; + } + + if (FAILURE == zend_hash_find(bound_signals, sighash, strlen(sighash)+1, (void**)&rec)) { + /* Could not find this handler in our list */ + RETURN_FALSE; + } + + zend_hash_del(bound_signals, sighash, strlen(sighash)+1); + + efree(sighash); + + RETURN_TRUE; +} + + + + static void sig_rec_dtor(void *pDest) { struct sig_record *rec = *(struct sig_record **)pDest; - - if (rec->type == SIG_REC_TYPE_SIGNAL) { - signal_remove_id(rec->v.sig.signal_id, sig_func, rec); - } else { - g_source_remove(rec->v.timeout.tag); + + switch(rec->type) { + case SIG_REC_TYPE_SIGNAL: + signal_remove_id(rec->v.sig.signal_id, sig_func, rec); + break; + case SIG_REC_TYPE_COMMAND: + command_unbind_full(rec->v.cmd.command, sig_func, rec); + efree(rec->v.cmd.command); + break; + case SIG_REC_TYPE_TIMEOUT: + g_source_remove(rec->v.timeout.tag); + break; } if (rec->handler) { @@ -721,6 +828,8 @@ PHP_FE(irssi_timeout_remove, NULL) PHP_FE(irssi_window_get_active, NULL) PHP_FE(irssi_window_find_name, NULL) + PHP_FE(irssi_command_bind, NULL) + PHP_FE(irssi_command_unbind, NULL) NULL, NULL, NULL }; Index: embed/php-irssi/gensignals.php diff -u embed/php-irssi/gensignals.php:1.3 embed/php-irssi/gensignals.php:1.4 --- embed/php-irssi/gensignals.php:1.3 Thu Jan 30 07:12:20 2003 +++ embed/php-irssi/gensignals.php Sun Feb 2 16:05:26 2003 @@ -15,7 +15,7 @@ +----------------------------------------------------------------------+ | Author: Wez Furlong <wez@php.net> | +----------------------------------------------------------------------+ - $Id: gensignals.php,v 1.3 2003/01/30 12:12:20 wez Exp $ + $Id: gensignals.php,v 1.4 2003/02/02 21:05:26 wez Exp $ */ /* Generate signal information from the signals.txt file in the docs @@ -36,8 +36,8 @@ $signal = $matches[1]; $thing = $matches[2]; - if ($thing) - return; +// if ($thing) +// return; $args = explode(", ", $matches[3]); Index: embed/php-irssi/nick.c diff -u embed/php-irssi/nick.c:1.3 embed/php-irssi/nick.c:1.4 --- embed/php-irssi/nick.c:1.3 Thu Jan 30 10:42:47 2003 +++ embed/php-irssi/nick.c Sun Feb 2 16:05:26 2003 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ | Author: Wez Furlong <wez@php.net> | +----------------------------------------------------------------------+ - $Id: nick.c,v 1.3 2003/01/30 15:42:47 wez Exp $ + $Id: nick.c,v 1.4 2003/02/02 21:05:26 wez Exp $ */ #include "php-irssi.h" #define PHP_IRSSI_PROTOS_ONLY @@ -73,6 +73,11 @@ { struct php_irssi_obj_ref *ref; + if (nr == NULL) { + ZVAL_NULL(obj); + return; + } + php_irssi_create_wrapper(&ref, "NICK", obj TSRMLS_CC); if (ref) { ref->idents[IDX_SERVER] = estrdup(cr->server->tag); Index: embed/php-irssi/php-core.c diff -u embed/php-irssi/php-core.c:1.8 embed/php-irssi/php-core.c:1.9 --- embed/php-irssi/php-core.c:1.8 Sun Feb 2 14:18:27 2003 +++ embed/php-irssi/php-core.c Sun Feb 2 16:05:26 2003 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ | Author: Wez Furlong <wez@php.net> | +----------------------------------------------------------------------+ - $Id: php-core.c,v 1.8 2003/02/02 19:18:27 wez Exp $ + $Id: php-core.c,v 1.9 2003/02/02 21:05:26 wez Exp $ */ #define MODULE_NAME "php/core" #include "common.h" @@ -134,7 +134,7 @@ } /* Handler for "/php" command */ -static void cmd_php(const char *data, SERVER_REC *server, void *item) +static void cmd_php(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { if (*data == '\0') { data = "help"; Index: embed/php-irssi/server.c diff -u embed/php-irssi/server.c:1.3 embed/php-irssi/server.c:1.4 --- embed/php-irssi/server.c:1.3 Sat Feb 1 22:27:16 2003 +++ embed/php-irssi/server.c Sun Feb 2 16:05:26 2003 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ | Author: Wez Furlong <wez@php.net> | +----------------------------------------------------------------------+ - $Id: server.c,v 1.3 2003/02/02 03:27:16 wez Exp $ + $Id: server.c,v 1.4 2003/02/02 21:05:26 wez Exp $ */ #include "php-irssi.h" @@ -28,6 +28,11 @@ { struct php_irssi_obj_ref *ref; + if (srv == NULL) { + ZVAL_NULL(obj); + return; + } + php_irssi_create_wrapper(&ref, "SERVER", obj TSRMLS_CC); if (ref) { ref->idents[IDX_SERVER] = estrdup(srv->tag); Index: embed/php-irssi/examples/command.php +++ embed/php-irssi/examples/command.php <?php /* $Id: command.php,v 1.1 2003/02/02 21:05:26 wez Exp $ * * Commands. * * This sample demonstrates how to map "/foo bar baz" as a valid * irssi command and have your own PHP code handle it. * * Just like any callback made from irssi, you should not hang around for * too long; long delays can cause irssi to drop network connections to * your chatnets. */ /* $command_text is the text that the user typed after the command. * so, for "/foo bar baz", $command_text will be "bar baz". * $server is the server object associated with the window in which * the user typed the command. It may be NULL if there is no server. * $windowitem is the associated windowitem. It may be NULL, just * like the server. Use get_class($windowitem) to determine which * item it actually represents - it will typically be a channel object. */ function the_foo_command($command_text, $server, $windowitem) { echo "You typed $command_text"; } irssi_command_bind("foo", "the_foo_command"); /* Load this script and then type "/foo bar baz" at the irssi prompt */ ?>