diff options
-rw-r--r-- | isisd/isis_misc.h | 4 | ||||
-rw-r--r-- | lib/compiler.h | 62 | ||||
-rw-r--r-- | lib/log.h | 19 | ||||
-rw-r--r-- | lib/sbuf.h | 2 | ||||
-rw-r--r-- | lib/termtable.h | 5 | ||||
-rw-r--r-- | lib/vty.h | 4 | ||||
-rw-r--r-- | lib/zebra.h | 7 | ||||
-rw-r--r-- | tests/lib/test_printfrr.c | 2 |
8 files changed, 77 insertions, 28 deletions
diff --git a/isisd/isis_misc.h b/isisd/isis_misc.h index c551fde7d..fbfabaf24 100644 --- a/isisd/isis_misc.h +++ b/isisd/isis_misc.h @@ -79,9 +79,9 @@ enum { ISIS_UI_LEVEL_BRIEF, #include "lib/log.h" void log_multiline(int priority, const char *prefix, const char *format, ...) - PRINTF_ATTRIBUTE(3, 4); + PRINTFRR(3, 4); struct vty; void vty_multiline(struct vty *vty, const char *prefix, const char *format, ...) - PRINTF_ATTRIBUTE(3, 4); + PRINTFRR(3, 4); void vty_out_timestr(struct vty *vty, time_t uptime); #endif diff --git a/lib/compiler.h b/lib/compiler.h index 9ce91e336..218100417 100644 --- a/lib/compiler.h +++ b/lib/compiler.h @@ -218,6 +218,68 @@ extern "C" { #define array_size(ar) (sizeof(ar) / sizeof(ar[0])) +/* sigh. this is so ugly, it overflows and wraps to being nice again. + * + * printfrr() supports "%Ld" for <int64_t>, whatever that is typedef'd to. + * However, gcc & clang think that "%Ld" is <long long>, which doesn't quite + * match up since int64_t is <long> on a lot of 64-bit systems. + * + * If we have _FRR_ATTRIBUTE_PRINTFRR, we loaded a compiler plugin that + * replaces the whole format checking bits with a custom version that + * understands "%Ld" (along with "%pI4" and co.), so we don't need to do + * anything. + * + * If we don't have that attribute... we still want -Wformat to work. So, + * this is the "f*ck it" approach and we just redefine int64_t to always be + * <long long>. This should work until such a time that <long long> is + * something else (e.g. 128-bit integer)... let's just guard against that + * with the _Static_assert below and work with the world we have right now, + * where <long long> is always 64-bit. + */ + +/* these need to be included before any of the following, so we can + * "overwrite" things. + */ +#include <stdint.h> +#include <inttypes.h> + +#ifdef _FRR_ATTRIBUTE_PRINTFRR +#define PRINTFRR(a, b) __attribute__((printfrr(a, b))) + +#else /* !_FRR_ATTRIBUTE_PRINTFRR */ +#define PRINTFRR(a, b) __attribute__((format(printf, a, b))) + +/* these should be typedefs, but might also be #define */ +#ifdef uint64_t +#undef uint64_t +#endif +#ifdef int64_t +#undef int64_t +#endif + +/* can't overwrite the typedef, but we can replace int64_t with _int64_t */ +typedef unsigned long long _uint64_t; +#define uint64_t _uint64_t +typedef signed long long _int64_t; +#define int64_t _int64_t + +/* if this breaks, 128-bit machines may have entered reality (or <long long> + * is something weird) + */ +#if __STDC_VERSION__ >= 201112L +_Static_assert(sizeof(_uint64_t) == 8 && sizeof(_int64_t) == 8, + "nobody expects the spanish intquisition"); +#endif + +/* since we redefined int64_t, we also need to redefine PRI*64 */ +#undef PRIu64 +#undef PRId64 +#undef PRIx64 +#define PRIu64 "llu" +#define PRId64 "lld" +#define PRIx64 "llx" +#endif /* !_FRR_ATTRIBUTE_PRINTFRR */ + #ifdef __cplusplus } #endif @@ -81,20 +81,13 @@ extern void openzlog(const char *progname, const char *protoname, /* Close zlog function. */ extern void closezlog(void); -/* GCC have printf type attribute check. */ -#ifdef __GNUC__ -#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b))) -#else -#define PRINTF_ATTRIBUTE(a,b) -#endif /* __GNUC__ */ - /* Handy zlog functions. */ -extern void zlog_err(const char *format, ...) PRINTF_ATTRIBUTE(1, 2); -extern void zlog_warn(const char *format, ...) PRINTF_ATTRIBUTE(1, 2); -extern void zlog_info(const char *format, ...) PRINTF_ATTRIBUTE(1, 2); -extern void zlog_notice(const char *format, ...) PRINTF_ATTRIBUTE(1, 2); -extern void zlog_debug(const char *format, ...) PRINTF_ATTRIBUTE(1, 2); -extern void zlog(int priority, const char *format, ...) PRINTF_ATTRIBUTE(2, 3); +extern void zlog_err(const char *format, ...) PRINTFRR(1, 2); +extern void zlog_warn(const char *format, ...) PRINTFRR(1, 2); +extern void zlog_info(const char *format, ...) PRINTFRR(1, 2); +extern void zlog_notice(const char *format, ...) PRINTFRR(1, 2); +extern void zlog_debug(const char *format, ...) PRINTFRR(1, 2); +extern void zlog(int priority, const char *format, ...) PRINTFRR(2, 3); /* For logs which have error codes associated with them */ #define flog_err(ferr_id, format, ...) \ diff --git a/lib/sbuf.h b/lib/sbuf.h index b1518a3aa..9f0311006 100644 --- a/lib/sbuf.h +++ b/lib/sbuf.h @@ -78,7 +78,7 @@ const char *sbuf_buf(struct sbuf *buf); void sbuf_free(struct sbuf *buf); #include "lib/log.h" void sbuf_push(struct sbuf *buf, int indent, const char *format, ...) - PRINTF_ATTRIBUTE(3, 4); + PRINTFRR(3, 4); #ifdef __cplusplus } diff --git a/lib/termtable.h b/lib/termtable.h index 491010a85..4f7c595ce 100644 --- a/lib/termtable.h +++ b/lib/termtable.h @@ -137,8 +137,7 @@ void ttable_cell_del(struct ttable_cell *cell); * columns were specified */ struct ttable_cell *ttable_insert_row(struct ttable *tt, unsigned int row, - const char *format, ...) - PRINTF_ATTRIBUTE(3, 4); + const char *format, ...) PRINTFRR(3, 4); /** * Inserts a new row at the end of the table. * @@ -164,7 +163,7 @@ struct ttable_cell *ttable_insert_row(struct ttable *tt, unsigned int row, * columns were specified */ struct ttable_cell *ttable_add_row(struct ttable *tt, const char *format, ...) - PRINTF_ATTRIBUTE(2, 3); + PRINTFRR(2, 3); /** * Removes a row from the table. @@ -302,8 +302,8 @@ extern struct vty *vty_stdio(void (*atclose)(int isexit)); * - vty_endframe() clears the buffer without printing it, and prints an * extra string if the buffer was empty before (for context-end markers) */ -extern int vty_out(struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3); -extern void vty_frame(struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3); +extern int vty_out(struct vty *, const char *, ...) PRINTFRR(2, 3); +extern void vty_frame(struct vty *, const char *, ...) PRINTFRR(2, 3); extern void vty_endframe(struct vty *, const char *); bool vty_set_include(struct vty *vty, const char *regexp); diff --git a/lib/zebra.h b/lib/zebra.h index 2f9ada09b..51b4849f5 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -244,13 +244,6 @@ size_t strlcpy(char *__restrict dest, const char *__restrict src, size_t destsize); #endif -/* GCC have printf type attribute check. */ -#ifdef __GNUC__ -#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b))) -#else -#define PRINTF_ATTRIBUTE(a,b) -#endif /* __GNUC__ */ - /* * RFC 3542 defines several macros for using struct cmsghdr. * Here, we define those that are not present diff --git a/tests/lib/test_printfrr.c b/tests/lib/test_printfrr.c index c8ef150b0..24de3fa88 100644 --- a/tests/lib/test_printfrr.c +++ b/tests/lib/test_printfrr.c @@ -27,6 +27,7 @@ static int errors; +static void printcmp(const char *fmt, ...) PRINTFRR(1, 2); static void printcmp(const char *fmt, ...) { va_list ap; @@ -58,6 +59,7 @@ static void printcmp(const char *fmt, ...) errors++; } +static void printchk(const char *ref, const char *fmt, ...) PRINTFRR(2, 3); static void printchk(const char *ref, const char *fmt, ...) { va_list ap; |