Back in 2007, bb_simple_perror_msg() was introduced to allow for a lower overhead call to bb_perror_msg() when only a string was being printed with no parameters. This saves space because it avoids the overhead of a call to a variadic function. However there has never been a simple version of bb_error_msg(), and since that time various new calls to bb_perror_msg() have been added that only take a single parameter and so could have been using bb_simple_perror_message().
This changeset introduces 'simple' versions of bb_error_msg(), bb_error_msg_and_die(), bb_herror_msg() and bb_herror_msg_and_die(), and also overrides the standard versions with macros that use some preprocessor magic to automatically substitute any calls that only take a single parameter with the corresponding 'simple' version. All calls to the standard functions in the codebase that pass something like ("%s", arg) as the parameters have been replaced with 'simple' calls, as the macros can't fix these up. The space saving gained by this (using 'defconfig' on x86_64 with gcc Ubuntu 6.4.0-17ubuntu1~16.04) was: ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 4/301 up/down: 73/-910) Total: -837 bytes text data bss dec hex filename 936949 4263 1856 943068 e63dc busybox_old 936098 4263 1856 942217 e6089 busybox_unstripped Signed-off-by: James Byrne <james.by...@origamienergy.com> --- include/libbb.h | 19 +++++++++++++++++++ libbb/herror_msg.c | 10 ++++++++++ libbb/verror_msg.c | 10 ++++++++++ libbb/xgethostbyname.c | 2 +- miscutils/chat.c | 2 +- networking/arp.c | 10 +++++----- networking/tftp.c | 2 +- networking/wget.c | 2 +- shell/hush.c | 2 +- util-linux/acpid.c | 2 +- util-linux/fsck_minix.c | 2 +- util-linux/mount.c | 4 ++-- 12 files changed, 53 insertions(+), 14 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index a605c7f..23ad68d 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1286,19 +1286,38 @@ extern void (*die_func)(void); void xfunc_die(void) NORETURN FAST_FUNC; void bb_show_usage(void) NORETURN FAST_FUNC; void bb_error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; +void bb_simple_error_msg(const char *s) FAST_FUNC; void bb_error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC; +void bb_simple_error_msg_and_die(const char *s) NORETURN FAST_FUNC; void bb_perror_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; void bb_simple_perror_msg(const char *s) FAST_FUNC; void bb_perror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC; void bb_simple_perror_msg_and_die(const char *s) NORETURN FAST_FUNC; void bb_herror_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; +void bb_simple_herror_msg(const char *s) NORETURN FAST_FUNC; void bb_herror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC; +void bb_simple_herror_msg_and_die(const char *s) NORETURN FAST_FUNC; void bb_perror_nomsg_and_die(void) NORETURN FAST_FUNC; void bb_perror_nomsg(void) FAST_FUNC; void bb_verror_msg(const char *s, va_list p, const char *strerr) FAST_FUNC; void bb_die_memory_exhausted(void) NORETURN FAST_FUNC; void bb_logenv_override(void) FAST_FUNC; +/* Override bb_error_msg() and related functions with macros that will + * substitute them for the equivalent bb_simple_error_msg() function when + * they are used with only a single parameter. Macro approach inspired by + * https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments and + * https://gustedt.wordpress.com/2010/06/03/default-arguments-for-c99 + */ +#define _ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15 +#define BB_MSG_KIND(...) _ARG16(__VA_ARGS__, , , , , , , , , , , , , , , _simple) +#define _BB_MSG(name, kind, ...) bb##kind##name(__VA_ARGS__) +#define BB_MSG(name, kind, ...) _BB_MSG(name, kind, __VA_ARGS__) +#define bb_error_msg(...) BB_MSG(_error_msg, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) +#define bb_error_msg_and_die(...) BB_MSG(_error_msg_and_die, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) +#define bb_perror_msg(...) BB_MSG(_perror_msg, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) +#define bb_perror_msg_and_die(...) BB_MSG(_perror_msg_and_die, BB_MSG_KIND(__VA_ARGS__), __VA_ARGS__) + /* We need to export XXX_main from libbusybox * only if we build "individual" binaries */ diff --git a/libbb/herror_msg.c b/libbb/herror_msg.c index d041076..a7dd986 100644 --- a/libbb/herror_msg.c +++ b/libbb/herror_msg.c @@ -26,3 +26,13 @@ void FAST_FUNC bb_herror_msg_and_die(const char *s, ...) va_end(p); xfunc_die(); } + +void FAST_FUNC bb_simple_herror_msg(const char *s) +{ + bb_herror_msg("%s", s); +} + +void FAST_FUNC bb_simple_herror_msg_and_die(const char *s) +{ + bb_herror_msg_and_die("%s", s); +} diff --git a/libbb/verror_msg.c b/libbb/verror_msg.c index 22c3035..155b28c 100644 --- a/libbb/verror_msg.c +++ b/libbb/verror_msg.c @@ -180,3 +180,13 @@ void FAST_FUNC bb_error_msg(const char *s, ...) bb_verror_msg(s, p, NULL); va_end(p); } + +void FAST_FUNC bb_simple_error_msg(const char *s) +{ + bb_error_msg("%s", s); +} + +void FAST_FUNC bb_simple_error_msg_and_die(const char *s) +{ + bb_error_msg_and_die("%s", s); +} diff --git a/libbb/xgethostbyname.c b/libbb/xgethostbyname.c index 89d0329..9446dab 100644 --- a/libbb/xgethostbyname.c +++ b/libbb/xgethostbyname.c @@ -12,6 +12,6 @@ struct hostent* FAST_FUNC xgethostbyname(const char *name) { struct hostent *retval = gethostbyname(name); if (!retval) - bb_herror_msg_and_die("%s", name); + bb_simple_herror_msg_and_die(name); return retval; } diff --git a/miscutils/chat.c b/miscutils/chat.c index 2dfe52c..574d514 100644 --- a/miscutils/chat.c +++ b/miscutils/chat.c @@ -307,7 +307,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv) } else if (DIR_SAY == key) { // just print argument verbatim // TODO: should we use full_write() to avoid unistd/stdio conflict? - bb_error_msg("%s", arg); + bb_simple_error_msg(arg); } // next, please! argv++; diff --git a/networking/arp.c b/networking/arp.c index 177ab15..0fe4409 100644 --- a/networking/arp.c +++ b/networking/arp.c @@ -116,7 +116,7 @@ static int arp_del(char **args) /* Resolve the host name. */ host = *args; if (ap->input(host, &sa) < 0) { - bb_herror_msg_and_die("%s", host); + bb_simple_herror_msg_and_die(host); } /* If a host has more than one address, use the correct one! */ @@ -173,7 +173,7 @@ static int arp_del(char **args) if (strcmp(*args, "255.255.255.255") != 0) { host = *args; if (ap->input(host, &sa) < 0) { - bb_herror_msg_and_die("%s", host); + bb_simple_herror_msg_and_die(host); } memcpy(&req.arp_netmask, &sa, sizeof(struct sockaddr)); req.arp_flags |= ATF_NETMASK; @@ -261,7 +261,7 @@ static int arp_set(char **args) host = *args++; if (ap->input(host, &sa) < 0) { - bb_herror_msg_and_die("%s", host); + bb_simple_herror_msg_and_die(host); } /* If a host has more than one address, use the correct one! */ memcpy(&req.arp_pa, &sa, sizeof(struct sockaddr)); @@ -326,7 +326,7 @@ static int arp_set(char **args) if (strcmp(*args, "255.255.255.255") != 0) { host = *args; if (ap->input(host, &sa) < 0) { - bb_herror_msg_and_die("%s", host); + bb_simple_herror_msg_and_die(host); } memcpy(&req.arp_netmask, &sa, sizeof(struct sockaddr)); flags |= ATF_NETMASK; @@ -422,7 +422,7 @@ static int arp_show(char *name) if (name != NULL) { /* Resolve the host name. */ if (ap->input(name, &sa) < 0) { - bb_herror_msg_and_die("%s", name); + bb_simple_herror_msg_and_die(name); } host = xstrdup(ap->sprint(&sa, 1)); } diff --git a/networking/tftp.c b/networking/tftp.c index 4cd3918..0f56380 100644 --- a/networking/tftp.c +++ b/networking/tftp.c @@ -736,7 +736,7 @@ static int tftp_protocol( strcpy(G_error_pkt_str, bb_msg_read_error); send_err_pkt: if (G_error_pkt_str[0]) - bb_error_msg("%s", G_error_pkt_str); + bb_simple_error_msg(G_error_pkt_str); G.error_pkt[1] = TFTP_ERROR; xsendto(socket_fd, G.error_pkt, 4 + 1 + strlen(G_error_pkt_str), &peer_lsa->u.sa, peer_lsa->len); diff --git a/networking/wget.c b/networking/wget.c index 30c3392..80683f6 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -772,7 +772,7 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ #endif if (ftpcmd(NULL, NULL, sfp) != 220) - bb_error_msg_and_die("%s", G.wget_buf); + bb_simple_error_msg_and_die(G.wget_buf); /* note: ftpcmd() sanitizes G.wget_buf, ok to print */ /* Split username:password pair */ diff --git a/shell/hush.c b/shell/hush.c index c777001..a5e1745 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -9998,7 +9998,7 @@ static int FAST_FUNC builtin_read(char **argv) } if ((uintptr_t)r > 1) { - bb_error_msg("%s", r); + bb_simple_error_msg(r); r = (char*)(uintptr_t)1; } diff --git a/util-linux/acpid.c b/util-linux/acpid.c index 4f491fa..eded6b0 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c @@ -148,7 +148,7 @@ static void process_event(const char *event) const char *args[] = { "run-parts", handler, NULL }; // log the event - bb_error_msg("%s", event); + bb_simple_error_msg(event); // spawn handler // N.B. run-parts would require scripts to have #!/bin/sh diff --git a/util-linux/fsck_minix.c b/util-linux/fsck_minix.c index c4612f2..fc9aecc 100644 --- a/util-linux/fsck_minix.c +++ b/util-linux/fsck_minix.c @@ -321,7 +321,7 @@ static void die(const char *str) { if (termios_set) tcsetattr_stdin_TCSANOW(&sv_termios); - bb_error_msg_and_die("%s", str); + bb_simple_error_msg_and_die(str); } static void push_filename(const char *name) diff --git a/util-linux/mount.c b/util-linux/mount.c index fa2e7b1..41ce2fb 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -1292,7 +1292,7 @@ static NOINLINE int nfsmount(struct mntent *mp, unsigned long vfsflags, char *fi if (!inet_aton(hostname, &server_addr.sin_addr)) { hp = gethostbyname(hostname); if (hp == NULL) { - bb_herror_msg("%s", hostname); + bb_simple_herror_msg(hostname); goto fail; } if (hp->h_length != (int)sizeof(struct in_addr)) { @@ -1587,7 +1587,7 @@ static NOINLINE int nfsmount(struct mntent *mp, unsigned long vfsflags, char *fi } else { hp = gethostbyname(mounthost); if (hp == NULL) { - bb_herror_msg("%s", mounthost); + bb_simple_herror_msg(mounthost); goto fail; } if (hp->h_length != (int)sizeof(struct in_addr)) { -- 2.7.4 The contents of this email and any attachment are confidential to the intended recipient(s). If you are not an intended recipient: (i) do not use, disclose, distribute, copy or publish this email or its contents; (ii) please contact the sender immediately; and (iii) delete this email. Origami Energy Limited (company number 8619644); Origami Storage Limited (company number 10436515) and OSSPV001 Limited (company number 10933403), each registered in England and each with a registered office at: Ashcombe Court, Woolsack Way, Godalming, GU7 1LQ. _______________________________________________ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox