From ee4113e2c8ef0554d24165af7dd51fe6bb16e206 Mon Sep 17 00:00:00 2001 From: Inaky Perez-Gonzalez Date: Thu, 9 Apr 2009 11:39:14 -0700 Subject: libwimaxll: rework log helpers Add log level control and message origin, making it kind of backwards compatible. Signed-off-by: Inaky Perez-Gonzalez --- include/wimaxll.h | 15 ++- include/wimaxll/log.h | 61 ++++++++---- lib/log.c | 253 ++++++++++++++++++++++++++++++++++++++++++-------- lib/wimax.c | 62 +------------ 4 files changed, 274 insertions(+), 117 deletions(-) diff --git a/include/wimaxll.h b/include/wimaxll.h index ad2941e..5396c16 100644 --- a/include/wimaxll.h +++ b/include/wimaxll.h @@ -176,7 +176,7 @@ * @subsection diagnostics Controlling the ouput of diagnostics * * \e libwimaxll will output messages by default to \a stderr. See - * \ref diagnostics_group for changing the default destination. + * \ref helper_log for changing the default destination. * * @subsection bytesex Endianess conversion * @@ -341,13 +341,20 @@ ssize_t wimaxll_wait_for_state_change(struct wimaxll_handle *wmx, enum wimax_st *old_state, enum wimax_st *new_state); +/* + * Basic diagnostics + * + * Deprecated, see wimaxll/log.h + */ +extern void (*wimaxll_vmsg)(const char *, va_list) + __attribute__((deprecated)); +void wimaxll_vmsg_stderr(const char *, va_list) + __attribute__((deprecated)); + /** * \defgroup miscellaneous_group Miscellaneous utilities */ -extern void (*wimaxll_vmsg)(const char *, va_list); -void wimaxll_vmsg_stderr(const char *, va_list); - enum wimax_st wimaxll_state_by_name(const char *); size_t wimaxll_states_snprintf(char *, size_t); const char * wimaxll_state_to_name(enum wimax_st); diff --git a/include/wimaxll/log.h b/include/wimaxll/log.h index bb955b3..fac0afa 100644 --- a/include/wimaxll/log.h +++ b/include/wimaxll/log.h @@ -62,6 +62,19 @@ * } * * @endcode + * + * To control where the log/progress messages go and how they are + * formatted, the client can set a couple of function pointers + * wimaxll_msg_hdr_cb() (which controls how a header/prefix for the + * message is created) and wimaxll_vlmsg_cb(), which takes the message + * and delivers it to whichever destination. + * + * The default implementations are wimaxll_msg_hdr_default() and + * wimaxll_vlmsg_default(), which add a + * "libwimall[DEVICENAME]:" header (with an optional "(@ + * FUNCTION:LINE)") and deliver the message to \e stdout if it is a + * normal message (\e W_PRINT) or else if it is an error, warning, + * info or debug message, it is sent to \e stderr. */ #ifndef __wimaxll__log_h__ @@ -90,27 +103,39 @@ enum w_levels { W_D7, }; -void __w_vmsg(unsigned level, unsigned current_level, - const char *tag, unsigned line, - const char *fmt, va_list vargs); +struct wimaxll_handle; + +void wimaxll_msg(struct wimaxll_handle *, const char *fmt, ...) + __attribute__ ((format(printf, 2, 3))); + +void wimaxll_lmsg(unsigned level, unsigned current_level, + const char *origin_str, unsigned origin_line, + struct wimaxll_handle *wmx, const char *fmt, ...) + __attribute__ ((format(printf, 6, 7))); + +extern void (*wimaxll_vlmsg_cb)(struct wimaxll_handle *, unsigned, + const char *, const char *, va_list); +void wimaxll_vlmsg_stderr(struct wimaxll_handle *, unsigned, + const char *, const char *, va_list); -void __w_msg(unsigned level, unsigned current_level, - const char *tag, unsigned line, - const char *fmt, ...); +extern void (*wimaxll_msg_hdr_cb)(char *, size_t, struct wimaxll_handle *, + enum w_levels, const char *, unsigned); +void wimaxll_msg_hdr_default(char *, size_t, struct wimaxll_handle *, + enum w_levels, const char *, unsigned); void w_abort(int result, const char *fmt, ...); -#define w_error(fmt...) __w_msg(W_ERROR, W_VERBOSITY, __func__, __LINE__, "E: " fmt) -#define w_warn(fmt...) __w_msg(W_WARN, W_VERBOSITY, __func__, __LINE__, "W: " fmt) -#define w_info(fmt...) __w_msg(W_INFO, W_VERBOSITY, __func__, __LINE__, "I: " fmt) -#define w_print(fmt...) __w_msg(W_PRINT, W_VERBOSITY, __func__, __LINE__, fmt) -#define w_d0(fmt...) __w_msg(W_D0, W_VERBOSITY, __func__, __LINE__, "D0: " fmt) -#define w_d1(fmt...) __w_msg(W_D1, W_VERBOSITY, __func__, __LINE__, "D1: " fmt) -#define w_d2(fmt...) __w_msg(W_D2, W_VERBOSITY, __func__, __LINE__, "D2: " fmt) -#define w_d3(fmt...) __w_msg(W_D3, W_VERBOSITY, __func__, __LINE__, "D3: " fmt) -#define w_d4(fmt...) __w_msg(W_D4, W_VERBOSITY, __func__, __LINE__, "D4: " fmt) -#define w_d5(fmt...) __w_msg(W_D5, W_VERBOSITY, __func__, __LINE__, "D5: " fmt) -#define w_d6(fmt...) __w_msg(W_D6, W_VERBOSITY, __func__, __LINE__, "D6: " fmt) -#define w_d7(fmt...) __w_msg(W_D7, W_VERBOSITY, __func__, __LINE__, "D7: " fmt) +#define w_error(fmt...) wimaxll_lmsg(W_ERROR, W_VERBOSITY, __func__, __LINE__, NULL, "E: " fmt) +#define w_warn(fmt...) wimaxll_lmsg(W_WARN, W_VERBOSITY, __func__, __LINE__, NULL, "W: " fmt) +#define w_info(fmt...) wimaxll_lmsg(W_INFO, W_VERBOSITY, __func__, __LINE__, NULL, "I: " fmt) +#define w_print(fmt...) wimaxll_lmsg(W_PRINT, W_VERBOSITY, __func__, __LINE__, NULL, fmt) +#define w_d0(fmt...) wimaxll_lmsg(W_D0, W_VERBOSITY, __func__, __LINE__, NULL, "D0: " fmt) +#define w_d1(fmt...) wimaxll_lmsg(W_D1, W_VERBOSITY, __func__, __LINE__, NULL, "D1: " fmt) +#define w_d2(fmt...) wimaxll_lmsg(W_D2, W_VERBOSITY, __func__, __LINE__, NULL, "D2: " fmt) +#define w_d3(fmt...) wimaxll_lmsg(W_D3, W_VERBOSITY, __func__, __LINE__, NULL, "D3: " fmt) +#define w_d4(fmt...) wimaxll_lmsg(W_D4, W_VERBOSITY, __func__, __LINE__, NULL, "D4: " fmt) +#define w_d5(fmt...) wimaxll_lmsg(W_D5, W_VERBOSITY, __func__, __LINE__, NULL, "D5: " fmt) +#define w_d6(fmt...) wimaxll_lmsg(W_D6, W_VERBOSITY, __func__, __LINE__, NULL, "D6: " fmt) +#define w_d7(fmt...) wimaxll_lmsg(W_D7, W_VERBOSITY, __func__, __LINE__, NULL, "D7: " fmt) #endif /* #define __wimaxll__log_h__ */ diff --git a/lib/log.c b/lib/log.c index 29463c8..9d85988 100644 --- a/lib/log.c +++ b/lib/log.c @@ -35,64 +35,241 @@ #include #define W_VERBOSITY W_ERROR #include +#include "internal.h" /** - * Log a message to (varargs version) if log level allows it + * Deliver \e libwimaxll diagnostics messages to \e stderr or \e stdout. * - * \param level level of the messagve - * \param current_level current logging level - * \param tag a str to print along with \e line (if not NULL, its - * not printed). - * \param line an integer to print along with \e tag (if \e tag is not - * NULL) - * \param fmt printf-like format string - * \param vargs arguments to \e fmt + * \param wmx WiMAX handle this message is related to + * \param level Message level + * \param header Header for the message; the implementation must + * decide if it has to be printed or not. + * \param fmt printf-like format + * \param vargs variable-argument list as created by + * stdargs.h:va_list() that will be formatted according to \e + * fmt. * - * \internal + * Default diagnostics printing function. If the log level is + * "W_PRINT", we put it on stdout without a header, otherwise in + * stderr with header. * - * Use w_*() functions only - * - * @ingroup: helper_log + * \ingroup helper_log */ -void __w_vmsg(unsigned level, unsigned current_level, - const char *tag, unsigned line, - const char *fmt, va_list vargs) +void wimaxll_vlmsg_default(struct wimaxll_handle *wmx, unsigned level, + const char *header, + const char *fmt, va_list vargs) { - FILE *f; - f = level != W_PRINT? stderr : stdout; - if (level <= current_level || level == W_PRINT) { - if (tag) - fprintf(f, "%s:%u: ", tag, line); - vfprintf(f, fmt, vargs); + FILE *f = level != W_PRINT? stderr : stdout; + + /* Backwards compat */ + if (wimaxll_vmsg) { + if (header) + wimaxll_vmsg(header, NULL); + wimaxll_vmsg(fmt, vargs); + return; + } + if (level == W_PRINT) + f = stdout; + else { + f = stderr; + fprintf(f, header); } + vfprintf(f, fmt, vargs); } /** - * Log a message to if log level allows it + * Print library diagnostics messages [backend] * - * \param level level of the messagve - * \param current_level current logging level - * \param tag a str to print along with \e line (if not NULL, its - * not printed). - * \param line an integer to print along with \e tag (if \e tag is not - * NULL) - * \param fmt printf-like format string, plus their arguments + * @param wmx WiMAX handle this message is related to + * @param level Message level + * @param header Header to print for the message (the implementation + * must decide if to print it or not). + * @param fmt printf-like format + * @param vargs variable-argument list as created by + * stdargs.h:va_list() that will be formatted according to \e + * fmt. * - * \internal + * Prints/writes the \e libwimaxll's diagnostics messages to a + * destination as selected by the user of the library. * - * Use w_*() functions only + * \note This function pointer must be set \b before calling any other + * \e libwimaxll function. * - * @ingroup: helper_log + * By default, diagnostics are printed with wimaxll_vlmsg_default() to + * \a stderr or stdout based on the level. + * + * For example, to deliver diagnostics to syslog: + * + * @code + * #include + * ... + * static + * void wimaxll_vlmsg_syslog(....const char *fmt, va_list vargs) + * { + * syslog(LOG_MAKEPRI(LOG_USER, LOG_INFO), header); + * vsyslog(LOG_MAKEPRI(LOG_USER, LOG_INFO), fmt, vargs); + * } + * ... + * wimaxll_vlmsg = wimaxll_vlmsg_syslog(); + * ... + * wimaxll_open(BLAH); + * @endcode + * + * The internal function wimaxll_msg() and wimaxll_lmsg() are used as + * as a frontend to this function. + * + * \ingroup helper_log + */ +void (*wimaxll_vlmsg_cb)(struct wimaxll_handle *wmx, unsigned level, + const char *header, + const char *fmt, va_list vargs) = + wimaxll_vlmsg_default; + + +/** + * Default header for diagnostic messages + * + * If there is no handle, prints just "libwimaxll", otherwise + * "libwimaxll[device]"; if the message is debug, also adds a + * "(@ FUNCTION:LINE)" origin tag. + * + * \ingroup helper_log + */ +void wimaxll_msg_hdr_default(char *buf, size_t buf_len, + struct wimaxll_handle *wmx, enum w_levels level, + const char *origin_str, unsigned origin_line) +{ + size_t bytes; + if (wmx == NULL) + bytes = snprintf(buf, buf_len, "libwimaxll: "); + else if ((unsigned long) wmx < 4096) + bytes = snprintf(buf, buf_len, "libwimaxll[bad handle %p]: ", + wmx); + else + bytes = snprintf(buf, buf_len, "libwimaxll[%s]: ", wmx->name); + if (level >= W_D0 && origin_str != NULL) + snprintf(buf + bytes, buf_len - bytes, + "(@ %s:%u) ", origin_str, origin_line); +} + + +/** + * Create a header for library diagnostic messages [backend] + * + * @param buf Buffer where to place the header + * @param buf_len Size of the buffer + * @param wmx WiMAX handle the message is being generated for (can be + * NULL or invalid). + * @param level Level of the log message this header is being + * generated for. + * @param origin_str Origin of the message (used for a source file + * name or function name). If %NULL, the origin information should + * not be considered. + * @param origin_line Origin of the message (used for a line in a + * source file or function). + * + * Creates a header to prefix to ever message printed with + * wimaxll_msg(). + * + * By default, diagnostics are printed with wimaxll_msg_hdr_default() + * is used, which creates a "libwimaxll[DEVICENAME]" prefix. + * + * To change it: + * + * @code + * ... + * static + * void my_wimaxll_msg_hdr(char *buf, size_t len, struct + * wimaxll_handle *wmx) + * { + * snprintf(buf, len, "my prefix: "); + * } + * ... + * wimaxll_msg_hdr = my_wimaxll_msg_hdr; + * ... + * wimaxll_open(BLAH); + * @endcode + * + * \ingroup helper_log + */ +void (*wimaxll_msg_hdr_cb)(char *buf, size_t buf_len, + struct wimaxll_handle *wmx, enum w_levels level, + const char *origin_str, unsigned origin_line) = + wimaxll_msg_hdr_default; + + +static +void wimaxll_vlmsg(unsigned level, unsigned current_level, + const char *origin_str, unsigned origin_int, + struct wimaxll_handle *wmx, const char *fmt, va_list vargs) +{ + char header[64] = ""; + if (level > current_level && level != W_PRINT) + return; + if (wimaxll_msg_hdr_cb) + wimaxll_msg_hdr_cb(header, sizeof(header), wmx, + level, origin_str, origin_int); + wimaxll_vlmsg_cb(wmx, level, header, fmt, vargs); +} + + +/** + * Prints library diagnostic messages with a predefined format [frontend] + * + * @param wmx WiMAX handle; if NULL, no device header will be presented. + * @param fmt printf-like format followed by any arguments + * + * Called by the library functions to print status/error messages. By + * default these are sent over to stderr. + * + * However, library users can change this default behaviour by setting + * wimaxll_vmsg() as documented in that function pointer's + * documentation. + * + * \ingroup helper_log + */ +void wimaxll_msg(struct wimaxll_handle *wmx, const char *fmt, ...) +{ + va_list vargs; + va_start(vargs, fmt); + wimaxll_vlmsg(W_PRINT, W_PRINT, NULL, 0, wmx, fmt, vargs); + va_end(vargs); +} + + +/** + * Prints library diagnostic messages with a predefined format + * [frontend] and log level control + * + * @param level level of the messagve + * @param current_level current logging level + * @param origin_str Origin of the message (used for a source file + * name or function name). + * @param origin_line Origin of the message (used for a line in a + * source file or function). + * @param wmx WiMAX handle; if NULL, no device header will be presented. + * @param fmt printf-like format followed by any arguments + * + * Called by the library functions to print status/error messages if + * the current log level allows it. By default these are sent over to + * stderr. + * + * However, library users can change this default behaviour by setting + * wimaxll_vmsg() as documented in that function pointer's + * documentation. + * + * \ingroup helper_log */ -void __w_msg(unsigned level, unsigned current_level, - const char *tag, unsigned line, - const char *fmt, ...) +void wimaxll_lmsg(unsigned level, unsigned current_level, + const char *origin_str, unsigned origin_line, + struct wimaxll_handle *wmx, const char *fmt, ...) { va_list vargs; va_start(vargs, fmt); - __w_vmsg(level, current_level, tag, line, fmt, vargs); + wimaxll_vlmsg(level, current_level, origin_str, origin_line, + wmx, fmt, vargs); va_end(vargs); } @@ -109,7 +286,7 @@ void w_abort(int result, const char *fmt, ...) { va_list vargs; va_start(vargs, fmt); - __w_vmsg(W_ERROR, W_ERROR, __FILE__, __LINE__, fmt, vargs); + wimaxll_vlmsg(W_ERROR, W_ERROR, __FILE__, __LINE__, NULL, fmt, vargs); va_end(vargs); exit(result); } diff --git a/lib/wimax.c b/lib/wimax.c index c0a52e4..d579d8c 100644 --- a/lib/wimax.c +++ b/lib/wimax.c @@ -191,22 +191,11 @@ int wimaxll_wait_for_ack(struct wimaxll_handle *wmx) } -/** - * \defgroup diagnostics_group Output of diagnostics messages - * - * The \e libwimaxll library prints diagnostics by default to \a - * stderr. Said destination can be changed by the user by setting the - * wimaxll_vmsg() function pointer before calling any other \a - * libwimaxll function. - * - * To restore the default diagnostics destination, set wimaxll_vmsg() - * back to wimaxll_vmsg_stderr(). - */ - - /** * Deliver \e libwimaxll diagnostics messages to \e stderr * + * \deprecated { use wimaxll_vlmsg_cb } + * * \param fmt printf-like format * \param vargs variable-argument list as created by * stdargs.h:va_list() that will be formatted according to \e @@ -226,6 +215,8 @@ void wimaxll_vmsg_stderr(const char *fmt, va_list vargs) /** * Print library diagnostics messages [backend] * + * \deprecated { use wimaxll_vlmsg_cb } + * * @param fmt printf-like format * @param vargs variable-argument list as created by * stdargs.h:va_list() that will be formatted according to \e @@ -262,50 +253,7 @@ void wimaxll_vmsg_stderr(const char *fmt, va_list vargs) * The internal function wimaxll_msg() is used as as a frontend to * this function. */ -void (*wimaxll_vmsg)(const char *fmt, va_list vargs) = wimaxll_vmsg_stderr; - - -static -void __wimaxll_msg(const char *fmt, ...) -{ - va_list vargs; - va_start(vargs, fmt); - wimaxll_vmsg(fmt, vargs); - va_end(vargs); -} - - -/** - * \internal - * - * Prints library diagnostic messages with a predefined format [frontend] - * - * @param wmx WiMAX handle; if NULL, no device header will be presented. - * @param fmt printf-like format followed by any arguments - * - * Called by the library functions to print status/error messages. By - * default these are sent over to stderr. - * - * However, library users can change this default behaviour by setting - * wimaxll_vmsg() as documented in that function pointer's - * documentation. - * - * \ingroup diagnostics_group - */ -void wimaxll_msg(struct wimaxll_handle *wmx, const char *fmt, ...) -{ - va_list vargs; - if (wmx == NULL) - __wimaxll_msg("libwimax: "); - else if ((unsigned long) wmx < 4096) { - __wimaxll_msg("libwimax: E: Corrupt device handle %p\n", wmx); - __wimaxll_msg("libwimax[n/a]: "); - } else - __wimaxll_msg("libwimax[%s]: ", wmx->name); - va_start(vargs, fmt); - wimaxll_vmsg(fmt, vargs); - va_end(vargs); -} +void (*wimaxll_vmsg)(const char *fmt, va_list vargs) = NULL; /** -- cgit v1.2.3