From c3ee4e375bb90d6ded7d9ebc01e26876d9c83799 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 9 Dec 2024 17:40:51 +0100 Subject: [PATCH] MINOR: tools: make fddebug() automatically emit the location fddebug() is sometimes quite helpful, but annoying to use when following a call path because it's a pain to always repeat the function name and call place. Let's have it automatically prepend the function name, the file name and the line number, and make its arguments optional, replacing them by a simple LF when all absent. This way, simply placing: fddebug(); is sufficient to emit a location follocing "[%s@%s:%d]\n". This function must not be used in production (and even call places with it shouldn't be committed) and it should only be used by developers, so the simplest the better. --- include/haproxy/tools.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h index 4f90a05ec..ef2f5c4ec 100644 --- a/include/haproxy/tools.h +++ b/include/haproxy/tools.h @@ -1028,9 +1028,27 @@ void make_word_fingerprint(uint8_t *fp, const char *word); int word_fingerprint_distance(const uint8_t *fp1, const uint8_t *fp2); /* debugging macro to emit messages using write() on fd #-1 so that strace sees - * them. + * them. It relies on variadic macros with optional arguments so that any + * number of argument is accepted. If at least one argument is passed, the + * first one is a format string and the other ones are the arguments, exactly + * like printf(). The macro always prepends the function name and the location + * as file:line between square brackets on any line. If no format string is + * passed, then "\n" is used. Otherwise the caller has to deal with \n itself + * (format or data). */ -#define fddebug(msg...) do { char *_m = NULL; memprintf(&_m, ##msg); if (_m) write(-1, _m, strlen(_m)); free(_m); } while (0) +#define fddebug(...) __fddebug(__VA_ARGS__) +#define _fddebug(fmt, msg...) __fddebug("" ##fmt, ##msg) +#define __fddebug(fmt, msg...) do { \ + char *_m = NULL; \ + memprintf(&_m, \ + (""fmt)[0] ? \ + ("[%s@%s:%d] " fmt) : \ + ("[%s@%s:%d]\n"), __func__, \ + __FILE__, __LINE__, ##msg); \ + if (_m) \ + write(-1, _m, strlen(_m)); \ + free(_m); \ + } while (0) /* displays a long memory block at , assuming first byte of * has address . String may be placed as a prefix in front of