rest of the ~rewrite?

git-svn-id: http://svn.irssi.org/repos/irssi/trunk@172 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2000-04-26 08:10:09 +00:00 committed by cras
commit d29ca0b107
32 changed files with 2049 additions and 1536 deletions

View file

@ -1,13 +1,13 @@
if BUILD_TEXTUI
TEXTUI=gui-text
TEXTUI=fe-text
endif
if BUILD_GNOMEUI
GNOMEUI=gui-gnome
GNOMEUI=fe-gnome
endif
if BUILD_IRSSIBOT
BOTUI=gui-none
BOTUI=fe-none
endif
noinst_HEADERS = \
@ -17,4 +17,4 @@ noinst_HEADERS = \
irssi-plugin.h \
irssi-plugin-gui.h
SUBDIRS = lib-popt lib-config irc-base irc-extra ui-common $(GNOMEUI) $(TEXTUI) $(BOTUI)
SUBDIRS = lib-popt lib-config core irc fe-common perl $(GNOMEUI) $(TEXTUI) $(BOTUI)

View file

@ -13,9 +13,6 @@
/* How often to check if there's anyone to be unbanned in knockout list */
#define KNOCKOUT_TIMECHECK 10000
/* How often to check users in notify list */
#define NOTIFY_TIMECHECK 30000
/* How often to check for gone status of nick */
#define MAX_GONE_REFRESH_TIME 300

View file

@ -35,7 +35,7 @@
#include <glib.h>
#include <gmodule.h>
#include "irc-base/memdebug.h"
#include "core/memdebug.h"
#include "nls.h"
#define g_free_not_null(a) \

View file

@ -40,11 +40,10 @@ CONFIG_NODE *config_node_find(CONFIG_NODE *node, const char *key)
/* find the section from node - if not found create it unless new_type is -1.
you can also specify in new_type if it's NODE_TYPE_LIST or NODE_TYPE_BLOCK */
CONFIG_NODE *config_node_section(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, int new_type)
CONFIG_NODE *config_node_section(CONFIG_NODE *parent, const char *key, int new_type)
{
CONFIG_NODE *node;
g_return_val_if_fail(rec != NULL, NULL);
g_return_val_if_fail(parent != NULL, NULL);
g_return_val_if_fail(is_node_list(parent), NULL);
@ -91,7 +90,7 @@ CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int crea
is_list = **tmp == '(';
if (create) new_type = is_list ? NODE_TYPE_LIST : NODE_TYPE_BLOCK;
node = config_node_section(rec, node, *tmp + is_list, new_type);
node = config_node_section(node, *tmp + is_list, new_type);
if (node == NULL) return NULL;
}
g_strfreev(list);
@ -252,3 +251,34 @@ int config_node_get_keyvalue(CONFIG_NODE *node, const char *key, const char *val
return -1;
}
/* Return all values from from the list `node' in a g_strsplit() array */
char **config_node_get_list(CONFIG_NODE *node)
{
GString *values;
GSList *tmp;
char **ret;
g_return_val_if_fail(node != NULL, NULL);
g_return_val_if_fail(is_node_list(node), NULL);
/* put values to string */
values = g_string_new(NULL);
for (tmp = node->value; tmp != NULL; tmp = tmp->next) {
node = tmp->data;
if (node->type == NODE_TYPE_VALUE)
g_string_sprintfa(values, "%s ", (char *) node->value);
}
/* split the values to **str array */
if (values->len == 0)
ret = NULL;
else {
g_string_truncate(values, values->len-1);
ret = g_strsplit(values->str, " ", -1);
}
g_string_free(values, TRUE);
return ret;
}

View file

@ -108,13 +108,17 @@ int config_set_bool(CONFIG_REC *rec, const char *section, const char *key, int v
CONFIG_NODE *config_node_find(CONFIG_NODE *node, const char *key);
/* Find the section from node - if not found create it unless new_type is -1.
You can also specify in new_type if it's NODE_TYPE_LIST or NODE_TYPE_BLOCK */
CONFIG_NODE *config_node_section(CONFIG_REC *rec, CONFIG_NODE *parent, const char *key, int new_type);
CONFIG_NODE *config_node_section(CONFIG_NODE *parent, const char *key, int new_type);
/* Find the section with the whole path.
Create the path if necessary `create' is TRUE. */
CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int create);
/* Get the value of keys `key' and `key_value' and put them to
`ret_key' and `ret_value'. Returns -1 if not found. */
int config_node_get_keyvalue(CONFIG_NODE *node, const char *key, const char *value_key, char **ret_key, char **ret_value);
/* Return all values from from the list `node' in a g_strsplit() array */
char **config_node_get_list(CONFIG_NODE *node);
/* Add all values in `array' to `node' */
void config_node_add_list(CONFIG_NODE *node, char **array);
char *config_node_get_str(CONFIG_NODE *parent, const char *key, const char *def);
int config_node_get_int(CONFIG_NODE *parent, const char *key, int def);
@ -124,13 +128,15 @@ void config_node_set_str(CONFIG_NODE *parent, const char *key, const char *value
void config_node_set_int(CONFIG_NODE *parent, const char *key, int value);
void config_node_set_bool(CONFIG_NODE *parent, const char *key, int value);
/* add/change the value of the `key' */
/* Add/change the value of the `key' */
void config_node_set_str(CONFIG_NODE *parent, const char *key, const char *value);
/* remove one node from block/list.
/* Remove one node from block/list.
..set_str() with value = NULL does the same. */
void config_node_remove(CONFIG_NODE *parent, CONFIG_NODE *node);
/* Remove n'th node from a list */
void config_node_list_remove(CONFIG_NODE *node, int index);
/* clear the entire configuration */
/* Clear the entire configuration */
void config_nodes_remove_all(CONFIG_REC *rec);
#endif

View file

@ -62,7 +62,7 @@ static void config_parse_get_token(GScanner *scanner, CONFIG_NODE *node)
#undef g_strdup_printf /* This is free'd by GLib itself */
scanner->value.v_string = g_strdup_printf("%lu", scanner->value.v_int);
#ifdef MEM_DEBUG
#define g_strdup_printf ig_strdup_printf
#define g_strdup_printf(a, b...) ig_strdup_printf(__FILE__, __LINE__, a, ##b)
#endif
}
break;
@ -127,8 +127,10 @@ static int config_parse_symbol(CONFIG_REC *rec, CONFIG_NODE *node)
key = g_strdup(rec->scanner->value.v_string);
config_parse_get_token(rec->scanner, node);
if (rec->scanner->token != '=')
if (rec->scanner->token != '=') {
g_free(key);
return '=';
}
config_parse_get_token(rec->scanner, node);
}
@ -155,7 +157,7 @@ static int config_parse_symbol(CONFIG_REC *rec, CONFIG_NODE *node)
if (key == NULL && node->type != NODE_TYPE_LIST)
return G_TOKEN_ERROR;
newnode = config_node_section(rec, node, key, NODE_TYPE_BLOCK);
newnode = config_node_section(node, key, NODE_TYPE_BLOCK);
config_parse_loop(rec, newnode, '}');
g_free_not_null(key);
@ -170,7 +172,7 @@ static int config_parse_symbol(CONFIG_REC *rec, CONFIG_NODE *node)
/* list */
if (key == NULL)
return G_TOKEN_ERROR;
newnode = config_node_section(rec, node, key, NODE_TYPE_LIST);
newnode = config_node_section(node, key, NODE_TYPE_LIST);
config_parse_loop(rec, newnode, ')');
g_free_not_null(key);
@ -197,17 +199,18 @@ static void config_parse_loop(CONFIG_REC *rec, CONFIG_NODE *node, int expect)
g_return_if_fail(rec != NULL);
g_return_if_fail(node != NULL);
do {
for (;;) {
config_parse_peek_token(rec->scanner, node);
if (rec->scanner->next_token == expect ||
rec->scanner->next_token == G_TOKEN_EOF) break;
expected_token = config_parse_symbol(rec, node);
if (expected_token != G_TOKEN_NONE) {
if (expected_token == G_TOKEN_ERROR)
expected_token = G_TOKEN_NONE;
g_scanner_unexp_token(rec->scanner, expected_token, NULL, "symbol", NULL, NULL, TRUE);
}
config_parse_peek_token(rec->scanner, node);
} while (rec->scanner->next_token != expect &&
rec->scanner->next_token != G_TOKEN_EOF);
}
}
static void config_parse_error_func(GScanner *scanner, char *message, int is_error)

View file

@ -43,6 +43,22 @@ void config_node_remove(CONFIG_NODE *parent, CONFIG_NODE *node)
g_free(node);
}
/* Remove n'th node from a list */
void config_node_list_remove(CONFIG_NODE *node, int index)
{
GSList *tmp;
g_return_if_fail(node != NULL);
g_return_if_fail(is_node_list(node));
for (tmp = node->value; tmp != NULL; tmp = tmp->next, index--) {
if (index == 0) {
config_node_remove(node, tmp->data);
break;
}
}
}
void config_nodes_remove_all(CONFIG_REC *rec)
{
g_return_if_fail(rec != NULL);
@ -120,3 +136,12 @@ int config_set_bool(CONFIG_REC *rec, const char *section, const char *key, int v
{
return config_set_str(rec, section, key, value ? "yes" : "no");
}
/* Add all values in `array' to `node' */
void config_node_add_list(CONFIG_NODE *node, char **array)
{
char **tmp;
for (tmp = array; *tmp != NULL; tmp++)
config_node_set_str(node, NULL, *tmp);
}

View file

@ -76,7 +76,7 @@ static int config_has_specials(const char *text)
g_return_val_if_fail(text != NULL, FALSE);
while (*text != '\0') {
if ((unsigned char) *text <= 32 || *text == '"' || *text == '\\')
if (!isalnum((int) *text))
return TRUE;
text++;
}
@ -162,7 +162,7 @@ static int config_write_node(CONFIG_REC *rec, CONFIG_NODE *node, int line_feeds)
case NODE_TYPE_BLOCK:
/* key = { */
if (node->key != NULL) {
if (config_write_str(rec, node->key) == -1 ||
if (config_write_word(rec, node->key, FALSE) == -1 ||
config_write_str(rec, " = ") == -1)
return -1;
}
@ -182,7 +182,7 @@ static int config_write_node(CONFIG_REC *rec, CONFIG_NODE *node, int line_feeds)
case NODE_TYPE_LIST:
/* key = ( */
if (node->key != NULL) {
if (config_write_str(rec, node->key) == -1 ||
if (config_write_word(rec, node->key, FALSE) == -1 ||
config_write_str(rec, " = ") == -1)
return -1;
}
@ -327,7 +327,6 @@ int config_write(CONFIG_REC *rec, const char *fname, int create_mode)
config_error(rec, errno == 0 ? "bug" : g_strerror(errno));
return -1;
}
write(rec->handle, "\n", 1);
close(rec->handle);
rec->handle = -1;

30
src/perl/Makefile.am Normal file
View file

@ -0,0 +1,30 @@
noinst_LTLIBRARIES = libperl.la
libperl_la_DEPENDENCIES = perl-signals.h
INCLUDES = $(GLIB_CFLAGS) \
-DPLUGINSDIR=\""$(libdir)/irssi/plugins"\" \
-DSCRIPTDIR=\""$(libdir)/irssi/scripts"\" \
$(PERL_CFLAGS) \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/core
libperl_la_SOURCES = \
irssi-perl.c \
xsinit.c
perl-signals.h: $(top_srcdir)/docs/signals.txt $(srcdir)/get-signals.pl
cat $(top_srcdir)/docs/signals.txt | $(perlpath) $(srcdir)/get-signals.pl > perl-signals.h
EXTRA_DIST = \
get-signals.pl \
xs/Irssi.xs \
xs/Irssi.pm \
xs/Makefile.PL.in \
xs/typemap
all-local:
cd xs && if [ ! -f Makefile ]; then $(perlpath) Makefile.PL; fi && $(MAKE) && cd ..
install-exec-local:
cd xs && make install && cd ..

38
src/perl/get-signals.pl Executable file
View file

@ -0,0 +1,38 @@
#!/usr/bin/perl
print "static PERL_SIGNAL_ARGS_REC perl_signal_args[] =\n{\n";
while (<STDIN>) {
chomp;
last if (/UI common/);
next if (!/^ "([^"]*)"(<.*>)?,\s*(.*)/);
next if (/\.\.\./);
next if (/\(/);
$signal = $1;
$_ = $3;
s/char \*[^,]*/string/g;
s/ulong \*[^,]*/ulongptr/g;
s/int[^,]*/int/g;
s/GSList of (\w+)s/gslist_\1/g;
s/SERVER_REC \*[^,]*/Irssi::Server/g;
s/RECONNECT_REC \*[^,]*/Irssi::Reconnect/g;
s/CHANNEL_REC \*[^,]*/Irssi::Channel/g;
s/COMMAND_REC \*[^,]*/Irssi::Command/g;
s/NICK_REC \*[^,]*/Irssi::Nick/g;
s/BAN_REC \*[^,]*/Irssi::Ban/g;
s/NETSPLIT_REC \*[^,]*/Irssi::Netsplit/g;
s/DCC_REC \*[^,]*/Irssi::Dcc/g;
s/LOG_REC \*[^,]*/Irssi::Log/g;
s/LOG_ITEM_REC \*[^,]*/Irssi::Logitem/g;
s/PLUGIN_REC \*[^,]*/Irssi::Plugin/g;
s/AUTOIGNORE_REC \*[^,]*/Irssi::Autoignore/g;
s/([\w:]+)(,|$)/"\1"\2/g;
print " { -1, \"$signal\", { $_, NULL } },\n";
}
print "\n { -1, NULL }\n};\n";

529
src/perl/irssi-perl.c Normal file
View file

@ -0,0 +1,529 @@
/*
perl.c : irssi
Copyright (C) 1999 Timo Sirainen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <EXTERN.h>
#ifndef _SEM_SEMUN_UNDEFINED
#define HAS_UNION_SEMUN
#endif
#include <perl.h>
#undef _
#undef PACKAGE
#include "module.h"
#include "modules.h"
#include "signals.h"
#include "commands.h"
extern void xs_init(void);
typedef struct {
int signal_id;
char *signal;
char *args[7];
} PERL_SIGNAL_ARGS_REC;
typedef struct {
char *signal;
int signal_id;
char *func;
int last;
} PERL_SIGNAL_REC;
typedef struct {
int tag;
char *func;
char *data;
} PERL_TIMEOUT_REC;
#include "perl-signals.h"
static GHashTable *first_signals, *last_signals;
static GSList *perl_timeouts;
static PerlInterpreter *irssi_perl_interp;
static int signal_grabbed, siglast_grabbed;
static void sig_signal(void *signal, ...);
static void sig_lastsignal(void *signal, ...);
static void perl_signal_destroy(PERL_SIGNAL_REC *rec)
{
GHashTable *table;
GSList *siglist;
void *signal_idp;
table = rec->last ? last_signals : first_signals;
signal_idp = GINT_TO_POINTER(rec->signal_id);
siglist = g_hash_table_lookup(table, signal_idp);
if (siglist == NULL) return;
siglist = g_slist_remove(siglist, rec);
g_hash_table_remove(table, signal_idp);
if (siglist != NULL) g_hash_table_insert(table, signal_idp, siglist);
if (!rec->last && signal_grabbed && g_hash_table_size(first_signals) == 0) {
signal_grabbed = FALSE;
signal_remove("signal", (SIGNAL_FUNC) sig_signal);
}
if (rec->last && siglast_grabbed && g_hash_table_size(last_signals) == 0) {
siglast_grabbed = FALSE;
signal_remove("last signal", (SIGNAL_FUNC) sig_lastsignal);
}
if (strncmp(rec->signal, "command ", 8) == 0)
command_unbind(rec->signal+8, NULL);
g_free(rec->signal);
g_free(rec->func);
g_free(rec);
}
static void perl_timeout_destroy(PERL_TIMEOUT_REC *rec)
{
perl_timeouts = g_slist_remove(perl_timeouts, rec);
g_source_remove(rec->tag);
g_free(rec->func);
g_free(rec->data);
g_free(rec);
}
static void irssi_perl_start(void)
{
/* stolen from xchat, thanks :) */
char *args[] = {"", "-e", "0"};
char load_file[] =
"sub load_file()\n"
"{\n"
" (my $file_name) = @_;\n"
" open FH, $file_name or return 2;\n"
" local($/) = undef;\n"
" $file = <FH>;\n"
" close FH;\n"
" eval $file;\n"
" eval $file if $@;\n"
" return 1 if $@;\n"
" return 0;\n"
"}";
first_signals = g_hash_table_new((GHashFunc) g_direct_hash, (GCompareFunc) g_direct_equal);
last_signals = g_hash_table_new((GHashFunc) g_direct_hash, (GCompareFunc) g_direct_equal);
perl_timeouts = NULL;
irssi_perl_interp = perl_alloc();
perl_construct(irssi_perl_interp);
perl_parse(irssi_perl_interp, xs_init, 3, args, NULL);
perl_eval_pv(load_file, TRUE);
}
static void signal_destroy_hash(void *key, PERL_SIGNAL_REC *rec)
{
perl_signal_destroy(rec);
}
static void irssi_perl_stop(void)
{
g_hash_table_foreach(first_signals, (GHFunc) signal_destroy_hash, NULL);
g_hash_table_destroy(first_signals);
g_hash_table_foreach(last_signals, (GHFunc) signal_destroy_hash, NULL);
g_hash_table_destroy(last_signals);
while (perl_timeouts != NULL)
perl_timeout_destroy(perl_timeouts->data);
perl_destruct(irssi_perl_interp);
perl_free(irssi_perl_interp);
irssi_perl_interp = NULL;
}
static void cmd_run(char *data)
{
dSP;
struct stat statbuf;
char *fname;
int retcount;
/* add .pl suffix if it's missing */
data = (strlen(data) <= 3 || strcmp(data+strlen(data)-3, ".pl") == 0) ?
g_strdup(data) : g_strdup_printf("%s.pl", data);
if (g_path_is_absolute(data)) {
/* whole path specified */
fname = g_strdup(data);
} else {
/* check from ~/.irssi/scripts/ */
fname = g_strdup_printf("%s/.irssi/scripts/%s", g_get_home_dir(), data);
if (stat(fname, &statbuf) != 0) {
/* check from SCRIPTDIR */
g_free(fname),
fname = g_strdup_printf(SCRIPTDIR"/%s", data);
}
}
g_free(data);
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv(fname, strlen(fname)))); g_free(fname);
PUTBACK;
retcount = perl_call_pv("load_file", G_EVAL|G_SCALAR);
SPAGAIN;
if (SvTRUE(ERRSV)) {
STRLEN n_a;
signal_emit("perl error", 1, SvPV(ERRSV, n_a));
(void) POPs;
}
else while (retcount--) (void) POPi;
PUTBACK;
FREETMPS;
LEAVE;
}
static void cmd_flush(const char *data)
{
irssi_perl_stop();
irssi_perl_start();
}
static void perl_signal_to(const char *signal, const char *func, int last)
{
PERL_SIGNAL_REC *rec;
GHashTable *table;
GSList *siglist;
void *signal_idp;
rec = g_new(PERL_SIGNAL_REC, 1);
rec->signal_id = module_get_uniq_id_str("signals", signal);
rec->signal = g_strdup(signal);
rec->func = g_strdup(func);
rec->last = last;
table = last ? last_signals : first_signals;
signal_idp = GINT_TO_POINTER(rec->signal_id);
siglist = g_hash_table_lookup(table, signal_idp);
if (siglist != NULL) g_hash_table_remove(table, signal_idp);
siglist = g_slist_append(siglist, rec);
g_hash_table_insert(table, signal_idp, siglist);
if (!last && !signal_grabbed) {
signal_grabbed = TRUE;
signal_add("signal", (SIGNAL_FUNC) sig_signal);
} else if (last && !siglast_grabbed) {
siglast_grabbed = TRUE;
signal_add("last signal", (SIGNAL_FUNC) sig_lastsignal);
}
}
void perl_signal_add(const char *signal, const char *func)
{
perl_signal_to(signal, func, FALSE);
}
void perl_signal_add_last(const char *signal, const char *func)
{
perl_signal_to(signal, func, TRUE);
}
static void perl_signal_remove_list(GSList *list, const char *func)
{
while (list != NULL) {
PERL_SIGNAL_REC *rec = list->data;
if (strcmp(func, rec->func) == 0) {
perl_signal_destroy(rec);
break;
}
list = list->next;
}
}
void perl_signal_remove(const char *signal, const char *func)
{
GSList *list;
int signal_id;
signal_id = module_get_uniq_id_str("signals", signal);
list = g_hash_table_lookup(first_signals, GINT_TO_POINTER(signal_id));
if (list != NULL)
perl_signal_remove_list(list, func);
else {
list = g_hash_table_lookup(last_signals, GINT_TO_POINTER(signal_id));
if (list != NULL) perl_signal_remove_list(list, func);
}
}
static int perl_timeout(PERL_TIMEOUT_REC *rec)
{
dSP;
int retcount;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv(rec->data, strlen(rec->data))));
PUTBACK;
retcount = perl_call_pv(rec->func, G_EVAL|G_SCALAR);
SPAGAIN;
if (SvTRUE(ERRSV)) {
STRLEN n_a;
signal_emit("perl error", 1, SvPV(ERRSV, n_a));
(void) POPs;
}
else while (retcount--) (void) POPi;
PUTBACK;
FREETMPS;
LEAVE;
return 1;
}
int perl_timeout_add(int msecs, const char *func, const char *data)
{
PERL_TIMEOUT_REC *rec;
rec = g_new(PERL_TIMEOUT_REC, 1);
rec->func = g_strdup(func);
rec->data = g_strdup(data);
rec->tag = g_timeout_add(msecs, (GSourceFunc) perl_timeout, rec);
perl_timeouts = g_slist_append(perl_timeouts, rec);
return rec->tag;
}
void perl_timeout_remove(int tag)
{
GSList *tmp;
for (tmp = perl_timeouts; tmp != NULL; tmp = tmp->next) {
PERL_TIMEOUT_REC *rec = tmp->data;
if (rec->tag == tag) {
perl_timeout_destroy(rec);
break;
}
}
}
static int call_perl(const char *func, int signal, va_list va)
{
dSP;
PERL_SIGNAL_ARGS_REC *rec;
int retcount, n, ret;
void *arg;
HV *stash;
/* first check if we find exact match */
rec = NULL;
for (n = 0; perl_signal_args[n].signal != NULL; n++)
{
if (signal == perl_signal_args[n].signal_id)
{
rec = &perl_signal_args[n];
break;
}
}
if (rec == NULL)
{
/* try to find by name */
const char *signame;
signame = module_find_id_str("signals", signal);
for (n = 0; perl_signal_args[n].signal != NULL; n++)
{
if (strncmp(signame, perl_signal_args[n].signal,
strlen(perl_signal_args[n].signal)) == 0)
{
rec = &perl_signal_args[n];
break;
}
}
}
ENTER;
SAVETMPS;
PUSHMARK(sp);
if (rec != NULL)
{
/* put the arguments to perl stack */
for (n = 0; n < 7; n++)
{
arg = va_arg(va, gpointer);
if (rec->args[n] == NULL)
break;
if (strcmp(rec->args[n], "string") == 0)
XPUSHs(sv_2mortal(newSVpv(arg == NULL ? "" : arg, arg == NULL ? 0 : strlen(arg))));
else if (strcmp(rec->args[n], "int") == 0)
XPUSHs(sv_2mortal(newSViv(GPOINTER_TO_INT(arg))));
else if (strcmp(rec->args[n], "ulongptr") == 0)
XPUSHs(sv_2mortal(newSViv(*(gulong *) arg)));
else if (strncmp(rec->args[n], "glist_", 6) == 0)
{
GSList *tmp;
stash = gv_stashpv(rec->args[n]+6, 0);
for (tmp = arg; tmp != NULL; tmp = tmp->next)
XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash)));
}
else
{
stash = gv_stashpv(rec->args[n], 0);
XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(arg))), stash)));
}
}
}
PUTBACK;
retcount = perl_call_pv((char *) func, G_EVAL|G_SCALAR);
SPAGAIN;
ret = 0;
if (SvTRUE(ERRSV))
{
STRLEN n_a;
signal_emit("perl error", 1, SvPV(ERRSV, n_a));
(void)POPs;
}
else
{
SV *sv;
if (retcount > 0)
{
sv = POPs;
if (SvIOK(sv) && SvIV(sv) == 1) ret = 1;
}
for (n = 2; n <= retcount; n++)
(void)POPi;
}
PUTBACK;
FREETMPS;
LEAVE;
return ret;
}
static void sig_signal(void *signal, ...)
{
GSList *list;
va_list va;
va_start(va, signal);
list = g_hash_table_lookup(first_signals, signal);
while (list != NULL) {
PERL_SIGNAL_REC *rec = list->data;
if (call_perl(rec->func, GPOINTER_TO_INT(signal), va)) {
signal_stop();
return;
}
list = list->next;
}
va_end(va);
}
static void sig_lastsignal(void *signal, ...)
{
GSList *list;
va_list va;
va_start(va, signal);
list = g_hash_table_lookup(last_signals, signal);
while (list != NULL) {
PERL_SIGNAL_REC *rec = list->data;
if (call_perl(rec->func, GPOINTER_TO_INT(signal), va)) {
signal_stop();
return;
}
list = list->next;
}
va_end(va);
}
static void irssi_perl_autorun(void)
{
DIR *dirp;
struct dirent *dp;
char *path, *fname;
path = g_strdup_printf("%s/.irssi/scripts/autorun", g_get_home_dir());
dirp = opendir(path);
if (dirp == NULL) {
g_free(path);
return;
}
while ((dp = readdir(dirp)) != NULL) {
fname = g_strdup_printf("%s/%s", path, dp->d_name);
cmd_run(fname);
g_free(fname);
}
closedir(dirp);
g_free(path);
}
void irssi_perl_init(void)
{
command_bind("run", NULL, (SIGNAL_FUNC) cmd_run);
command_bind("perlflush", NULL, (SIGNAL_FUNC) cmd_flush);
signal_grabbed = siglast_grabbed = FALSE;
irssi_perl_start();
irssi_perl_autorun();
}
void irssi_perl_deinit(void)
{
irssi_perl_stop();
command_unbind("run", (SIGNAL_FUNC) cmd_run);
command_unbind("perlflush", (SIGNAL_FUNC) cmd_flush);
if (signal_grabbed) signal_remove("signal", (SIGNAL_FUNC) sig_signal);
if (siglast_grabbed) signal_remove("last signal", (SIGNAL_FUNC) sig_lastsignal);
}

7
src/perl/irssi-perl.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef __IRSSI_PERL_H
#define __IRSSI_PERL_H
void irssi_perl_init(void);
void irssi_perl_deinit(void);
#endif

3
src/perl/module.h Normal file
View file

@ -0,0 +1,3 @@
#include "common.h"
#define MODULE_NAME "irssi-perl"

108
src/perl/perl-signals.h Normal file
View file

@ -0,0 +1,108 @@
static PERL_SIGNAL_ARGS_REC perl_signal_args[] =
{
{ -1, "gui channel open", { "CHANNEL_REC", NULL } },
{ -1, "send command", { "string", "SERVER_REC", "CHANNEL_REC", NULL } },
{ -1, "send command", { "string", "SERVER_REC", NULL } },
{ -1, "command ", { "string", "SERVER_REC", "CHANNEL_REC", NULL } },
{ -1, "default command", { "string", "SERVER_REC", "CHANNEL_REC", NULL } },
{ -1, "server event", { "string", "SERVER_REC", "string", "string", NULL } },
{ -1, "event ", { "string", "SERVER_REC", "string", "string", NULL } },
{ -1, "default event", { "string", "SERVER_REC", "string", "string", NULL } },
{ -1, "server incoming", { "SERVER_REC", "string", NULL } },
{ -1, "redir ", { "string", "SERVER_REC", "string", "string", NULL } },
{ -1, "ban new", { "BAN_REC", NULL } },
{ -1, "ban remove", { "BAN_REC", NULL } },
{ -1, "ban exception new", { "BAN_REC", NULL } },
{ -1, "ban exception remove", { "BAN_REC", NULL } },
{ -1, "ban type changed", { "string", NULL } },
{ -1, "commandlist new", { "COMMAND_REC", NULL } },
{ -1, "commandlist remove", { "COMMAND_REC", NULL } },
{ -1, "channel created", { "CHANNEL_REC", NULL } },
{ -1, "channel destroyed", { "CHANNEL_REC", NULL } },
{ -1, "channel name changed", { "CHANNEL_REC", NULL } },
{ -1, "channel topic changed", { "CHANNEL_REC", NULL } },
{ -1, "channel server changed", { "CHANNEL_REC", "Irssi::Server", NULL } },
{ -1, "channel query", { "CHANNEL_REC", NULL } },
{ -1, "channel wholist", { "CHANNEL_REC", NULL } },
{ -1, "channel sync", { "CHANNEL_REC", NULL } },
{ -1, "ctcp msg ", { "string", "SERVER_REC", "string", "string", "string", NULL } },
{ -1, "default ctcp msg", { "string", "SERVER_REC", "string", "string", "string", NULL } },
{ -1, "ctcp reply ", { "string", "SERVER_REC", "string", "string", "string", NULL } },
{ -1, "default ctcp reply", { "string", "SERVER_REC", "string", "string", "string", NULL } },
{ -1, "server lag", { "SERVER_REC", NULL } },
{ -1, "server lag disconnect", { "SERVER_REC", NULL } },
{ -1, "lag", { "string", "int", NULL } },
{ -1, "invitelist new", { "CHANNEL_REC", "string", NULL } },
{ -1, "invitelist remove", { "CHANNEL_REC", "string", NULL } },
{ -1, "channel mode changed", { "CHANNEL_REC", NULL } },
{ -1, "user mode changed", { "SERVER_REC", NULL } },
{ -1, "nick mode changed", { "CHANNEL_REC", "NICK_REC", NULL } },
{ -1, "netsplit add", { "NETSPLIT_REC", NULL } },
{ -1, "netsplit remove", { "NETSPLIT_REC", NULL } },
{ -1, "nicklist new", { "CHANNEL_REC", "NICK_REC", NULL } },
{ -1, "nicklist remove", { "CHANNEL_REC", "NICK_REC", NULL } },
{ -1, "nicklist changed", { "CHANNEL_REC", "NICK_REC", "string", NULL } },
{ -1, "nick gone changed", { "CHANNEL_REC", "NICK_REC", NULL } },
{ -1, "nick ircop changed", { "CHANNEL_REC", "NICK_REC", NULL } },
{ -1, "server nick changed", { "SERVER_REC", NULL } },
{ -1, "massjoin", { "CHANNEL_REC", "gslist_NICK_REC", NULL } },
{ -1, "rawlog", { "SERVER_REC", "string", NULL } },
{ -1, "server connect failed", { "SERVER_REC", NULL } },
{ -1, "server connected", { "SERVER_REC", NULL } },
{ -1, "server connecting", { "SERVER_REC", "ulongptr", NULL } },
{ -1, "server looking", { "SERVER_REC", NULL } },
{ -1, "server disconnected", { "SERVER_REC", NULL } },
{ -1, "event connected", { "SERVER_REC", NULL } },
{ -1, "server reconnect new", { "RECONNECT_REC", NULL } },
{ -1, "server reconnect remove", { "RECONNECT_REC", NULL } },
{ -1, "server reconnect not found", { "string", NULL } },
{ -1, "print text stripped", { "SERVER_REC", "string", "int", "string", NULL } },
{ -1, "dcc ctcp ", { "string", "DCC_REC", NULL } },
{ -1, "default dcc ctcp", { "string", "DCC_REC", NULL } },
{ -1, "dcc unknown ctcp", { "string", "string", "string", NULL } },
{ -1, "dcc reply ", { "string", "DCC_REC", NULL } },
{ -1, "default dcc reply", { "string", "DCC_REC", NULL } },
{ -1, "dcc unknown reply", { "string", "string", "string", NULL } },
{ -1, "dcc chat message", { "DCC_REC", "string", NULL } },
{ -1, "dcc created", { "DCC_REC", NULL } },
{ -1, "dcc destroyed", { "DCC_REC", NULL } },
{ -1, "dcc connected", { "DCC_REC", NULL } },
{ -1, "dcc rejecting", { "DCC_REC", NULL } },
{ -1, "dcc closed", { "DCC_REC", NULL } },
{ -1, "dcc chat message", { "DCC_REC", "string", NULL } },
{ -1, "dcc transfer update", { "DCC_REC", NULL } },
{ -1, "dcc request", { "DCC_REC", NULL } },
{ -1, "dcc get receive", { "DCC_REC", NULL } },
{ -1, "dcc error connect", { "DCC_REC", NULL } },
{ -1, "dcc error file create", { "DCC_REC", "string", NULL } },
{ -1, "dcc error file not found", { "string", "string", NULL } },
{ -1, "dcc error get not found", { "string", NULL } },
{ -1, "dcc error send exists", { "string", "string", NULL } },
{ -1, "dcc error unknown type", { "string", NULL } },
{ -1, "dcc error close not found", { "string", "string", "string", NULL } },
{ -1, "flood", { "SERVER_REC", "string", "string", "string", "string", NULL } },
{ -1, "autoignore new", { "SERVER_REC", "AUTOIGNORE_REC", NULL } },
{ -1, "autoignore remove", { "SERVER_REC", "AUTOIGNORE_REC", NULL } },
{ -1, "log new", { "LOG_REC", NULL } },
{ -1, "log remove", { "LOG_REC", NULL } },
{ -1, "log locked", { "LOG_REC", NULL } },
{ -1, "log started", { "LOG_REC", NULL } },
{ -1, "log stopped", { "LOG_REC", NULL } },
{ -1, "log written", { "LOG_REC", "string", NULL } },
{ -1, "notifylist new", { "NOTIFYLIST_REC", NULL } },
{ -1, "notifylist remove", { "NOTIFYLIST_REC", NULL } },
{ -1, "notifylist joined", { "SERVER_REC", "string", "string", "string", "string", "string", NULL } },
{ -1, "notifylist away changed", { "SERVER_REC", "string", "string", "string", "string", "string", NULL } },
{ -1, "notifylist unidle", { "SERVER_REC", "string", "string", "string", "string", "string", NULL } },
{ -1, "notifylist left", { "SERVER_REC", "string", "string", "string", "string", "string", NULL } },
{ -1, "plugin created", { "PLUGIN_REC", NULL } },
{ -1, "plugin loaded", { "PLUGIN_REC", NULL } },
{ -1, "plugin destroyed", { "PLUGIN_REC", NULL } },
{ -1, "plugin error already loaded", { "string", NULL } },
{ -1, "plugin error invalid", { "string", NULL } },
{ -1, "plugin error load", { "string", "string", NULL } },
{ -1, "plugin error not loaded", { "string", NULL } },
{ -1, "plugin error version", { "string", NULL } },
{ -1, NULL }
};

21
src/perl/xs/Irssi.pm Normal file
View file

@ -0,0 +1,21 @@
#
# Perl interface to irssi functions.
#
package Irssi;
use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
$VERSION = "0.10";
require Exporter;
require DynaLoader;
@ISA = qw(Exporter DynaLoader);
@EXPORT = qw(channel_find_any);
@EXPORT_OK = qw();
bootstrap Irssi $VERSION;
1;

933
src/perl/xs/Irssi.xs Normal file
View file

@ -0,0 +1,933 @@
/* This could be split to different files / modules ..? */
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#undef _
#include <irssi-plugin.h>
#include <irc-base/server-setup.h>
#include <irc-base/server-reconnect.h>
#include <irc-base/server-redirect.h>
typedef SERVER_REC *Irssi__Server;
typedef SERVER_CONNECT_REC *Irssi__Connect;
typedef RECONNECT_REC *Irssi__Reconnect;
typedef CHANNEL_REC *Irssi__Channel;
typedef COMMAND_REC *Irssi__Command;
typedef NICK_REC *Irssi__Nick;
typedef BAN_REC *Irssi__Ban;
typedef DCC_REC *Irssi__Dcc;
typedef NETSPLIT_REC *Irssi__Netsplit;
typedef AUTOIGNORE_REC *Irssi__Autoignore;
typedef LOG_REC *Irssi__Log;
typedef LOG_ITEM_REC *Irssi__Logitem;
typedef PLUGIN_REC *Irssi__Plugin;
#define new_pv(a) (newSVpv((a) == NULL ? "" : (a), (a) == NULL ? 0 : strlen(a)))
void add_connect_hash(HV *hv, SERVER_CONNECT_REC *conn)
{
hv_store(hv, "address", 7, new_pv(conn->address), 0);
hv_store(hv, "port", 4, newSViv(conn->port), 0);
hv_store(hv, "password", 8, new_pv(conn->password), 0);
hv_store(hv, "ircnet", 6, new_pv(conn->ircnet), 0);
hv_store(hv, "wanted_nick", 11, new_pv(conn->nick), 0);
hv_store(hv, "alternate_nick", 14, new_pv(conn->alternate_nick), 0);
hv_store(hv, "username", 8, new_pv(conn->username), 0);
hv_store(hv, "realname", 8, new_pv(conn->realname), 0);
hv_store(hv, "autojoin_channels", 17, new_pv(conn->autojoin_channels), 0);
}
MODULE = Irssi PACKAGE = Irssi
PROTOTYPES: ENABLE
Irssi::Channel
cur_channel()
CODE:
RETVAL = cur_channel;
OUTPUT:
RETVAL
Irssi::Server
cur_server()
CODE:
RETVAL = cur_channel->server;
OUTPUT:
RETVAL
void
channels()
PREINIT:
GSList *tmp;
HV *stash;
PPCODE:
stash = gv_stashpv("Irssi::Channel", 0);
for (tmp = channels; tmp != NULL; tmp = tmp->next) {
XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash)));
}
void
servers()
PREINIT:
GSList *tmp;
HV *stash;
PPCODE:
stash = gv_stashpv("Irssi::Server", 0);
for (tmp = servers; tmp != NULL; tmp = tmp->next) {
XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash)));
}
void
commands()
PREINIT:
GSList *tmp;
HV *stash;
PPCODE:
stash = gv_stashpv("Irssi::Command", 0);
for (tmp = commands; tmp != NULL; tmp = tmp->next) {
XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash)));
}
void
dccs()
PREINIT:
GSList *tmp;
HV *stash;
PPCODE:
stash = gv_stashpv("Irssi::Dcc", 0);
for (tmp = dcc_conns; tmp != NULL; tmp = tmp->next) {
XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash)));
}
void
logs()
PREINIT:
GSList *tmp;
HV *stash;
PPCODE:
stash = gv_stashpv("Irssi::Log", 0);
for (tmp = logs; tmp != NULL; tmp = tmp->next) {
XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash)));
}
void
plugins()
PREINIT:
GSList *tmp;
HV *stash;
PPCODE:
stash = gv_stashpv("Irssi::Plugin", 0);
for (tmp = plugins; tmp != NULL; tmp = tmp->next) {
XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash)));
}
Irssi::Connect
server_create_conn(dest, port=6667, password=NULL, nick=NULL, channels=NULL)
char *dest
int port
char *password
char *nick
char *channels
Irssi::Server
server_find_tag(tag)
char *tag
Irssi::Server
server_find_ircnet(ircnet)
char *ircnet
Irssi::Channel
channel_find(channel)
char *channel
CODE:
RETVAL = channel_find(NULL, channel);
OUTPUT:
RETVAL
void
print(str)
char *str
CODE:
printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, str);
void
signal_emit(signal, ...)
char *signal
CODE:
void *p[6];
int n;
memset(p, 0, sizeof(p));
for (n = 1; n < items && n < 6; n++) {
p[n-1] = SvPOKp(ST(n)) ? SvPV(ST(n), PL_na) : (void *) SvIV((SV*)SvRV(ST(n)));
}
signal_emit(signal, items-1, p[0], p[1], p[2], p[3], p[4], p[5]);
void
signal_add(signal, func)
char *signal
char *func
CODE:
perl_signal_add(signal, func);
void
signal_add_last(signal, func)
char *signal
char *func
CODE:
perl_signal_add_last(signal, func);
void
signal_remove(signal, func)
char *signal
char *func
CODE:
perl_signal_remove(signal, func);
int
timeout_add(msecs, func, data)
int msecs
char *func
char *data
CODE:
RETVAL = perl_timeout_add(msecs, func, data);
OUTPUT:
RETVAL
void
timeout_remove(tag)
int tag
CODE:
perl_timeout_remove(tag);
void
command_bind(cmd, category, func)
char *cmd
char *category
char *func
CODE:
char *signal;
command_bind(cmd, *category ? category : "Perl scripts' commands", NULL);
signal = g_strconcat("command ", cmd, NULL);
perl_signal_add(signal, func);
g_free(signal);
void
command_unbind(cmd, func)
char *cmd
char *func
CODE:
char *signal;
command_unbind(cmd, NULL);
signal = g_strconcat("command ", cmd, NULL);
perl_signal_remove(signal, func);
g_free(signal);
void
command(cmd, server=cur_channel->server, channel=cur_channel)
char *cmd
Irssi::Server server
Irssi::Channel channel
CODE:
signal_emit("send command", 3, cmd, server, channel);
int
is_channel(text)
char *text
CODE:
RETVAL = ischannel(*text);
OUTPUT:
RETVAL
int
irc_mask_match(mask, nick, user, host)
char *mask
char *nick
char *user
char *host
int
irc_mask_match_address(mask, nick, address)
char *mask
char *nick
char *address
int
irc_masks_match(masks, nick, address)
char *masks
char *nick
char *address
char *
irc_get_mask(nick, host, flags)
char *nick
char *host
int flags
int
level2bits(str)
char *str
char *
bits2level(bits)
int bits
int
combine_level(level, str)
int level
char *str
Irssi::Dcc
dcc_find_item(type, nick, arg)
int type
char *nick
char *arg
Irssi::Dcc
dcc_find_by_port(nick, port)
char *nick
int port
char *
dcc_type2str(type)
int type
int
dcc_str2type(type)
char *type
void
ignore_add(mask, level)
char *mask
char *level
void
ignore_remove(mask, level)
char *mask
char *level
Irssi::Log
log_create(fname, data)
char *fname
char *data
Irssi::Log
log_create_with_level(fname, level)
char *fname
int level
Irssi::Log
log_file_find(fname)
char *fname
void
notifylist_add(nick, ircnet)
char *nick
char *ircnet
Irssi::Server
notifylist_ison(nick, serverlist)
char *nick
char *serverlist
int
plugin_load(name, args)
char *name
char *args
char *
plugin_get_description(name)
char *name
Irssi::Plugin
plugin_find(name)
char *name
void
setup_get(option)
char *option
PREINIT:
char *ret;
PPCODE:
switch(setup_option_type(option)) {
case SETUP_TYPE_TOGGLEBUTTON:
XPUSHs(sv_2mortal(newSViv(setup_get_bool(option))));
break;
case SETUP_TYPE_SPIN:
case SETUP_TYPE_INT_OBJECT:
XPUSHs(sv_2mortal(newSViv(setup_get_int(option))));
break;
case SETUP_TYPE_ENTRY:
ret = setup_get_str(option);
XPUSHs(sv_2mortal(newSVpv(ret, strlen(ret))));
break;
}
#*******************************************************
MODULE = Irssi PACKAGE = Irssi::Server PREFIX = server_
#*******************************************************
void
send_raw(server, cmd)
Irssi::Server server
char *cmd
CODE:
irc_send_cmd(server, cmd);
void
command(server, cmd, channel=cur_channel)
char *cmd
Irssi::Server server
Irssi::Channel channel
CODE:
if (channel->server != server) {
GSList *tmp;
for (tmp = channels; tmp != NULL; tmp = tmp->next) {
CHANNEL_REC *rec = tmp->data;
if (rec->server == server) {
channel = rec;
break;
}
}
}
signal_emit("send command", 3, cmd, server, channel);
void
server_disconnect(server)
Irssi::Server server
Irssi::Channel
channel_create(server, channel, type, automatic)
Irssi::Server server
char *channel
int type
int automatic
Irssi::Channel
channel_find(server, channel)
Irssi::Server server
char *channel
Irssi::Channel
channel_find_closest(server, channel, level)
Irssi::Server server
char *channel
int level
Irssi::Channel
channel_find_level(server, level)
Irssi::Server server
int level
void
printtext(server, channel, level, str)
Irssi::Server server
char *channel
int level
char *str
CODE:
printtext(server, channel, level, str);
void
irc_send_cmd_split(server, cmd, arg, max_nicks)
Irssi::Server server
char *cmd
int arg
int max_nicks
void
ctcp_send_reply(server, data)
Irssi::Server server
char *data
Irssi::Netsplit
netsplit_find(server, nick, address)
Irssi::Server server
char *nick
char *address
Irssi::Nick
netsplit_find_channel(server, nick, address, channel)
Irssi::Server server
char *nick
char *address
char *channel
void
rawlog_input(server, str)
Irssi::Server server
char *str
void
rawlog_output(server, str)
Irssi::Server server
char *str
void
rawlog_redirect(server, str)
Irssi::Server server
char *str
void
server_redirect_init(server, command, last, ...)
Irssi::Server server
char *command
int last
PREINIT:
GSList *list;
int n;
CODE:
list = NULL;
for (n = 3; n < items; n++) {
list = g_slist_append(list, SvPV(ST(n), PL_na));
}
server_redirect_initv(server, command, last, list);
int
server_redirect_single_event(server, arg, last, group, event, signal, argpos)
Irssi::Server server
char *arg
int last
int group
char *event
char *signal
int argpos
void
server_redirect_event(server, arg, last, ...)
Irssi::Server server
char *arg
int last
PREINIT:
int n, group;
CODE:
group = 0;
for (n = 3; n+3 <= items; n += 3, last--) {
group = server_redirect_single_event(server, arg, last > 0, group,
(char *) SvPV(ST(n), PL_na), (char *) SvPV(ST(n+1), PL_na), (int) SvIV(ST(n+2)));
}
void
autoignore_add(server, type, nick)
Irssi::Server server
int type
char *nick
int
autoignore_remove(server, mask, level)
Irssi::Server server
char *mask
char *level
int
ignore_check(server, nick, host, type)
Irssi::Server server
char *nick
char *host
int type
int
notifylist_ison_server(server, nick)
Irssi::Server server
char *nick
void
values(server)
Irssi::Server server
PREINIT:
HV *hv;
PPCODE:
hv = newHV();
add_connect_hash(hv, server->connrec);
hv_store(hv, "real_address", 12, new_pv(server->real_address), 0);
hv_store(hv, "tag", 3, new_pv(server->tag), 0);
hv_store(hv, "nick", 4, new_pv(server->nick), 0);
hv_store(hv, "usermode", 8, new_pv(server->usermode), 0);
hv_store(hv, "usermode_away", 13, newSViv(server->usermode_away), 0);
hv_store(hv, "away_reason", 11, new_pv(server->away_reason), 0);
hv_store(hv, "connected", 9, newSViv(server->connected), 0);
hv_store(hv, "connection_lost", 15, newSViv(server->connection_lost), 0);
XPUSHs(sv_2mortal(newRV_noinc((SV*)hv)));
#*******************************************************
MODULE = Irssi PACKAGE = Irssi::Connect PREFIX = server_
#*******************************************************
void
values(conn)
Irssi::Connect conn
PREINIT:
HV *hv;
PPCODE:
hv = newHV();
add_connect_hash(hv, conn);
XPUSHs(sv_2mortal(newRV_noinc((SV*)hv)));
Irssi::Server
server_connect(conn)
Irssi::Connect conn
#*******************************************************
MODULE = Irssi PACKAGE = Irssi::Reconnect
#*******************************************************
void
values(reconnect)
Irssi::Reconnect reconnect
PREINIT:
HV *hv;
PPCODE:
hv = newHV();
add_connect_hash(hv, reconnect->conn);
hv_store(hv, "tag", 3, newSViv(reconnect->tag), 0);
hv_store(hv, "next_connect", 12, newSViv(reconnect->next_connect), 0);
XPUSHs(sv_2mortal(newRV_noinc((SV*)hv)));
#*******************************************************
MODULE = Irssi PACKAGE = Irssi::Channel PREFIX = channel_
#*******************************************************
void
command(channel, cmd)
Irssi::Channel channel
char *cmd
CODE:
signal_emit("send command", 3, cmd, channel->server, channel);
void
channel_destroy(channel)
Irssi::Channel channel
void
channel_change_name(channel, name)
Irssi::Channel channel
char *name
char *
channel_get_mode(channel)
Irssi::Channel channel
Irssi::Nick
nicklist_insert(channel, nick, op, voice, send_massjoin)
Irssi::Channel channel
char *nick
int op
int voice
int send_massjoin
void
nicklist_remove(channel, nick)
Irssi::Channel channel
Irssi::Nick nick
Irssi::Nick
nicklist_find(channel, mask)
Irssi::Channel channel
char *mask
void
nicklist_getnicks(channel)
Irssi::Channel channel
PREINIT:
GSList *list, *tmp;
HV *stash;
PPCODE:
list = nicklist_getnicks(channel);
stash = gv_stashpv("Irssi::Nick", 0);
for (tmp = list; tmp != NULL; tmp = tmp->next) {
XPUSHs(sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash)));
}
g_slist_free(list);
Irssi::Ban
ban_add(channel, ban, nick, time)
Irssi::Channel channel
char *ban
char *nick
time_t time
void
ban_remove(channel, ban)
Irssi::Channel channel
char *ban
Irssi::Ban
ban_exception_add(channel, ban, nick, time)
Irssi::Channel channel
char *ban
char *nick
time_t time
void
ban_exception_remove(channel, ban)
Irssi::Channel channel
char *ban
char *
ban_get_mask(channel, nick)
Irssi::Channel channel
char *nick
void
modes_set(channel, data, mode)
Irssi::Channel channel
char *data
char *mode
CODE:
modes_set(data, mode, channel->server, channel);
void
modes_parse_channel(channel, setby, modestr)
Irssi::Channel channel
char *setby
char *modestr
void
invitelist_add(channel, mask)
Irssi::Channel channel
char *mask
void
invitelist_remove(channel, mask)
Irssi::Channel channel
char *mask
void
values(channel)
Irssi::Channel channel
PREINIT:
HV *hv, *stash;
char *type;
PPCODE:
switch (channel->type)
{
case CHANNEL_TYPE_CHANNEL:
type = "channel";
break;
case CHANNEL_TYPE_QUERY:
type = "query";
break;
case CHANNEL_TYPE_DCC_CHAT:
type = "dcc chat";
break;
default:
type = "empty";
break;
}
hv = newHV();
stash = gv_stashpv("Irssi::Server", 0);
hv_store(hv, "server", 6, sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(channel->server))), stash), 0);
hv_store(hv, "name", 4, new_pv(channel->name), 0);
hv_store(hv, "type", 4, new_pv(type), 0);
hv_store(hv, "topic", 5, new_pv(channel->topic), 0);
hv_store(hv, "key", 3, new_pv(channel->key), 0);
hv_store(hv, "limit", 5, newSViv(channel->limit), 0);
hv_store(hv, "level", 5, newSViv(channel->level), 0);
hv_store(hv, "new_data", 8, newSViv(channel->new_data), 0);
hv_store(hv, "synced", 6, newSViv(channel->synced), 0);
hv_store(hv, "wholist", 7, newSViv(channel->wholist), 0);
hv_store(hv, "names_got", 9, newSViv(channel->names_got), 0);
hv_store(hv, "chanop", 6, newSViv(channel->chanop), 0);
hv_store(hv, "left", 4, newSViv(channel->left), 0);
hv_store(hv, "kicked", 6, newSViv(channel->kicked), 0);
XPUSHs(sv_2mortal(newRV_noinc((SV*)hv)));
#*******************************************************
MODULE = Irssi PACKAGE = Irssi::Command
#*******************************************************
void
values(cmd)
Irssi::Command cmd
PREINIT:
HV *hv;
PPCODE:
hv = newHV();
hv_store(hv, "cmd", 3, new_pv(cmd->cmd), 0);
hv_store(hv, "category", 8, new_pv(cmd->category), 0);
XPUSHs(sv_2mortal(newRV_noinc((SV*)hv)));
#*******************************************************
MODULE = Irssi PACKAGE = Irssi::Nick
#*******************************************************
void
values(nick)
Irssi::Nick nick
PREINIT:
HV *hv;
PPCODE:
hv = newHV();
hv_store(hv, "nick", 4, new_pv(nick->nick), 0);
hv_store(hv, "host", 4, new_pv(nick->host), 0);
hv_store(hv, "name", 4, new_pv(nick->realname), 0);
hv_store(hv, "hops", 4, newSViv(nick->hops), 0);
hv_store(hv, "op", 2, newSViv(nick->op), 0);
hv_store(hv, "voice", 5, newSViv(nick->voice), 0);
hv_store(hv, "gone", 4, newSViv(nick->gone), 0);
hv_store(hv, "ircop", 5, newSViv(nick->ircop), 0);
hv_store(hv, "last_check", 10, newSViv(nick->last_check), 0);
hv_store(hv, "send_massjoin", 13, newSViv(nick->send_massjoin), 0);
XPUSHs(sv_2mortal(newRV_noinc((SV*)hv)));
#*******************************************************
MODULE = Irssi PACKAGE = Irssi::Ban
#*******************************************************
void
values(ban)
Irssi::Ban ban
PREINIT:
HV *hv;
PPCODE:
hv = newHV();
hv_store(hv, "ban", 3, new_pv(ban->ban), 0);
hv_store(hv, "setby", 5, new_pv(ban->setby), 0);
hv_store(hv, "time", 4, newSViv(ban->time), 0);
XPUSHs(sv_2mortal(newRV_noinc((SV*)hv)));
#*******************************************************
MODULE = Irssi PACKAGE = Irssi::Dcc PREFIX = dcc_
#*******************************************************
void
dcc_destroy(dcc)
Irssi::Dcc dcc
void
values(ban)
Irssi::Ban ban
PREINIT:
HV *hv;
PPCODE:
hv = newHV();
hv_store(hv, "ban", 3, new_pv(ban->ban), 0);
hv_store(hv, "setby", 5, new_pv(ban->setby), 0);
hv_store(hv, "time", 4, newSViv(ban->time), 0);
XPUSHs(sv_2mortal(newRV_noinc((SV*)hv)));
#*******************************************************
MODULE = Irssi PACKAGE = Irssi::Netsplit
#*******************************************************
void
values(netsplit)
Irssi::Netsplit netsplit
PREINIT:
HV *hv;
PPCODE:
hv = newHV();
hv_store(hv, "nick", 4, new_pv(netsplit->nick), 0);
hv_store(hv, "address", 7, new_pv(netsplit->address), 0);
hv_store(hv, "server", 6, new_pv(netsplit->server), 0);
hv_store(hv, "destserver", 10, new_pv(netsplit->destserver), 0);
hv_store(hv, "destroy", 7, newSViv(netsplit->destroy), 0);
/*FIXME: add GSList *channels;*/
XPUSHs(sv_2mortal(newRV_noinc((SV*)hv)));
#*******************************************************
MODULE = Irssi PACKAGE = Irssi::Autoignore
#*******************************************************
void
values(ai)
Irssi::Autoignore ai
PREINIT:
HV *hv;
PPCODE:
hv = newHV();
hv_store(hv, "nick", 4, new_pv(ai->nick), 0);
hv_store(hv, "timeleft", 8, newSViv(ai->timeleft), 0);
hv_store(hv, "level", 5, newSViv(ai->level), 0);
XPUSHs(sv_2mortal(newRV_noinc((SV*)hv)));
#*******************************************************
MODULE = Irssi PACKAGE = Irssi::Log PREFIX = log_
#*******************************************************
void
values(log)
Irssi::Log log
PREINIT:
HV *hv;
PPCODE:
hv = newHV();
hv_store(hv, "fname", 5, new_pv(log->fname), 0);
hv_store(hv, "autoopen_log", 12, newSViv(log->autoopen_log), 0);
hv_store(hv, "last", 4, newSViv(log->last), 0);
hv_store(hv, "level", 5, newSViv(log->level), 0);
/*FIXME: add GSList *items;*/
XPUSHs(sv_2mortal(newRV_noinc((SV*)hv)));
void
destroy(log)
Irssi::Log log
CODE:
log_file_destroy(log);
int
open(log)
Irssi::Log log
CODE:
log_file_open(log);
void
close(log)
Irssi::Log log
CODE:
log_file_close(log);
void
log_append_item(log, name, level)
Irssi::Log log
char *name
int level
void
log_remove_item(log, name)
Irssi::Log log
char *name
#*******************************************************
MODULE = Irssi PACKAGE = Irssi::Logitem
#*******************************************************
void
values(item)
Irssi::Logitem item
PREINIT:
HV *hv;
PPCODE:
hv = newHV();
hv_store(hv, "name", 4, new_pv(item->name), 0);
hv_store(hv, "level", 5, newSViv(item->level), 0);
XPUSHs(sv_2mortal(newRV_noinc((SV*)hv)));
#*******************************************************
MODULE = Irssi PACKAGE = Irssi::Plugin PREFIX = plugin_
#*******************************************************
void
values(plugin)
Irssi::Plugin plugin
PREINIT:
HV *hv;
PPCODE:
hv = newHV();
hv_store(hv, "name", 4, new_pv(plugin->name), 0);
hv_store(hv, "description", 11, new_pv(plugin->description), 0);
XPUSHs(sv_2mortal(newRV_noinc((SV*)hv)));

View file

@ -0,0 +1,6 @@
use ExtUtils::MakeMaker;
WriteMakefile('NAME' => 'Irssi',
'LIBS' => '',
'INC' => '-I@top_srcdir@/src @GLIB_CFLAGS@',
'VERSION_FROM' => '@srcdir@/Irssi.pm');

14
src/perl/xs/typemap Normal file
View file

@ -0,0 +1,14 @@
TYPEMAP
Irssi::Server T_PTROBJ
Irssi::Connect T_PTROBJ
Irssi::Reconnect T_PTROBJ
Irssi::Channel T_PTROBJ
Irssi::Command T_PTROBJ
Irssi::Nick T_PTROBJ
Irssi::Ban T_PTROBJ
Irssi::Dcc T_PTROBJ
Irssi::Netsplit T_PTROBJ
Irssi::Autoignore T_PTROBJ
Irssi::Log T_PTROBJ
Irssi::Logitem T_PTROBJ
Irssi::Plugin T_PTROBJ

41
src/perl/xsinit.c Normal file
View file

@ -0,0 +1,41 @@
#if defined(__cplusplus) && !defined(PERL_OBJECT)
#define is_cplusplus
#endif
#ifdef is_cplusplus
extern "C" {
#endif
#include <EXTERN.h>
#include <perl.h>
#ifdef PERL_OBJECT
#define NO_XSLOCKS
#include <XSUB.h>
#include "win32iop.h"
#include <fcntl.h>
#include <perlhost.h>
#endif
#ifdef is_cplusplus
}
# ifndef EXTERN_C
# define EXTERN_C extern "C"
# endif
#else
# ifndef EXTERN_C
# define EXTERN_C extern
# endif
#endif
EXTERN_C void xs_init _((void));
EXTERN_C void boot_DynaLoader _((CV* cv));
EXTERN_C void
xs_init(void)
{
char *file = __FILE__;
dXSUB_SYS;
/* DynaLoader is a special case */
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
}