cvs: embed /php-irssi channel.c ext-irssi.c gensignals.php nick.c php-core.c server.c /php-irssi/examples command.php

[email protected] ("Wez Furlong") Sun, 02 Feb 2003 21:05:26 -0000
Newsgroups php.embed.cvs
Message-ID <cvswez1044219926@cvsserver>
--wez1044219926
Content-Type: text/plain

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.
  
  
--wez1044219926
Content-Type: text/plain
Content-Disposition: attachment; filename="wez-20030202160526.txt"

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 <[email protected]>                                    |
   +----------------------------------------------------------------------+
-  $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 <[email protected]>                                    |
   +----------------------------------------------------------------------+
-  $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 <[email protected]>                                    |
   +----------------------------------------------------------------------+
-  $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 <[email protected]>                                    |
   +----------------------------------------------------------------------+
-  $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 <[email protected]>                                    |
   +----------------------------------------------------------------------+
-  $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 <[email protected]>                                    |
   +----------------------------------------------------------------------+
-  $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 */

?>

--wez1044219926--