mirror of
https://github.com/irssi/irssi.git
synced 2024-11-03 04:27:19 -05:00
Add perl_signal_args_to_c() to convert signal parameters from Perl to C values,
and make Irssi::signal_emit/Irssi::signal_continue use it. Also make perl_call_signal() turn NULLs into undef, so we can recover them in perl_signal_args_to_c(), which is its inverse operation. Patch by Lukas Mai. git-svn-id: file:///var/www/svn.irssi.org/SVN/irssi/trunk@4953 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
parent
0cea011470
commit
8c64738cdc
@ -65,6 +65,15 @@ static void add_tuple(gpointer key_, gpointer value_, gpointer user_data)
|
|||||||
hv_store(hash, key, strlen(key), new_pv(value), 0);
|
hv_store(hash, key, strlen(key), new_pv(value), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wrap_signal_emit(void *signal, void **p) {
|
||||||
|
signal_emit(signal, 6, p[0], p[1], p[2], p[3], p[4], p[5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wrap_signal_continue(void *dummy, void **p) {
|
||||||
|
(void)dummy;
|
||||||
|
signal_continue(6, p[0], p[1], p[2], p[3], p[4], p[5]);
|
||||||
|
}
|
||||||
|
|
||||||
MODULE = Irssi::Core PACKAGE = Irssi
|
MODULE = Irssi::Core PACKAGE = Irssi
|
||||||
PROTOTYPES: ENABLE
|
PROTOTYPES: ENABLE
|
||||||
|
|
||||||
@ -72,44 +81,34 @@ void
|
|||||||
signal_emit(signal, ...)
|
signal_emit(signal, ...)
|
||||||
char *signal
|
char *signal
|
||||||
CODE:
|
CODE:
|
||||||
void *p[SIGNAL_MAX_ARGUMENTS];
|
int signal_id;
|
||||||
int n;
|
SV *args[SIGNAL_MAX_ARGUMENTS];
|
||||||
|
int n, used;
|
||||||
|
|
||||||
memset(p, 0, sizeof(p));
|
signal_id = signal_get_uniq_id(signal);
|
||||||
for (n = 1; n < items && n < SIGNAL_MAX_ARGUMENTS+1; n++) {
|
used = items - 1;
|
||||||
if (SvPOKp(ST(n)))
|
if (used > SIGNAL_MAX_ARGUMENTS) {
|
||||||
p[n-1] = SvPV(ST(n), PL_na);
|
used = SIGNAL_MAX_ARGUMENTS;
|
||||||
else if (irssi_is_ref_object(ST(n)))
|
|
||||||
p[n-1] = irssi_ref_object(ST(n));
|
|
||||||
else if (SvROK(ST(n)))
|
|
||||||
p[n-1] = (void *) SvIV((SV*)SvRV(ST(n)));
|
|
||||||
else if (SvIOK(ST(n)))
|
|
||||||
p[n-1] = (void *)SvIV(ST(n));
|
|
||||||
else
|
|
||||||
p[n-1] = NULL;
|
|
||||||
}
|
}
|
||||||
signal_emit(signal, items-1, p[0], p[1], p[2], p[3], p[4], p[5]);
|
for (n = 0; n < used; ++n) {
|
||||||
|
args[n] = ST(n + 1);
|
||||||
|
}
|
||||||
|
perl_signal_args_to_c(wrap_signal_emit, signal, signal_id, args, used);
|
||||||
|
|
||||||
void
|
void
|
||||||
signal_continue(...)
|
signal_continue(...)
|
||||||
CODE:
|
CODE:
|
||||||
void *p[SIGNAL_MAX_ARGUMENTS];
|
SV *args[SIGNAL_MAX_ARGUMENTS];
|
||||||
int n;
|
int n, used;
|
||||||
|
|
||||||
memset(p, 0, sizeof(p));
|
used = items;
|
||||||
for (n = 0; n < items && n < SIGNAL_MAX_ARGUMENTS; n++) {
|
if (used > SIGNAL_MAX_ARGUMENTS) {
|
||||||
if (SvPOKp(ST(n)))
|
used = SIGNAL_MAX_ARGUMENTS;
|
||||||
p[n] = SvPV(ST(n), PL_na);
|
|
||||||
else if (irssi_is_ref_object(ST(n)))
|
|
||||||
p[n] = irssi_ref_object(ST(n));
|
|
||||||
else if (SvROK(ST(n)))
|
|
||||||
p[n] = (void *) SvIV((SV*)SvRV(ST(n)));
|
|
||||||
else if (SvIOK(ST(n)))
|
|
||||||
p[n] = (void *) SvIV(ST(n));
|
|
||||||
else
|
|
||||||
p[n] = NULL;
|
|
||||||
}
|
}
|
||||||
signal_continue(items, p[0], p[1], p[2], p[3], p[4], p[5]);
|
for (n = 0; n < used; ++n) {
|
||||||
|
args[n] = ST(n);
|
||||||
|
}
|
||||||
|
perl_signal_args_to_c(wrap_signal_continue, NULL, signal_get_emitted_id(), args, used);
|
||||||
|
|
||||||
void
|
void
|
||||||
signal_add(...)
|
signal_add(...)
|
||||||
|
@ -70,6 +70,150 @@ static PERL_SIGNAL_ARGS_REC *perl_signal_args_find(int signal_id)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void perl_signal_args_to_c(
|
||||||
|
void (*callback)(void *, void **), void *cb_arg,
|
||||||
|
int signal_id, SV **args, size_t n_args)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
int v_int;
|
||||||
|
unsigned long v_ulong;
|
||||||
|
GSList *v_gslist;
|
||||||
|
GList *v_glist;
|
||||||
|
} saved_args[SIGNAL_MAX_ARGUMENTS];
|
||||||
|
void *p[SIGNAL_MAX_ARGUMENTS];
|
||||||
|
PERL_SIGNAL_ARGS_REC *rec;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
if (!(rec = perl_signal_args_find(signal_id))) {
|
||||||
|
const char *name = signal_get_id_str(signal_id);
|
||||||
|
if (!name) {
|
||||||
|
croak("%d is not a known signal id", signal_id);
|
||||||
|
}
|
||||||
|
croak("\"%s\" is not a registered signal", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n = 0; n < SIGNAL_MAX_ARGUMENTS && n < n_args && rec->args[n] != NULL; ++n) {
|
||||||
|
void *c_arg;
|
||||||
|
SV *arg = args[n];
|
||||||
|
|
||||||
|
if (!SvOK(arg)) {
|
||||||
|
c_arg = NULL;
|
||||||
|
} else if (strcmp(rec->args[n], "string") == 0) {
|
||||||
|
c_arg = SvPV_nolen(arg);
|
||||||
|
} else if (strcmp(rec->args[n], "int") == 0) {
|
||||||
|
c_arg = (void *)SvIV(arg);
|
||||||
|
} else if (strcmp(rec->args[n], "ulongptr") == 0) {
|
||||||
|
saved_args[n].v_ulong = SvUV(arg);
|
||||||
|
c_arg = &saved_args[n].v_ulong;
|
||||||
|
} else if (strcmp(rec->args[n], "intptr") == 0) {
|
||||||
|
saved_args[n].v_int = SvIV(SvRV(arg));
|
||||||
|
c_arg = &saved_args[n].v_int;
|
||||||
|
} else if (strncmp(rec->args[n], "glistptr_", 9) == 0) {
|
||||||
|
GList *gl;
|
||||||
|
int is_str;
|
||||||
|
AV *av;
|
||||||
|
SV *t;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
t = SvRV(arg);
|
||||||
|
if (SvTYPE(t) != SVt_PVAV) {
|
||||||
|
croak("Not an ARRAY reference");
|
||||||
|
}
|
||||||
|
av = (AV *)t;
|
||||||
|
|
||||||
|
is_str = strcmp(rec->args[n]+9, "char*") == 0;
|
||||||
|
|
||||||
|
gl = NULL;
|
||||||
|
count = av_len(av) + 1;
|
||||||
|
while (count-- > 0) {
|
||||||
|
SV **px = av_fetch(av, count, 0);
|
||||||
|
SV *x = px ? *px : NULL;
|
||||||
|
gl = g_list_prepend(
|
||||||
|
gl,
|
||||||
|
x == NULL ? NULL :
|
||||||
|
is_str ? g_strdup(SvPV_nolen(x)) :
|
||||||
|
irssi_ref_object(x)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
saved_args[n].v_glist = gl;
|
||||||
|
c_arg = &saved_args[n].v_glist;
|
||||||
|
} else if (strncmp(rec->args[n], "gslist_", 7) == 0) {
|
||||||
|
GSList *gsl;
|
||||||
|
AV *av;
|
||||||
|
SV *t;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
t = SvRV(arg);
|
||||||
|
if (SvTYPE(t) != SVt_PVAV) {
|
||||||
|
croak("Not an ARRAY reference");
|
||||||
|
}
|
||||||
|
av = (AV *)t;
|
||||||
|
|
||||||
|
gsl = NULL;
|
||||||
|
count = av_len(av) + 1;
|
||||||
|
while (count-- > 0) {
|
||||||
|
SV **x = av_fetch(av, count, 0);
|
||||||
|
gsl = g_slist_prepend(
|
||||||
|
gsl,
|
||||||
|
x == NULL ? NULL :
|
||||||
|
irssi_ref_object(*x)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
c_arg = saved_args[n].v_gslist = gsl;
|
||||||
|
} else {
|
||||||
|
c_arg = irssi_ref_object(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
p[n] = c_arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; n < SIGNAL_MAX_ARGUMENTS; ++n) {
|
||||||
|
p[n] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(cb_arg, p);
|
||||||
|
|
||||||
|
for (n = 0; n < SIGNAL_MAX_ARGUMENTS && n < n_args && rec->args[n] != NULL; ++n) {
|
||||||
|
SV *arg = args[n];
|
||||||
|
|
||||||
|
if (!SvOK(arg)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(rec->args[n], "intptr") == 0) {
|
||||||
|
SV *t = SvRV(arg);
|
||||||
|
SvIOK_only(t);
|
||||||
|
SvIV_set(t, saved_args[n].v_int);
|
||||||
|
} else if (strncmp(rec->args[n], "gslist_", 7) == 0) {
|
||||||
|
g_slist_free(saved_args[n].v_gslist);
|
||||||
|
} else if (strncmp(rec->args[n], "glistptr_", 9) == 0) {
|
||||||
|
int is_iobject, is_str;
|
||||||
|
AV *av;
|
||||||
|
GList *gl, *tmp;
|
||||||
|
|
||||||
|
is_iobject = strcmp(rec->args[n]+9, "iobject") == 0;
|
||||||
|
is_str = strcmp(rec->args[n]+9, "char*") == 0;
|
||||||
|
|
||||||
|
av = (AV *)SvRV(arg);
|
||||||
|
av_clear(av);
|
||||||
|
|
||||||
|
gl = saved_args[n].v_glist;
|
||||||
|
for (tmp = gl; tmp != NULL; tmp = tmp->next) {
|
||||||
|
av_push(av,
|
||||||
|
is_iobject ? iobject_bless((SERVER_REC *)tmp->data) :
|
||||||
|
is_str ? new_pv(tmp->data) :
|
||||||
|
irssi_bless_plain(rec->args[n]+9, tmp->data)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_str) {
|
||||||
|
g_list_foreach(gl, (GFunc)g_free, NULL);
|
||||||
|
}
|
||||||
|
g_list_free(gl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func,
|
static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func,
|
||||||
int signal_id, gconstpointer *args)
|
int signal_id, gconstpointer *args)
|
||||||
{
|
{
|
||||||
@ -95,15 +239,7 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func,
|
|||||||
rec != NULL && rec->args[n] != NULL; n++) {
|
rec != NULL && rec->args[n] != NULL; n++) {
|
||||||
arg = (void *) args[n];
|
arg = (void *) args[n];
|
||||||
|
|
||||||
if (strcmp(rec->args[n], "string") == 0)
|
if (strncmp(rec->args[n], "glistptr_", 9) == 0) {
|
||||||
perlarg = new_pv(arg);
|
|
||||||
else if (strcmp(rec->args[n], "int") == 0)
|
|
||||||
perlarg = newSViv((IV)arg);
|
|
||||||
else if (strcmp(rec->args[n], "ulongptr") == 0)
|
|
||||||
perlarg = newSViv(*(unsigned long *) arg);
|
|
||||||
else if (strcmp(rec->args[n], "intptr") == 0)
|
|
||||||
saved_args[n] = perlarg = newRV_noinc(newSViv(*(int *) arg));
|
|
||||||
else if (strncmp(rec->args[n], "glistptr_", 9) == 0) {
|
|
||||||
/* pointer to linked list - push as AV */
|
/* pointer to linked list - push as AV */
|
||||||
GList *tmp, **ptr;
|
GList *tmp, **ptr;
|
||||||
int is_iobject, is_str;
|
int is_iobject, is_str;
|
||||||
@ -121,7 +257,17 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func,
|
|||||||
}
|
}
|
||||||
|
|
||||||
saved_args[n] = perlarg = newRV_noinc((SV *) av);
|
saved_args[n] = perlarg = newRV_noinc((SV *) av);
|
||||||
} else if (strncmp(rec->args[n], "gslist_", 7) == 0) {
|
} else if (strcmp(rec->args[n], "int") == 0)
|
||||||
|
perlarg = newSViv((IV)arg);
|
||||||
|
else if (arg == NULL)
|
||||||
|
perlarg = &PL_sv_undef;
|
||||||
|
else if (strcmp(rec->args[n], "string") == 0)
|
||||||
|
perlarg = new_pv(arg);
|
||||||
|
else if (strcmp(rec->args[n], "ulongptr") == 0)
|
||||||
|
perlarg = newSViv(*(unsigned long *) arg);
|
||||||
|
else if (strcmp(rec->args[n], "intptr") == 0)
|
||||||
|
saved_args[n] = perlarg = newRV_noinc(newSViv(*(int *) arg));
|
||||||
|
else if (strncmp(rec->args[n], "gslist_", 7) == 0) {
|
||||||
/* linked list - push as AV */
|
/* linked list - push as AV */
|
||||||
GSList *tmp;
|
GSList *tmp;
|
||||||
int is_iobject;
|
int is_iobject;
|
||||||
@ -135,9 +281,6 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func,
|
|||||||
}
|
}
|
||||||
|
|
||||||
perlarg = newRV_noinc((SV *) av);
|
perlarg = newRV_noinc((SV *) av);
|
||||||
} else if (arg == NULL) {
|
|
||||||
/* don't bless NULL arguments */
|
|
||||||
perlarg = newSViv(0);
|
|
||||||
} else if (strcmp(rec->args[n], "iobject") == 0) {
|
} else if (strcmp(rec->args[n], "iobject") == 0) {
|
||||||
/* "irssi object" - any struct that has
|
/* "irssi object" - any struct that has
|
||||||
"int type; int chat_type" as it's first
|
"int type; int chat_type" as it's first
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
#ifndef __PERL_SIGNALS_H
|
#ifndef __PERL_SIGNALS_H
|
||||||
#define __PERL_SIGNALS_H
|
#define __PERL_SIGNALS_H
|
||||||
|
|
||||||
|
void perl_signal_args_to_c(void (*callback)(void *, void **), void *cb_arg,
|
||||||
|
int signal_id, SV **args, size_t n_args);
|
||||||
|
|
||||||
void perl_signal_add_full(const char *signal, SV *func, int priority);
|
void perl_signal_add_full(const char *signal, SV *func, int priority);
|
||||||
|
|
||||||
void perl_signal_remove(const char *signal, SV *func);
|
void perl_signal_remove(const char *signal, SV *func);
|
||||||
|
Loading…
Reference in New Issue
Block a user