From 4330dbec627d6bc1d2cd0c19fada7de4fd471bfc Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Mon, 11 May 2020 17:46:45 +0200 Subject: [PATCH 1/3] add "print format" signal to perl fix syntax in signals.txt with regards to GLists simplify signal emit code --- docs/signals.txt | 4 +- src/fe-common/core/fe-log.c | 6 +- src/fe-common/core/formats.c | 3 + src/fe-text/textbuffer-formats.c | 3 + src/perl/common/Core.xs | 38 ++-- src/perl/get-signals.pl | 5 +- src/perl/perl-signals.c | 312 ++++++++++++++++++------------- src/perl/perl-signals.h | 4 +- 8 files changed, 214 insertions(+), 161 deletions(-) diff --git a/docs/signals.txt b/docs/signals.txt index d7d42f5d..ff600cd3 100644 --- a/docs/signals.txt +++ b/docs/signals.txt @@ -251,7 +251,7 @@ FE common * Provides signals: completion.c: - "complete word", GList * of char*, WINDOW_REC, char *word, char *linestart, int *want_space + "complete word", GList * of char *s, WINDOW_REC, char *word, char *linestart, int *want_space fe-common-core.c: "irssi init read settings" @@ -285,6 +285,8 @@ keyboard.c: printtext.c: "print text", TEXT_DEST_REC *dest, char *text, char *stripped + "print format", THEME_REC *theme, char *module, TEXT_DEST_REC *dest, formatnum_args + "print noformat", TEXT_DEST_REC *dest, char *text themes.c: "theme created", THEME_REC diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index 12b6b643..b5222059 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -570,10 +570,10 @@ static void sig_print_format(THEME_REC *theme, const char *module, str = format_get_text_theme_charargs(log_theme, module, dest, GPOINTER_TO_INT(formatnum), args); - skip_next_printtext = TRUE; + if (str != NULL && *str != '\0') { + skip_next_printtext = TRUE; - if (*str != '\0') { - /* add the line start format */ + /* add the line start format */ linestart = format_get_level_tag(log_theme, dest); tmp = str; str = format_add_linestart(tmp, linestart); diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c index a4d3a023..eb47646e 100644 --- a/src/fe-common/core/formats.c +++ b/src/fe-common/core/formats.c @@ -650,6 +650,9 @@ char *format_get_text_theme_charargs(THEME_REC *theme, const char *module, MODULE_THEME_REC *module_theme; char *text; + if (module == NULL) + return NULL; + module_theme = g_hash_table_lookup(theme->modules, module); if (module_theme == NULL) return NULL; diff --git a/src/fe-text/textbuffer-formats.c b/src/fe-text/textbuffer-formats.c index edd14dbc..47f1735a 100644 --- a/src/fe-text/textbuffer-formats.c +++ b/src/fe-text/textbuffer-formats.c @@ -124,6 +124,9 @@ static void sig_print_format(THEME_REC *theme, const char *module, TEXT_DEST_REC if (!scrollback_format) return; + if (module == NULL) + return; + info = store_lineinfo_tmp(dest); formatnum = GPOINTER_TO_INT(formatnump); diff --git a/src/perl/common/Core.xs b/src/perl/common/Core.xs index 8e26f105..7ae18943 100644 --- a/src/perl/common/Core.xs +++ b/src/perl/common/Core.xs @@ -68,13 +68,15 @@ static void add_tuple(gpointer key_, gpointer value_, gpointer user_data) (void) 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_emit(void *signal, int params, void **p) +{ + signal_emit(signal, params, p[0], p[1], p[2], p[3], p[4], p[5]); } -static void wrap_signal_continue(void *dummy, void **p) { +static void wrap_signal_continue(void *dummy, int params, void **p) +{ (void)dummy; - signal_continue(6, p[0], p[1], p[2], p[3], p[4], p[5]); + signal_continue(params, p[0], p[1], p[2], p[3], p[4], p[5]); } MODULE = Irssi::Core PACKAGE = Irssi @@ -85,33 +87,14 @@ signal_emit(signal, ...) char *signal CODE: int signal_id; - SV *args[SIGNAL_MAX_ARGUMENTS]; - int n, used; signal_id = signal_get_uniq_id(signal); - used = items - 1; - if (used > SIGNAL_MAX_ARGUMENTS) { - used = SIGNAL_MAX_ARGUMENTS; - } - for (n = 0; n < used; ++n) { - args[n] = ST(n + 1); - } - perl_signal_args_to_c(wrap_signal_emit, signal, signal_id, args, used); + perl_signal_args_to_c(wrap_signal_emit, signal, signal_id, &ST(1), items - 1); void signal_continue(...) CODE: - SV *args[SIGNAL_MAX_ARGUMENTS]; - int n, used; - - used = items; - if (used > SIGNAL_MAX_ARGUMENTS) { - used = SIGNAL_MAX_ARGUMENTS; - } - 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); + perl_signal_args_to_c(wrap_signal_continue, NULL, signal_get_emitted_id(), &ST(0), items); void signal_add(...) @@ -162,7 +145,7 @@ PREINIT: HV *hv; HE *he; I32 len, pos; - const char *arr[7]; + const char *arr[SIGNAL_MAX_ARGUMENTS + 1]; CODE: if (items != 1 || !is_hvref(ST(0))) croak("Usage: Irssi::signal_register(hash)"); @@ -179,7 +162,8 @@ CODE: av = (AV *) SvRV(val); len = av_len(av)+1; - if (len > 6) len = 6; + if (len > SIGNAL_MAX_ARGUMENTS) + len = SIGNAL_MAX_ARGUMENTS; for (pos = 0; pos < len; pos++) { SV **val = av_fetch(av, pos, 0); arr[pos] = SvPV_nolen(*val); diff --git a/src/perl/get-signals.pl b/src/perl/get-signals.pl index 275be157..12aebdba 100755 --- a/src/perl/get-signals.pl +++ b/src/perl/get-signals.pl @@ -16,14 +16,15 @@ while (<>) { $signal = $1; $_ = $3; - s/GList \* of ([^,]*)/glistptr_\1/g; - s/GSList of (\w+)s/gslist_\1/g; + s/GList \* of ([^,]*)s/glistptr_\1/g; + s/GSList of ([^,]*)s/gslist_\1/g; s/char \*[^,]*/string/g; s/ulong \*[^,]*/ulongptr/g; s/int \*[^,]*/intptr/g; s/int [^,]*/int/g; + my %map = ( # core CHATNET_REC => 'iobject', diff --git a/src/perl/perl-signals.c b/src/perl/perl-signals.c index 59289588..27522f5e 100644 --- a/src/perl/perl-signals.c +++ b/src/perl/perl-signals.c @@ -21,10 +21,11 @@ #define NEED_PERL_H #define PERL_NO_GET_CONTEXT #include "module.h" -#include -#include #include +#include #include +#include +#include #include #include @@ -39,7 +40,7 @@ typedef struct { typedef struct { char *signal; - char *args[7]; + char *args[SIGNAL_MAX_ARGUMENTS + 1]; int dynamic; } PERL_SIGNAL_ARGS_REC; @@ -71,9 +72,8 @@ static PERL_SIGNAL_ARGS_REC *perl_signal_args_find(int signal_id) return NULL; } -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_args_to_c(void (*callback)(void *, int, void **), void *cb_arg, int signal_id, + SV **args, size_t n_args) { union { int v_int; @@ -83,136 +83,162 @@ void perl_signal_args_to_c( } saved_args[SIGNAL_MAX_ARGUMENTS]; void *p[SIGNAL_MAX_ARGUMENTS]; PERL_SIGNAL_ARGS_REC *rec; - size_t n; + char *arglist[MAX_FORMAT_PARAMS]; + 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); - } + 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]; + 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 (g_strcmp0(rec->args[n], "string") == 0) { - c_arg = SvPV_nolen(arg); - } else if (g_strcmp0(rec->args[n], "int") == 0) { - c_arg = (void *)SvIV(arg); - } else if (g_strcmp0(rec->args[n], "ulongptr") == 0) { - saved_args[n].v_ulong = SvUV(arg); - c_arg = &saved_args[n].v_ulong; - } else if (g_strcmp0(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; + if (g_strcmp0(rec->args[n], "formatnum_args") == 0 && n >= 3) { + const FORMAT_REC *formats; + const char *module; + int num; + int formatnum; - t = SvRV(arg); - if (SvTYPE(t) != SVt_PVAV) { - croak("Not an ARRAY reference"); - } - av = (AV *)t; + module = SvPV_nolen(args[n - 2]); + formatnum = format_find_tag(module, SvPV_nolen(arg)); + if (formatnum < 0) { /* format out of bounds */ + p[n - 2] = NULL; + break; + } - is_str = g_strcmp0(rec->args[n]+9, "char*") == 0; + formats = g_hash_table_lookup(default_formats, module); + arglist[formats[formatnum].params] = NULL; - 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; + p[n++] = GINT_TO_POINTER(formatnum); - t = SvRV(arg); - if (SvTYPE(t) != SVt_PVAV) { - croak("Not an ARRAY reference"); - } - av = (AV *)t; + for (num = 0; num < formats[formatnum].params; num++) { + if (n + num < n_args) + arglist[num] = SvPV_nolen(args[n + num]); + else + arglist[num] = ""; + } - 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++] = arglist; + n_args = n; - p[n] = c_arg; - } + break; + } else if (!SvOK(arg)) { + c_arg = NULL; + } else if (g_strcmp0(rec->args[n], "string") == 0) { + c_arg = SvPV_nolen(arg); + } else if (g_strcmp0(rec->args[n], "int") == 0) { + c_arg = (void *) SvIV(arg); + } else if (g_strcmp0(rec->args[n], "ulongptr") == 0) { + saved_args[n].v_ulong = SvUV(arg); + c_arg = &saved_args[n].v_ulong; + } else if (g_strcmp0(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; - for (; n < SIGNAL_MAX_ARGUMENTS; ++n) { - p[n] = NULL; - } + t = SvRV(arg); + if (SvTYPE(t) != SVt_PVAV) { + croak("Not an ARRAY reference"); + } + av = (AV *) t; - callback(cb_arg, p); + is_str = g_strcmp0(rec->args[n] + 9, "string") == 0 || + g_strcmp0(rec->args[n] + 9, "char*") == 0; /* deprecated form */ - for (n = 0; n < SIGNAL_MAX_ARGUMENTS && n < n_args && rec->args[n] != NULL; ++n) { - SV *arg = args[n]; + 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; - if (!SvOK(arg)) { - continue; - } + t = SvRV(arg); + if (SvTYPE(t) != SVt_PVAV) { + croak("Not an ARRAY reference"); + } + av = (AV *) t; - if (g_strcmp0(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; + 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); + } - is_iobject = g_strcmp0(rec->args[n]+9, "iobject") == 0; - is_str = g_strcmp0(rec->args[n]+9, "char*") == 0; + p[n] = c_arg; + } - av = (AV *)SvRV(arg); - av_clear(av); + for (; n < SIGNAL_MAX_ARGUMENTS; ++n) { + p[n] = NULL; + } - 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) - ); - } + callback(cb_arg, n_args, p); - if (is_str) { - g_list_foreach(gl, (GFunc)g_free, NULL); - } - g_list_free(gl); - } - } + for (n = 0; n < SIGNAL_MAX_ARGUMENTS && n < n_args && rec->args[n] != NULL; ++n) { + SV *arg = args[n]; + + if (!SvOK(arg)) { + continue; + } + + if (g_strcmp0(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 = g_strcmp0(rec->args[n] + 9, "iobject") == 0; + is_str = g_strcmp0(rec->args[n] + 9, "string") == 0 || + g_strcmp0(rec->args[n] + 9, "char*") == 0; /* deprecated form */ + + 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, @@ -246,7 +272,8 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func, int is_iobject, is_str; is_iobject = g_strcmp0(rec->args[n]+9, "iobject") == 0; - is_str = g_strcmp0(rec->args[n]+9, "char*") == 0; + is_str = g_strcmp0(rec->args[n] + 9, "string") == 0 || + g_strcmp0(rec->args[n] + 9, "char*") == 0; /* deprecated form */ av = newAV(); ptr = arg; @@ -267,8 +294,37 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func, else if (g_strcmp0(rec->args[n], "ulongptr") == 0) perlarg = newSViv(*(unsigned long *) arg); else if (g_strcmp0(rec->args[n], "intptr") == 0) - saved_args[n] = perlarg = newRV_noinc(newSViv(*(int *) arg)); - else if (strncmp(rec->args[n], "gslist_", 7) == 0) { + saved_args[n] = perlarg = newRV_noinc(newSViv(*(int *) arg)); + else if (g_strcmp0(rec->args[n], "formatnum_args") == 0 && n >= 3) { + const THEME_REC *theme; + const MODULE_THEME_REC *rec; + const FORMAT_REC *formats; + char *const *tmp; + int formatnum; + + theme = args[n - 3]; + if (theme == NULL) /* no theme */ + continue; + + rec = g_hash_table_lookup(theme->modules, args[n - 2]); + if (rec == NULL) /* no module in theme */ + continue; + + formats = g_hash_table_lookup(default_formats, args[n - 2]); + if (formats == NULL) /* no module in default_formats */ + continue; + + formatnum = GPOINTER_TO_INT(arg); + if (formatnum >= rec->count) /* format out of bounds */ + continue; + + XPUSHs(sv_2mortal(new_pv(formats[formatnum].tag))); + for (tmp = args[n + 1]; *tmp != NULL; tmp++) { + XPUSHs(sv_2mortal(new_pv(*tmp))); + } + + continue; + } else if (strncmp(rec->args[n], "gslist_", 7) == 0) { /* linked list - push as AV */ GSList *tmp; int is_iobject; @@ -338,8 +394,9 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func, out = g_list_append(out, val); } - if (g_strcmp0(rec->args[n]+9, "char*") == 0) - g_list_foreach(*ret, (GFunc) g_free, NULL); + if (g_strcmp0(rec->args[n] + 9, "string") == 0 || + g_strcmp0(rec->args[n] + 9, "char*") == 0) /* deprecated form */ + g_list_foreach(*ret, (GFunc) g_free, NULL); g_list_free(*ret); *ret = out; } @@ -349,12 +406,15 @@ static void perl_call_signal(PERL_SCRIPT_REC *script, SV *func, LEAVE; } +#if SIGNAL_MAX_ARGUMENTS != 6 +#error SIGNAL_MAX_ARGUMENTS changed - update code +#endif static void sig_func(const void *p1, const void *p2, const void *p3, const void *p4, const void *p5, const void *p6) { PERL_SIGNAL_REC *rec; - const void *args[6]; + const void *args[SIGNAL_MAX_ARGUMENTS]; args[0] = p1; args[1] = p2; args[2] = p3; args[3] = p4; args[4] = p5; args[5] = p6; @@ -553,7 +613,7 @@ void perl_signal_register(const char *signal, const char **args) return; rec = g_new0(PERL_SIGNAL_ARGS_REC, 1); - for (i = 0; i < 6 && args[i] != NULL; i++) + for (i = 0; i < SIGNAL_MAX_ARGUMENTS && args[i] != NULL; i++) rec->args[i] = g_strdup(args[i]); rec->dynamic = TRUE; rec->signal = g_strdup(signal); @@ -579,7 +639,7 @@ static void signal_args_free(PERL_SIGNAL_ARGS_REC *rec) if (!rec->dynamic) return; - for (i = 0; i < 6 && rec->args[i] != NULL; i++) + for (i = 0; i < SIGNAL_MAX_ARGUMENTS && rec->args[i] != NULL; i++) g_free(rec->args[i]); g_free(rec->signal); g_free(rec); diff --git a/src/perl/perl-signals.h b/src/perl/perl-signals.h index 8191a917..cb636d3c 100644 --- a/src/perl/perl-signals.h +++ b/src/perl/perl-signals.h @@ -1,8 +1,8 @@ #ifndef IRSSI_PERL_PERL_SIGNALS_H #define IRSSI_PERL_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_args_to_c(void (*callback)(void *, int, 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); From 3ea854816d378dd370575a4a557fbd2b80a55347 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Wed, 13 May 2020 00:03:36 +0200 Subject: [PATCH 2/3] Correct a wrong package for format_create_dest --- src/perl/ui/Formats.xs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/perl/ui/Formats.xs b/src/perl/ui/Formats.xs index c10f0b4e..8e34b7b9 100644 --- a/src/perl/ui/Formats.xs +++ b/src/perl/ui/Formats.xs @@ -104,7 +104,7 @@ PPCODE: g_free_not_null(ret); #******************************* -MODULE = Irssi::UI::Formats PACKAGE = Irssi::Window +MODULE = Irssi::UI::Formats PACKAGE = Irssi::UI::Window #******************************* void From b0cd72aadd62d6f018b36289635e7133f6988afc Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Wed, 13 May 2020 00:23:12 +0200 Subject: [PATCH 3/3] up abi --- src/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common.h b/src/common.h index 5fcf5d19..f2c50cde 100644 --- a/src/common.h +++ b/src/common.h @@ -6,7 +6,7 @@ #define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */ #define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */ -#define IRSSI_ABI_VERSION 27 +#define IRSSI_ABI_VERSION 28 #define DEFAULT_SERVER_ADD_PORT 6667 #define DEFAULT_SERVER_ADD_TLS_PORT 6697