From cda55d7de41c5cd5bd0ec42fa4f7500f8c763825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 7 May 2021 16:40:19 +0200 Subject: [PATCH 1/5] log: add va_list versions of log_* functions --- log.c | 78 ++++++++++++++++++++++++++++++++++++++--------------------- log.h | 28 ++++++++++++++++----- 2 files changed, 73 insertions(+), 33 deletions(-) diff --git a/log.c b/log.c index 8b4e8131..fba53876 100644 --- a/log.c +++ b/log.c @@ -122,43 +122,67 @@ _sys_log(enum log_class log_class, const char *module, syslog(level, "%s: %s", module, msg); } +void +log_msg_va(enum log_class log_class, const char *module, + const char *file, int lineno, const char *fmt, va_list va) +{ + va_list va2; + va_copy(va2, va); + _log(log_class, module, file, lineno, fmt, 0, va); + _sys_log(log_class, module, file, lineno, fmt, 0, va2); + va_end(va2); +} + void log_msg(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, ...) { - va_list ap1, ap2; - va_start(ap1, fmt); - va_copy(ap2, ap1); - _log(log_class, module, file, lineno, fmt, 0, ap1); - _sys_log(log_class, module, file, lineno, fmt, 0, ap2); - va_end(ap1); - va_end(ap2); + va_list va; + va_start(va, fmt); + log_msg_va(log_class, module, file, lineno, fmt, va); + va_end(va); } -void log_errno(enum log_class log_class, const char *module, - const char *file, int lineno, - const char *fmt, ...) +void +log_errno_va(enum log_class log_class, const char *module, + const char *file, int lineno, + const char *fmt, va_list va) { - va_list ap1, ap2; - va_start(ap1, fmt); - va_copy(ap2, ap1); - _log(log_class, module, file, lineno, fmt, errno, ap1); - _sys_log(log_class, module, file, lineno, fmt, errno, ap2); - va_end(ap1); - va_end(ap2); + log_errno_provided_va(log_class, module, file, lineno, errno, fmt, va); } -void log_errno_provided(enum log_class log_class, const char *module, - const char *file, int lineno, int errno_copy, - const char *fmt, ...) +void +log_errno(enum log_class log_class, const char *module, + const char *file, int lineno, + const char *fmt, ...) { - va_list ap1, ap2; - va_start(ap1, fmt); - va_copy(ap2, ap1); - _log(log_class, module, file, lineno, fmt, errno_copy, ap1); - _sys_log(log_class, module, file, lineno, fmt, errno_copy, ap2); - va_end(ap1); - va_end(ap2); + va_list va; + va_start(va, fmt); + log_errno_va(log_class, module, file, lineno, fmt, va); + va_end(va); +} + +void +log_errno_provided_va(enum log_class log_class, const char *module, + const char *file, int lineno, int errno_copy, + const char *fmt, va_list va) +{ + va_list va2; + va_copy(va2, va); + _log(log_class, module, file, lineno, fmt, errno_copy, va); + _sys_log(log_class, module, file, lineno, fmt, errno_copy, va2); + va_end(va2); +} + +void +log_errno_provided(enum log_class log_class, const char *module, + const char *file, int lineno, int errno_copy, + const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + log_errno_provided_va(log_class, module, file, lineno, errno_copy, fmt, va); + va_end(va); } int diff --git a/log.h b/log.h index f0c28d7b..367fd60e 100644 --- a/log.h +++ b/log.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include "macros.h" enum log_colorize { LOG_COLORIZE_NEVER, LOG_COLORIZE_ALWAYS, LOG_COLORIZE_AUTO }; @@ -10,19 +11,34 @@ void log_init(enum log_colorize colorize, bool do_syslog, enum log_facility syslog_facility, enum log_class log_level); void log_deinit(void); -void log_msg(enum log_class log_class, const char *module, - const char *file, int lineno, - const char *fmt, ...) PRINTF(5); +void log_msg( + enum log_class log_class, const char *module, + const char *file, int lineno, + const char *fmt, ...) PRINTF(5); -void log_errno(enum log_class log_class, const char *module, - const char *file, int lineno, - const char *fmt, ...) PRINTF(5); +void log_errno( + enum log_class log_class, const char *module, + const char *file, int lineno, + const char *fmt, ...) PRINTF(5); void log_errno_provided( enum log_class log_class, const char *module, const char *file, int lineno, int _errno, const char *fmt, ...) PRINTF(6); +void log_msg_va( + enum log_class log_class, const char *module, + const char *file, int lineno, const char *fmt, va_list va) VPRINTF(5); +void log_errno_va( + enum log_class log_class, const char *module, + const char *file, int lineno, + const char *fmt, va_list va) VPRINTF(5); +void log_errno_provided_va( + enum log_class log_class, const char *module, + const char *file, int lineno, int _errno, + const char *fmt, va_list va) VPRINTF(6); + + int log_level_from_string(const char *str); const char *log_level_string_hint(void); From 7af475098b48b3338b884f738e7360ad55d4a14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 7 May 2021 16:41:02 +0200 Subject: [PATCH 2/5] xmalloc: export xvasprintf() --- xmalloc.c | 2 +- xmalloc.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/xmalloc.c b/xmalloc.c index 28af50f9..9e305061 100644 --- a/xmalloc.c +++ b/xmalloc.c @@ -71,7 +71,7 @@ xvasprintf_(char **strp, const char *format, va_list ap) return vsnprintf(*strp, n + 1, format, ap); } -static VPRINTF(1) char * +char * xvasprintf(const char *format, va_list ap) { char *str; diff --git a/xmalloc.h b/xmalloc.h index 13d69ca4..bc0dd2d8 100644 --- a/xmalloc.h +++ b/xmalloc.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include "macros.h" @@ -10,4 +11,5 @@ void *xrealloc(void *ptr, size_t size); char *xstrdup(const char *str) XSTRDUP; char *xstrndup(const char *str, size_t n) XSTRDUP; char *xasprintf(const char *format, ...) PRINTF(1) XMALLOC; +char *xvasprintf(const char *format, va_list va) VPRINTF(1) XMALLOC; wchar_t *xwcsdup(const wchar_t *str) XSTRDUP; From 0b97740bd02df274c1a3e26f294e827c8e5cfae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 7 May 2021 16:41:10 +0200 Subject: [PATCH 3/5] config: implement LOG_AND_NOTIFY_* macros in terms of no-inline functions Reduces code size by quite a lot: From: section size addr .text 37857 0 ... Total 45169 To: section size addr .text 31681 0 ... Total 38993 LTO release build goes from 500K -> 492K --- config.c | 103 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 35 deletions(-) diff --git a/config.c b/config.c index bf6e125a..69af3573 100644 --- a/config.c +++ b/config.c @@ -91,43 +91,76 @@ static const char *const binding_action_map[] = { static_assert(ALEN(binding_action_map) == BIND_ACTION_COUNT, "binding action map size mismatch"); -#define LOG_AND_NOTIFY_ERR(...) \ - do { \ - LOG_ERR(__VA_ARGS__); \ - char *text = xasprintf(__VA_ARGS__); \ - struct user_notification notif = { \ - .kind = USER_NOTIFICATION_ERROR, \ - .text = text, \ - }; \ - tll_push_back(conf->notifications, notif); \ - } while (0) +static void NOINLINE PRINTF(5) +log_and_notify(struct config *conf, enum log_class log_class, + const char *file, int lineno, const char *fmt, ...) +{ + enum user_notification_kind kind; -#define LOG_AND_NOTIFY_WARN(...) \ - do { \ - LOG_WARN(__VA_ARGS__); \ - char *text = xasprintf(__VA_ARGS__); \ - struct user_notification notif = { \ - .kind = USER_NOTIFICATION_WARNING, \ - .text = text, \ - }; \ - tll_push_back(conf->notifications, notif); \ - } while (0) + switch (log_class) { + case LOG_CLASS_WARNING: kind = USER_NOTIFICATION_WARNING; break; + case LOG_CLASS_ERROR: kind = USER_NOTIFICATION_ERROR; break; -#define LOG_AND_NOTIFY_ERRNO(...) \ - do { \ - int errno_copy = errno; \ - LOG_ERRNO(__VA_ARGS__); \ - int len = snprintf(NULL, 0, __VA_ARGS__); \ - int errno_len = snprintf(NULL, 0, ": %s", strerror(errno_copy)); \ - char *text = xmalloc(len + errno_len + 1); \ - snprintf(text, len + errno_len + 1, __VA_ARGS__); \ - snprintf(&text[len], errno_len + 1, ": %s", strerror(errno_copy)); \ - struct user_notification notif = { \ - .kind = USER_NOTIFICATION_ERROR, \ - .text = text, \ - }; \ - tll_push_back(conf->notifications, notif); \ - } while(0) + case LOG_CLASS_INFO: + case LOG_CLASS_DEBUG: + BUG("unsupported log class: %d", log_class); + break; + } + + va_list va1, va2; + va_start(va1, fmt); + va_copy(va2, va1); + + log_msg_va(log_class, LOG_MODULE, file, lineno, fmt, va1); + + char *text = xvasprintf(fmt, va2); + tll_push_back( + conf->notifications, + ((struct user_notification){.kind = kind, .text = text})); + + va_end(va2); + va_end(va1); +} + +static void NOINLINE PRINTF(5) +log_errno_and_notify(struct config *conf, enum log_class log_class, + const char *file, int lineno, const char *fmt, ...) +{ + int errno_copy = errno; + + va_list va1, va2, va3; + va_start(va1, fmt); + va_copy(va2, va1); + va_copy(va3, va2); + + log_errno_provided_va( + log_class, LOG_MODULE, file, lineno, errno_copy, fmt, va1); + + int len = vsnprintf(NULL, 0, fmt, va2); + int errno_len = snprintf(NULL, 0, ": %s", strerror(errno_copy)); + + char *text = xmalloc(len + errno_len + 1); + vsnprintf(text, len + errno_len + 1, fmt, va3); + snprintf(&text[len], errno_len + 1, ": %s", strerror(errno_copy)); + + tll_push_back( + conf->notifications, + ((struct user_notification){ + .kind = USER_NOTIFICATION_ERROR, .text = text})); + + va_end(va3); + va_end(va2); + va_end(va1); +} + +#define LOG_AND_NOTIFY_ERR(...) \ + log_and_notify(conf, LOG_CLASS_ERROR, __FILE__, __LINE__, __VA_ARGS__) + +#define LOG_AND_NOTIFY_WARN(...) \ + log_and_notify(conf, LOG_CLASS_WARNING, __FILE__, __LINE__, __VA_ARGS__) + +#define LOG_AND_NOTIFY_ERRNO(...) \ + log_errno_and_notify(conf, LOG_CLASS_ERROR, __FILE__, __LINE__, __VA_ARGS__) static char * get_shell(void) From 449ac7c361f6e16c499c402b261ed7c82a3e83d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 7 May 2021 17:18:27 +0200 Subject: [PATCH 4/5] =?UTF-8?q?config:=20don=E2=80=99t=20inline=20str=5Fto?= =?UTF-8?q?=5F*()=20functions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/config.c b/config.c index 69af3573..ba71a60b 100644 --- a/config.c +++ b/config.c @@ -362,7 +362,7 @@ done: goto out; } -static bool +static bool NOINLINE str_to_bool(const char *s) { return strcasecmp(s, "on") == 0 || @@ -371,7 +371,7 @@ str_to_bool(const char *s) strtoul(s, NULL, 0) > 0; } -static bool +static bool NOINLINE str_to_ulong(const char *s, int base, unsigned long *res) { if (s == NULL) @@ -384,7 +384,7 @@ str_to_ulong(const char *s, int base, unsigned long *res) return errno == 0 && *end == '\0'; } -static bool +static bool NOINLINE str_to_double(const char *s, double *res) { if (s == NULL) @@ -397,7 +397,7 @@ str_to_double(const char *s, double *res) return errno == 0 && *end == '\0'; } -static bool +static bool NOINLINE str_to_wchars(const char *s, wchar_t **res, struct config *conf, const char *path, int lineno, const char *section, const char *key) @@ -416,7 +416,7 @@ str_to_wchars(const char *s, wchar_t **res, struct config *conf, return true; } -static bool +static bool NOINLINE str_to_color(const char *s, uint32_t *color, bool allow_alpha, struct config *conf, const char *path, int lineno, const char *section, const char *key) @@ -439,7 +439,7 @@ str_to_color(const char *s, uint32_t *color, bool allow_alpha, return true; } -static bool +static bool NOINLINE str_to_two_colors(const char *s, uint32_t *first, uint32_t *second, bool allow_alpha, struct config *conf, const char *path, int lineno, const char *section, const char *key) @@ -463,7 +463,7 @@ str_to_two_colors(const char *s, uint32_t *first, uint32_t *second, return true; } -static bool +static bool NOINLINE str_to_pt_or_px(const char *s, struct pt_or_px *res, struct config *conf, const char *path, int lineno, const char *section, const char *key) { @@ -497,7 +497,7 @@ str_to_pt_or_px(const char *s, struct pt_or_px *res, struct config *conf, return true; } -static bool +static bool NOINLINE str_to_spawn_template(struct config *conf, const char *s, struct config_spawn_template *template, const char *path, int lineno, const char *section, From ba2c3606bf35a848183f2280868b305b50632765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 7 May 2021 17:18:46 +0200 Subject: [PATCH 5/5] config: avoid tll() code expansion when generating default bindings tll_push_back() is a macro that results in quite a lot of instructions. Expanding this macro explicitly in many places thus causes code explosion. This is what happened in when we generate the default key/mouse bindings. Fix by calling tll_push_back() in a no-inline function. Reduces code size with ~4-5K --- config.c | 60 ++++++++++++++++++++++++++++++-------------------------- config.h | 3 ++- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/config.c b/config.c index ba71a60b..ce999adf 100644 --- a/config.c +++ b/config.c @@ -2132,15 +2132,20 @@ get_server_socket_path(void) return xasprintf("%s/foot-%s.sock", xdg_runtime, wayland_display); } +static void NOINLINE +add_key_binding(config_key_binding_list_t *list, int action, + const struct config_key_modifiers *mods, xkb_keysym_t sym) +{ + tll_push_back( + *list, + ((struct config_key_binding){action, *mods, sym})); +} + static void add_default_key_bindings(struct config *conf) { -#define add_binding(action, mods, sym) \ - do { \ - tll_push_back( \ - conf->bindings.key, \ - ((struct config_key_binding){action, mods, sym})); \ - } while (0) + #define add_binding(action, mods, sym) \ + add_key_binding(&conf->bindings.key, action, &mods, sym) const struct config_key_modifiers shift = {.shift = true}; const struct config_key_modifiers ctrl = {.ctrl = true}; @@ -2162,18 +2167,15 @@ add_default_key_bindings(struct config *conf) add_binding(BIND_ACTION_SPAWN_TERMINAL, ctrl_shift, XKB_KEY_n); add_binding(BIND_ACTION_SHOW_URLS_LAUNCH, ctrl_shift, XKB_KEY_u); -#undef add_binding + #undef add_binding } + static void add_default_search_bindings(struct config *conf) { -#define add_binding(action, mods, sym) \ - do { \ - tll_push_back( \ - conf->bindings.search, \ - ((struct config_key_binding){action, mods, sym})); \ -} while (0) + #define add_binding(action, mods, sym) \ + add_key_binding(&conf->bindings.search, action, &mods, sym) const struct config_key_modifiers none = {0}; const struct config_key_modifiers alt = {.alt = true}; @@ -2210,18 +2212,14 @@ add_default_search_bindings(struct config *conf) add_binding(BIND_ACTION_SEARCH_CLIPBOARD_PASTE, ctrl, XKB_KEY_y); add_binding(BIND_ACTION_SEARCH_PRIMARY_PASTE, shift, XKB_KEY_Insert); -#undef add_binding + #undef add_binding } static void add_default_url_bindings(struct config *conf) { -#define add_binding(action, mods, sym) \ - do { \ - tll_push_back( \ - conf->bindings.url, \ - ((struct config_key_binding){action, mods, sym})); \ -} while (0) + #define add_binding(action, mods, sym) \ + add_key_binding(&conf->bindings.url, action, &mods, sym) const struct config_key_modifiers none = {0}; const struct config_key_modifiers ctrl = {.ctrl = true}; @@ -2231,18 +2229,24 @@ add_default_url_bindings(struct config *conf) add_binding(BIND_ACTION_URL_CANCEL, none, XKB_KEY_Escape); add_binding(BIND_ACTION_URL_TOGGLE_URL_ON_JUMP_LABEL, none, XKB_KEY_t); -#undef add_binding + #undef add_binding +} + +static void NOINLINE +add_mouse_binding(config_mouse_binding_list_t *list, int action, + const struct config_key_modifiers *mods, + int button, int count) +{ + tll_push_back( + *list, + ((struct config_mouse_binding){action, *mods, button, count, {0}})); } static void add_default_mouse_bindings(struct config *conf) { -#define add_binding(action, mods, btn, count) \ - do { \ - tll_push_back( \ - conf->bindings.mouse, \ - ((struct config_mouse_binding){action, mods, btn, count, {0}})); \ -} while (0) + #define add_binding(action, mods, btn, count) \ + add_mouse_binding(&conf->bindings.mouse, action, &mods, btn, count) const struct config_key_modifiers none = {0}; const struct config_key_modifiers ctrl = {.ctrl = true}; @@ -2256,7 +2260,7 @@ add_default_mouse_bindings(struct config *conf) add_binding(BIND_ACTION_SELECT_WORD_WS, ctrl, BTN_LEFT, 2); add_binding(BIND_ACTION_SELECT_ROW, none, BTN_LEFT, 3); -#undef add_binding + #undef add_binding } bool diff --git a/config.h b/config.h index 8e67d398..db0e6775 100644 --- a/config.h +++ b/config.h @@ -52,6 +52,7 @@ struct config_mouse_binding { int count; struct config_binding_pipe pipe; }; +typedef tll(struct config_mouse_binding) config_mouse_binding_list_t; struct config_spawn_template { char *raw_cmd; @@ -166,7 +167,7 @@ struct config { struct { /* Bindings for "normal" mode */ config_key_binding_list_t key; - tll(struct config_mouse_binding) mouse; + config_mouse_binding_list_t mouse; /* * Special modes