test "$BABELTRACE_MINIMAL_LOG_LEVEL" != "INFO"],
[AC_MSG_ERROR([Invalid BABELTRACE_MINIMAL_LOG_LEVEL value ($BABELTRACE_MINIMAL_LOG_LEVEL): use TRACE, DEBUG, or INFO.])]
)
-AC_DEFINE_UNQUOTED([BT_MINIMAL_LOG_LEVEL], [BT_LOG_$BABELTRACE_MINIMAL_LOG_LEVEL], [Minimal log level])
+AC_DEFINE_UNQUOTED([BT_LOG_MINIMAL_LEVEL], [__BT_LOGGING_LEVEL_$BABELTRACE_MINIMAL_LOG_LEVEL], [Minimal log level])
# BABELTRACE_DEV_MODE:
AC_ARG_VAR([BABELTRACE_DEV_MODE], [Set to 1 to enable the Babeltrace developer mode (enables run-time checks for plugin developers)])
logging_liblogging_la_SOURCES = \
logging/comp-logging.h \
- logging/log.c \
+ logging/log-api.c \
+ logging/log-api.h \
logging/log.h
param_parse_libparam_parse_la_SOURCES = \
*/
#define BT_LOG_TAG "CLI-CFG-SRC-AUTO-DISC"
-#define BT_LOG_OUTPUT_LEVEL log_level
+#define BT_LOG_OUTPUT_LEVEL ((enum bt_log_level) log_level)
#include "logging/log.h"
#include <stdbool.h>
#include "common/common.h"
#define BT_AUTODISC_LOG_AND_APPEND(_lvl, _fmt, ...) \
- do { \
- BT_LOG_WRITE(_lvl, BT_LOG_TAG, _fmt, ##__VA_ARGS__); \
- (void) BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN( \
+ do { \
+ BT_LOG_WRITE_PRINTF(_lvl, BT_LOG_TAG, _fmt, ##__VA_ARGS__); \
+ (void) BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN( \
"Source auto-discovery", _fmt, ##__VA_ARGS__); \
} while (0)
plugins,
plugin_count,
NULL,
- bt_python_bindings_bt2_log_level,
+ (bt_logging_level) bt_python_bindings_bt2_log_level,
&auto_disc,
NULL);
if (status != 0) {
py_cls = lookup_cc_ptr_to_py_cls(component_class);
if (!py_cls) {
- BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_ERROR,
+ (enum bt_log_level) log_level, BT_LOG_TAG,
"Cannot find Python class associated to native component class: "
"comp-cls-addr=%p", component_class);
goto error;
py_params_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(params),
SWIGTYPE_p_bt_value, 0);
if (!py_params_ptr) {
- BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_ERROR,
+ (enum bt_log_level) log_level, BT_LOG_TAG,
BT_FMT_SWIG_ALLOC_FAILED);
goto error;
}
py_params_ptr, init_method_data ? init_method_data : Py_None,
(int) log_level);
if (!py_range_set_addr) {
- BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, log_level, BT_LOG_TAG,
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_WARNING,
+ (enum bt_log_level) log_level, BT_LOG_TAG,
"Failed to call Python class's _bt_get_supported_mip_versions_from_native() method: "
"py-cls-addr=%p", py_cls);
status = py_exc_to_status_component_class_clear(self_component_class,
bt_integer_range_unsigned_get_lower(range),
bt_integer_range_unsigned_get_upper(range));
if (add_range_status) {
- BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_ERROR,
+ (enum bt_log_level) log_level, BT_LOG_TAG,
"Failed to add range to supported MIP versions range set.");
goto error;
}
py_cls = lookup_cc_ptr_to_py_cls(component_class);
if (!py_cls) {
- BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_ERROR,
+ (enum bt_log_level) log_level, BT_LOG_TAG,
"Cannot find Python class associated to native component class: "
"comp-cls-addr=%p", component_class);
goto error;
py_params_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(params),
SWIGTYPE_p_bt_value, 0);
if (!py_params_ptr) {
- BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_ERROR,
+ (enum bt_log_level) log_level, BT_LOG_TAG,
BT_FMT_SWIG_ALLOC_FAILED);
goto error;
}
SWIG_as_voidptr(priv_query_executor),
SWIGTYPE_p_bt_private_query_executor, 0);
if (!py_priv_query_exec_ptr) {
- BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_ERROR,
+ (enum bt_log_level) log_level, BT_LOG_TAG,
BT_FMT_SWIG_ALLOC_FAILED);
goto error;
}
py_object = SWIG_FromCharPtr(object);
if (!py_object) {
- BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_ERROR,
+ (enum bt_log_level) log_level, BT_LOG_TAG,
"Failed to create a Python string.");
goto error;
}
log_level);
if (status < 0) {
#define BT_FMT "Failed to call Python class's _bt_query_from_native() method: py-cls-addr=%p"
- BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, log_level, BT_LOG_TAG,
- BT_FMT, py_cls);
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_WARNING,
+ (enum bt_log_level) log_level,
+ BT_LOG_TAG, BT_FMT, py_cls);
BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT_CLASS(
self_component_class, BT_FMT, py_cls);
#undef BT_FMT
PyObject *py_error_cause_str = NULL;
error_cause_str = format_bt_error_cause(error_cause, 80,
- bt_python_bindings_bt2_log_level, BT_COMMON_COLOR_WHEN_NEVER);
+ (bt_logging_level) bt_python_bindings_bt2_log_level,
+ BT_COMMON_COLOR_WHEN_NEVER);
BT_ASSERT(error_cause_str);
py_error_cause_str = PyString_FromString(error_cause_str);
PyObject *py_error_str = NULL;
error_str = format_bt_error(error, 80,
- bt_python_bindings_bt2_log_level, BT_COMMON_COLOR_WHEN_NEVER);
+ (bt_logging_level) bt_python_bindings_bt2_log_level,
+ BT_COMMON_COLOR_WHEN_NEVER);
BT_ASSERT(error_str);
py_error_str = PyString_FromString(error_str);
}
status = bt_get_greatest_operative_mip_version(comp_descr_set,
- bt_cli_log_level, mip_version);
+ (bt_logging_level) bt_cli_log_level, mip_version);
end:
bt_component_descriptor_set_put_ref(comp_descr_set);
if (g_file_test(cfg->command_name,
G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
- _bt_log_write_d(_BT_LOG_SRCLOC_FUNCTION, __FILE__, __LINE__,
+ bt_log_write_printf(__FILE__, __func__, __LINE__,
BT_LOG_WARNING, BT_LOG_TAG,
"The `%s` command was executed. "
"If you meant to convert a trace located in "
*/
fputc('\n', stderr);
- error_str = format_bt_error(error, columns, bt_cli_log_level,
- BT_COMMON_COLOR_WHEN_AUTO);
+ error_str = format_bt_error(error, columns,
+ (bt_logging_level) bt_cli_log_level, BT_COMMON_COLOR_WHEN_AUTO);
BT_ASSERT(error_str);
fprintf(stderr, "%s\n", error_str);
*/
#define BT_LOG_OUTPUT_LEVEL bt_cli_log_level
-#include "logging/log.h"
+#include "logging/log-api.h"
BT_LOG_INIT_LOG_LEVEL(bt_cli_log_level, "BABELTRACE_CLI_LOG_LEVEL");
#define BT_CLI_LOG_AND_APPEND(_lvl, _fmt, ...) \
do { \
- BT_LOG_WRITE(_lvl, BT_LOG_TAG, _fmt, ##__VA_ARGS__); \
+ BT_LOG_WRITE_PRINTF(_lvl, BT_LOG_TAG, _fmt, ##__VA_ARGS__); \
(void) BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN( \
"Babeltrace CLI", _fmt, ##__VA_ARGS__); \
} while (0)
/* retry operation */
continue;
} else {
-#ifdef BT_LOG_WRITE_ERRNO_CUR_LVL
- BT_LOG_WRITE_ERRNO_CUR_LVL(BT_LOG_ERROR,
+#ifdef BT_LOG_WRITE_ERRNO_PRINTF_CUR_LVL
+ BT_LOG_WRITE_ERRNO_PRINTF_CUR_LVL(BT_LOG_ERROR,
log_level, BT_LOG_TAG,
"Error while reading", ": fd=%d", fd);
#endif
SYSTEM_INFO sysinfo;
GetNativeSystemInfo(&sysinfo);
- BT_LOG_WRITE_CUR_LVL(BT_LOG_DEBUG, log_level, BT_LOG_TAG,
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_DEBUG, log_level, BT_LOG_TAG,
"Allocator granularity is %lu.",
sysinfo.dwAllocationGranularity);
ret = WSAStartup(verreq, &wsa);
if (ret != 0) {
-#ifdef BT_LOG_WRITE_CUR_LVL
- BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
+#ifdef BT_LOG_WRITE_PRINTF_CUR_LVL
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG,
"Winsock init failed with error: %d", ret);
#endif
goto end;
*/
# define BT_CTF_ASSERT_PRE_MSG(_fmt, ...) \
do { \
- _bt_log_write_d(_BT_LOG_SRCLOC_FUNCTION, __FILE__, \
+ bt_log_write_printf(__FILE__, __func__, \
__LINE__, BT_LOG_FATAL, BT_LOG_TAG, (_fmt), \
##__VA_ARGS__); \
} while (0)
*/
#define BT_ASSERT_COND_MSG(_fmt, ...) \
do { \
- bt_lib_log(_BT_LOG_SRCLOC_FUNCTION, __FILE__, \
+ bt_lib_log(__FILE__, __func__, \
__LINE__, BT_LOG_FATAL, BT_LOG_TAG, \
(_fmt), ##__VA_ARGS__); \
} while (0)
BT_ASSERT_COND_MSG("------------------------------------------------------------------------");
BT_ASSERT_COND_MSG("Error is:");
va_start(args, fmt);
- bt_lib_log_v(_BT_LOG_SRCLOC_FUNCTION, __FILE__, __LINE__, BT_LOG_FATAL,
+ bt_lib_log_v(__FILE__, __func__, __LINE__, BT_LOG_FATAL,
BT_LOG_TAG, fmt, &args);
va_end(args);
BT_ASSERT_COND_MSG("Aborting...");
* exposed, but not part of the public ABI.
*/
BT_EXPORT
-void bt_lib_log_v(const char *func, const char *file, unsigned line,
+void bt_lib_log_v(const char *file, const char *func, unsigned line,
int lvl, const char *tag, const char *fmt, va_list *args)
{
BT_ASSERT(fmt);
bt_common_custom_vsnprintf(lib_logging_buf, LIB_LOGGING_BUF_SIZE, '!',
handle_conversion_specifier_bt, NULL, fmt, args);
- _bt_log_write_d(func, file, line, lvl, tag, "%s", lib_logging_buf);
+ bt_log_write(file, func, line, lvl, tag, lib_logging_buf);
}
/*
* exposed, but not part of the public ABI.
*/
BT_EXPORT
-void bt_lib_log(const char *func, const char *file, unsigned line,
+void bt_lib_log(const char *file, const char *func, unsigned line,
int lvl, const char *tag, const char *fmt, ...)
{
va_list args;
BT_ASSERT(fmt);
va_start(args, fmt);
- bt_lib_log_v(func, file, line, lvl, tag, fmt, &args);
+ bt_lib_log_v(file, func, line, lvl, tag, fmt, &args);
va_end(args);
}
/* Log conditionally, but always append the error cause */
if (BT_LOG_ON(lvl)) {
- _bt_log_write_d(func, file, line, lvl, tag, "%s",
- lib_logging_buf);
+ bt_log_write(file, func, line, lvl, tag, lib_logging_buf);
}
status = bt_current_thread_error_append_cause_from_unknown(
BT_EXPORT
enum bt_logging_level bt_logging_get_minimal_level(void)
{
- return BT_MINIMAL_LOG_LEVEL;
+ return BT_LOG_MINIMAL_LEVEL;
}
BT_EXPORT
bt_version_get_development_stage() : "";
bt_logging_set_global_level(
- bt_log_get_level_from_env("LIBBABELTRACE2_INIT_LOG_LEVEL"));
+ (int) bt_log_get_level_from_env("LIBBABELTRACE2_INIT_LOG_LEVEL"));
BT_LOGI("Babeltrace %u.%u.%u%s library loaded: "
"major=%u, minor=%u, patch=%u, extra=\"%s\"",
bt_version_get_major(), bt_version_get_minor(),
#define BT_LIB_LOG(_lvl, _fmt, ...) \
do { \
if (BT_LOG_ON(_lvl)) { \
- bt_lib_log(_BT_LOG_SRCLOC_FUNCTION, __FILE__, \
+ bt_lib_log(__FILE__, __func__, \
__LINE__, _lvl, _BT_LOG_TAG, \
(_fmt), ##__VA_ARGS__); \
} \
* Use one of the BT_LIB_LOG*() macros above instead of calling this
* function directly.
*/
-void bt_lib_log(const char *func, const char *file, unsigned line,
+void bt_lib_log(const char *file, const char *func, unsigned line,
int lvl, const char *tag, const char *fmt, ...);
-void bt_lib_log_v(const char *func, const char *file, unsigned line,
+void bt_lib_log_v(const char *file, const char *func, unsigned line,
int lvl, const char *tag, const char *fmt, va_list *args);
#define BT_LIB_LOG_AND_APPEND(_lvl, _fmt, ...) \
do { \
bt_lib_maybe_log_and_append_cause( \
- _BT_LOG_SRCLOC_FUNCTION, __FILE__, \
+ __func__, __FILE__, \
__LINE__, _lvl, _BT_LOG_TAG, \
(_fmt), ##__VA_ARGS__); \
} while (0)
/* Logs with level `_lvl` for self component `_self_comp` */
#define BT_COMP_LOG(_lvl, _self_comp, _fmt, ...) \
- BT_LOG_WRITE((_lvl), BT_LOG_TAG, _BT_COMP_LOG_COMP_PREFIX _fmt, \
+ BT_LOG_WRITE_PRINTF_CUR_LVL((enum bt_log_level) (_lvl), \
+ (enum bt_log_level) (BT_LOG_OUTPUT_LEVEL), BT_LOG_TAG, \
+ _BT_COMP_LOG_COMP_PREFIX _fmt, \
(_self_comp) ? \
bt_component_get_name( \
bt_self_component_as_component(_self_comp)) : \
/* Logs with level `_lvl` for self component class `_self_comp_class` */
#define BT_COMP_CLASS_LOG(_lvl, _self_comp_class, _fmt, ...) \
- BT_LOG_WRITE((_lvl), BT_LOG_TAG, _BT_COMP_LOG_COMP_PREFIX _fmt, \
+ BT_LOG_WRITE_PRINTF_CUR_LVL((enum bt_log_level) (_lvl), \
+ (enum bt_log_level) (BT_LOG_OUTPUT_LEVEL), BT_LOG_TAG, \
+ _BT_COMP_LOG_COMP_PREFIX _fmt, \
bt_component_class_get_name( \
bt_self_component_class_as_component_class( \
_self_comp_class)), ##__VA_ARGS__)
#define BT_COMP_LOG_CUR_LVL(_lvl, _cur_lvl, _self_comp, _fmt, ...) \
- BT_LOG_WRITE_CUR_LVL((_lvl), (_cur_lvl), BT_LOG_TAG, \
+ BT_LOG_WRITE_PRINTF_CUR_LVL((enum bt_log_level) (_lvl), \
+ (enum bt_log_level) (_cur_lvl), BT_LOG_TAG, \
_BT_COMP_LOG_COMP_PREFIX _fmt, \
(_self_comp) ? \
bt_component_get_name( \
##__VA_ARGS__)
#define BT_COMP_LOG_ERRNO(_lvl, _self_comp, _msg, _fmt, ...) \
- BT_LOG_WRITE_ERRNO((_lvl), BT_LOG_TAG, _msg, \
+ BT_LOG_WRITE_ERRNO_PRINTF_CUR_LVL((enum bt_log_level) (_lvl), \
+ (enum bt_log_level) (BT_LOG_OUTPUT_LEVEL), \
+ BT_LOG_TAG, _msg, \
_BT_COMP_LOG_COMP_PREFIX _fmt, \
(_self_comp) ? \
bt_component_get_name( \
##__VA_ARGS__)
#define BT_COMP_LOG_ERRNO_CUR_LVL(_lvl, _cur_lvl, _self_comp, _msg, _fmt, ...) \
- BT_LOG_WRITE_ERRNO_CUR_LVL((_lvl), (_cur_lvl), BT_LOG_TAG, _msg, \
+ BT_LOG_WRITE_ERRNO_PRINTF_CUR_LVL((enum bt_log_level) (_lvl), \
+ (enum bt_log_level) (_cur_lvl), BT_LOG_TAG, _msg, \
_BT_COMP_LOG_COMP_PREFIX _fmt, \
(_self_comp) ? \
bt_component_get_name( \
##__VA_ARGS__)
#define BT_COMP_LOG_MEM(_lvl, _self_comp, _data_ptr, _data_sz, _fmt, ...) \
- BT_LOG_WRITE_MEM((_lvl), BT_LOG_TAG, (_data_ptr), (_data_sz), \
+ BT_LOG_WRITE_MEM_PRINTF_CUR_LVL((enum bt_log_level) (_lvl), \
+ (enum bt_log_level) (BT_LOG_OUTPUT_LEVEL), BT_LOG_TAG, \
+ (_data_ptr), (_data_sz), \
_BT_COMP_LOG_COMP_PREFIX _fmt, \
(_self_comp) ? \
bt_component_get_name( \
/* Logs error and errno string from component class context. */
#define BT_COMP_CLASS_LOG_ERRNO(_lvl, _self_comp_class, _msg, _fmt, ...) \
- BT_LOG_WRITE_ERRNO((_lvl), BT_LOG_TAG, _msg, \
+ BT_LOG_WRITE_ERRNO_PRINTF_CUR_LVL((enum bt_log_level) (_lvl), \
+ (enum bt_log_level) (BT_LOG_OUTPUT_LEVEL), BT_LOG_TAG, _msg, \
_BT_COMP_LOG_COMP_PREFIX _fmt, \
bt_component_class_get_name( \
bt_self_component_class_as_component_class(_self_comp_class)) \
--- /dev/null
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright (c) 2016 wonder-mice
+ * Copyright (c) 2016-2023 Philippe Proulx <pproulx@efficios.com>
+ *
+ * This is very inspired by zf_log.c (see
+ * <https://github.com/wonder-mice/zf_log/>), but modified (mostly
+ * stripped down) for the use cases of Babeltrace.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <glib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#if defined(_WIN32) || defined(_WIN64)
+# include <windows.h>
+#endif
+
+#ifdef __linux__
+# include <sys/prctl.h>
+# include <sys/syscall.h>
+#endif
+
+#ifdef __MACH__
+# include <pthread.h>
+#endif
+
+#ifdef __GNU__
+# include <mach.h>
+#endif
+
+#include "common/assert.h"
+#include "common/common.h"
+#include "common/macros.h"
+#include "compat/time.h"
+
+#include "log-api.h"
+
+#ifdef __CYGWIN__
+extern unsigned long pthread_getsequence_np(pthread_t *);
+#endif
+
+/*
+ * Thread-local logging message buffer to put the next message and write
+ * it with a single system call.
+ */
+static __thread char msg_buf[4 * 4096];
+
+/*
+ * Returns the number of available bytes in `msg_buf` considering the
+ * writing position `at`.
+ */
+static inline
+size_t avail_msg_buf_bytes(char *at)
+{
+ return msg_buf + sizeof(msg_buf) - at;
+}
+
+/*
+ * Appends the character `ch` to `msg_buf`.
+ */
+static inline
+void append_char_to_msg_buf(char ** const at, const char ch)
+{
+ **at = ch;
+ (*at)++;
+}
+
+/*
+ * Appends a space character to `msg_buf`.
+ */
+static inline
+void append_sp_to_msg_buf(char ** const at)
+{
+ append_char_to_msg_buf(at, ' ');
+}
+
+/*
+ * Appends the null-terminated string `str` to `msg_buf`.
+ */
+static inline
+void append_str_to_msg_buf(char ** const at, const char * const str)
+{
+ const size_t len = strlen(str);
+
+ memcpy(*at, str, len);
+ *at += len;
+}
+
+/*
+ * Formats the unsigned integer `val` with sprintf() using `fmt` and
+ * appends the resulting string to `msg_buf`.
+ */
+static inline
+void append_uint_to_msg_buf(char ** const at, const char * const fmt,
+ const unsigned int val)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ const int written_len = sprintf(*at, fmt, val);
+#pragma GCC diagnostic pop
+
+ BT_ASSERT_DBG(written_len > 0);
+ *at += (size_t) written_len;
+}
+
+/*
+ * Thread-local cache of seconds and milliseconds to formatted date/time
+ * string (null terminated).
+ *
+ * This is often useful because many log messages may happen during the
+ * same millisecond.
+ *
+ * Does not need any kind of protection since it's TLS.
+ */
+struct date_time_cache {
+ uint64_t s;
+ uint32_t ms;
+ char str[128];
+};
+
+static __thread struct date_time_cache date_time_cache = {0};
+
+static
+const char *date_time_cache_get(const struct timeval tv)
+{
+ const uint64_t s = (uint64_t) tv.tv_sec;
+ const uint32_t ms = (uint32_t) (tv.tv_usec / 1000);
+
+ if (date_time_cache.s != s || date_time_cache.ms != ms) {
+ /* Add to cache now */
+ struct tm tm;
+ const time_t time_s = (time_t) tv.tv_sec;
+
+ date_time_cache.s = (uint64_t) tv.tv_sec;
+ date_time_cache.ms = (uint32_t) (tv.tv_usec / 1000);
+ (void) bt_localtime_r(&time_s, &tm);
+ (void) sprintf(date_time_cache.str, "%02u-%02u %02u:%02u:%02u.%03u",
+ tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec, date_time_cache.ms);
+ }
+
+ return date_time_cache.str;
+}
+
+/*
+ * Appends a formatted date/time for `tv` to `msg_buf`.
+ */
+static inline
+void append_date_time_to_msg_buf(char ** const at, const struct timeval tv)
+{
+ const char *str = date_time_cache_get(tv);
+
+ append_str_to_msg_buf(at, str);
+}
+
+/*
+ * Appends the PID and TID to `msg_buf`.
+ */
+static inline
+void append_pid_tid_to_msg_buf(char ** const at)
+{
+ const unsigned int pid = (unsigned int) getpid();
+ unsigned int tid;
+
+ /* Look at this beautiful portability */
+#if defined(_WIN32) || defined(_WIN64)
+ tid = (unsigned int) GetCurrentThreadId();
+#elif defined(__CYGWIN__)
+ {
+ pthread_t thr = pthread_self();
+
+ tid = (unsigned int) pthread_getsequence_np(&thr);
+ }
+#elif defined(__sun__)
+ tid = (unsigned int) pthread_self();
+#elif defined(__linux__)
+ tid = (unsigned int) syscall(SYS_gettid);
+#elif defined(__APPLE__) && defined(__MACH__)
+ tid = (unsigned int) pthread_mach_thread_np(pthread_self());
+#elif defined(__GNU__)
+ {
+ mach_port_t mach_port = mach_thread_self();
+
+ mach_port_deallocate(mach_task_self(), mach_port);
+ tid = (unsigned int) mach_port;
+ }
+#else
+# error "Platform not supported"
+#endif
+
+ /* Append them now */
+ append_uint_to_msg_buf(at, "%u", pid);
+ append_sp_to_msg_buf(at);
+ append_uint_to_msg_buf(at, "%u", tid);
+}
+
+/*
+ * Writes the initial part of the log message to `msg_buf`, without the
+ * message and without resetting the terminal color).
+ */
+static
+void common_write_init(char ** const at, const char * const file_name,
+ const char * const func_name, const unsigned int line_no,
+ const enum bt_log_level lvl, const char * const tag)
+{
+ const char *color_p = "";
+ struct timeval tv;
+
+ /* Get time immediately */
+ gettimeofday(&tv, 0);
+
+ /* Write the terminal color code to use, if any */
+ switch (lvl) {
+ case BT_LOG_INFO:
+ color_p = bt_common_color_fg_blue();
+ break;
+ case BT_LOG_WARNING:
+ color_p = bt_common_color_fg_yellow();
+ break;
+ case BT_LOG_ERROR:
+ case BT_LOG_FATAL:
+ color_p = bt_common_color_fg_red();
+ break;
+ default:
+ break;
+ }
+
+ append_str_to_msg_buf(at, color_p);
+
+ /* Write date/time */
+ append_date_time_to_msg_buf(at, tv);
+ append_sp_to_msg_buf(at);
+
+ /* Write PID/TID */
+ append_pid_tid_to_msg_buf(at);
+ append_sp_to_msg_buf(at);
+
+ /* Write log level letter */
+ append_char_to_msg_buf(at, bt_log_get_letter_from_level(lvl));
+ append_sp_to_msg_buf(at);
+
+ /* Write tag */
+ if (tag) {
+ append_str_to_msg_buf(at, tag);
+ append_sp_to_msg_buf(at);
+ }
+
+ /* Write source location */
+ append_str_to_msg_buf(at, func_name);
+ append_char_to_msg_buf(at, '@');
+ append_str_to_msg_buf(at, file_name);
+ append_uint_to_msg_buf(at, ":%u", line_no);
+ append_sp_to_msg_buf(at);
+}
+
+/*
+ * Writes the final part of the log message to `msg_buf` (resets the
+ * terminal color and appends a newline), and then writes the whole log
+ * message to the standard error.
+ */
+static
+void common_write_fini(char ** const at)
+{
+ append_str_to_msg_buf(at, bt_common_color_reset());
+ append_char_to_msg_buf(at, '\n');
+ (void) write(STDERR_FILENO, msg_buf, *at - msg_buf);
+}
+
+void bt_log_write(const char * const file_name, const char * const func_name,
+ const unsigned int line_no, const enum bt_log_level lvl,
+ const char * const tag, const char * const msg)
+{
+ char *at = msg_buf;
+
+ common_write_init(&at, file_name, func_name, line_no, lvl, tag);
+ append_str_to_msg_buf(&at, msg);
+ common_write_fini(&at);
+}
+
+_BT_LOG_PRINTFLIKE(6, 0)
+static
+void write_vprintf(const char * const file_name, const char * const func_name,
+ const unsigned int line_no, const enum bt_log_level lvl,
+ const char * const tag, const char * const fmt, va_list args)
+{
+ char *at = msg_buf;
+ int written_len;
+
+ common_write_init(&at, file_name, func_name, line_no, lvl, tag);
+ written_len = vsnprintf(at, avail_msg_buf_bytes(at) - 16,
+ fmt, args);
+ if (written_len > 0) {
+ at += (size_t) written_len;
+ }
+
+ common_write_fini(&at);
+}
+
+void bt_log_write_printf(const char * const file_name,
+ const char * const func_name, const unsigned int line_no,
+ const enum bt_log_level lvl, const char * const tag,
+ const char * const fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ write_vprintf(file_name, func_name, line_no, lvl, tag, fmt, va);
+ va_end(va);
+}
+
+/*
+ * Writes the initial part of the log message to `msg_buf`, including
+ * the initial message and `errno` string, without the message and
+ * without resetting the terminal color).
+ */
+static
+void common_write_errno_init(char ** const at, const char * const file_name,
+ const char * const func_name, const unsigned int line_no,
+ const enum bt_log_level lvl, const char * const tag,
+ const char * const init_msg)
+{
+ BT_ASSERT_DBG(errno != 0);
+ const char * const errno_msg = g_strerror(errno);
+
+ common_write_init(at, file_name, func_name, line_no, lvl, tag);
+ append_str_to_msg_buf(at, init_msg);
+ append_char_to_msg_buf(at, ':');
+ append_sp_to_msg_buf(at);
+ append_str_to_msg_buf(at, errno_msg);
+}
+
+void bt_log_write_errno(const char * const file_name,
+ const char * const func_name, const unsigned int line_no,
+ const enum bt_log_level lvl, const char * const tag,
+ const char * const init_msg, const char * const msg)
+{
+ char *at = msg_buf;
+
+ common_write_errno_init(&at, file_name, func_name, line_no, lvl,
+ tag, init_msg);
+ append_str_to_msg_buf(&at, msg);
+ common_write_fini(&at);
+}
+
+void bt_log_write_errno_printf(const char * const file_name,
+ const char * const func_name, const unsigned int line_no,
+ const enum bt_log_level lvl, const char * const tag,
+ const char * const init_msg, const char * const fmt, ...)
+{
+ char *at = msg_buf;
+ int written_len;
+ va_list va;
+
+ common_write_errno_init(&at, file_name, func_name, line_no, lvl,
+ tag, init_msg);
+ va_start(va, fmt);
+ written_len = vsnprintf(at, avail_msg_buf_bytes(at) - 16, fmt, va);
+ va_end(va);
+ if (written_len > 0) {
+ at += (size_t) written_len;
+ }
+
+ common_write_fini(&at);
+}
+
+/*
+ * Logs `mem_len` bytes of `mem_data` on a single line.
+ */
+static
+void write_mem_line(const char * const file_name, const char * const func_name,
+ const unsigned int line_no, const enum bt_log_level lvl,
+ const char * const tag, const uint8_t * const mem_data,
+ const size_t mem_len, const size_t max_mem_line_len)
+{
+ static const char * const hex_chars = "0123456789abcdef";
+ char *at = msg_buf;
+ size_t i;
+
+ common_write_init(&at, file_name, func_name, line_no, lvl, tag);
+
+ /* Write hexadecimal representation */
+ for (i = 0; i < mem_len; i++) {
+ const uint8_t byte = mem_data[i];
+
+ /* Write nibble */
+ append_char_to_msg_buf(&at, hex_chars[byte >> 4]);
+ append_char_to_msg_buf(&at, hex_chars[byte & 0xf]);
+
+ /* Add a space */
+ append_sp_to_msg_buf(&at);
+ }
+
+ /* Insert spaces to align the following ASCII representation */
+ for (i = 0; i < max_mem_line_len - mem_len; i++) {
+ append_sp_to_msg_buf(&at);
+ append_sp_to_msg_buf(&at);
+ append_sp_to_msg_buf(&at);
+ }
+
+ /* Insert a vertical line between the representations */
+ append_str_to_msg_buf(&at, "| ");
+
+ /* Write the ASCII representation */
+ for (i = 0; i < mem_len; i++) {
+ const uint8_t byte = mem_data[i];
+
+ if (isprint(byte)) {
+ append_char_to_msg_buf(&at, (char) byte);
+ } else {
+ /* Non-printable character */
+ append_char_to_msg_buf(&at, '.');
+ }
+ }
+
+ common_write_fini(&at);
+}
+
+/*
+ * Logs `mem_len` bytes of `mem_data` on one or more lines.
+ */
+static
+void write_mem_lines(const char * const file_name, const char * const func_name,
+ const unsigned int line_no, const enum bt_log_level lvl,
+ const char * const tag, const uint8_t * const mem_data,
+ const size_t mem_len)
+{
+ const uint8_t *mem_at = mem_data;
+ size_t rem_mem_len = mem_len;
+
+ if (!mem_data || mem_len == 0) {
+ /* Nothing to write */
+ goto end;
+ }
+
+ while (rem_mem_len > 0) {
+ static const size_t max_mem_line_len = 16;
+
+ /* Number of bytes to write on this line */
+ const size_t mem_line_len = rem_mem_len > max_mem_line_len ?
+ max_mem_line_len : rem_mem_len;
+
+ /* Log those bytes */
+ write_mem_line(file_name, func_name, line_no, lvl, tag,
+ mem_at, mem_line_len, max_mem_line_len);
+
+ /* Adjust for next iteration */
+ rem_mem_len -= mem_line_len;
+ mem_at += mem_line_len;
+ }
+
+end:
+ return;
+}
+
+void bt_log_write_mem(const char * const file_name, const char * const func_name,
+ const unsigned int line_no, const enum bt_log_level lvl,
+ const char * const tag, const void * const mem_data,
+ const size_t mem_len, const char * const msg)
+{
+ bt_log_write(file_name, func_name, line_no, lvl, tag, msg);
+ write_mem_lines(file_name, func_name, line_no, lvl, tag,
+ mem_data, mem_len);
+}
+
+void bt_log_write_mem_printf(const char * const file_name,
+ const char * const func_name, const unsigned int line_no,
+ const enum bt_log_level lvl, const char * const tag,
+ const void * const mem_data, const size_t mem_len,
+ const char * const fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ write_vprintf(file_name, func_name, line_no, lvl, tag, fmt, va);
+ va_end(va);
+
+ write_mem_lines(file_name, func_name, line_no, lvl, tag,
+ mem_data, mem_len);
+}
--- /dev/null
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright (c) 2016 wonder-mice
+ * Copyright (c) 2016-2023 Philippe Proulx <pproulx@efficios.com>
+ *
+ * This is very inspired by zf_log.h (see
+ * <https://github.com/wonder-mice/zf_log/>), but modified (mostly
+ * stripped down) for the use cases of Babeltrace.
+ */
+
+#ifndef BABELTRACE_LOGGING_LOG_API_H
+#define BABELTRACE_LOGGING_LOG_API_H
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <babeltrace2/babeltrace.h>
+
+/* Access private `__BT_LOGGING_LEVEL_*` macros. */
+#define __BT_IN_BABELTRACE_H
+#include <babeltrace2/logging-defs.h>
+#undef __BT_IN_BABELTRACE_H
+
+#include "common/macros.h"
+#include "common/assert.h"
+
+/* Log levels */
+enum bt_log_level {
+ BT_LOG_TRACE = __BT_LOGGING_LEVEL_TRACE,
+ BT_LOG_DEBUG = __BT_LOGGING_LEVEL_DEBUG,
+ BT_LOG_INFO = __BT_LOGGING_LEVEL_INFO,
+ BT_LOG_WARNING = __BT_LOGGING_LEVEL_WARNING,
+ BT_LOG_ERROR = __BT_LOGGING_LEVEL_ERROR,
+ BT_LOG_FATAL = __BT_LOGGING_LEVEL_FATAL,
+ BT_LOG_NONE = __BT_LOGGING_LEVEL_NONE,
+};
+
+/*
+ * `BT_LOG_MINIMAL_LEVEL` (constant integer, mandatory): minimal log
+ * level to completely disable (not build) logging with levels that are
+ * more verbose.
+ */
+#ifndef BT_LOG_MINIMAL_LEVEL
+# error "`BT_LOG_MINIMAL_LEVEL` must to defined"
+#endif
+
+/* Internal: portable printf()-like attribute */
+#if defined(__printflike)
+# define _BT_LOG_PRINTFLIKE(_str_index, _first_to_check) \
+ __printflike(_str_index, _first_to_check)
+#elif defined(__MINGW_PRINTF_FORMAT)
+# define _BT_LOG_PRINTFLIKE(_str_index, _first_to_check) \
+ __attribute__((format(__MINGW_PRINTF_FORMAT, _str_index, _first_to_check)))
+#elif defined(__GNUC__)
+# define _BT_LOG_PRINTFLIKE(_str_index, _first_to_check) \
+ __attribute__((format(__printf__, _str_index, _first_to_check)))
+#else
+# define _BT_LOG_PRINTFLIKE(_str_index, _first_to_check)
+#endif
+
+/*
+ * Runs `_expr` if `_cond` is true.
+ */
+#define BT_LOG_IF(_cond, _expr) do { if (_cond) { _expr; } } while (0)
+
+/*
+ * Returns whether or not `_lvl` is enabled at build time, that is, it's
+ * equally or less verbose than `BT_LOG_MINIMAL_LEVEL`.
+ *
+ * See `BT_LOG_MINIMAL_LEVEL` to learn more.
+ */
+#define BT_LOG_ENABLED(_lvl) ((_lvl) >= BT_LOG_MINIMAL_LEVEL)
+#define BT_LOG_ENABLED_TRACE BT_LOG_ENABLED(__BT_LOGGING_LEVEL_TRACE)
+#define BT_LOG_ENABLED_DEBUG BT_LOG_ENABLED(__BT_LOGGING_LEVEL_DEBUG)
+#define BT_LOG_ENABLED_INFO BT_LOG_ENABLED(__BT_LOGGING_LEVEL_INFO)
+#define BT_LOG_ENABLED_WARNING BT_LOG_ENABLED(__BT_LOGGING_LEVEL_WARNING)
+#define BT_LOG_ENABLED_ERROR BT_LOG_ENABLED(__BT_LOGGING_LEVEL_ERROR)
+#define BT_LOG_ENABLED_FATAL BT_LOG_ENABLED(__BT_LOGGING_LEVEL_FATAL)
+
+/*
+ * Returns whether or not `_lvl` is enabled at run time, that is, it's
+ * equally or less verbose than some current (run-time) level
+ * `_cur_lvl`.
+ */
+#define BT_LOG_ON_CUR_LVL(_lvl, _cur_lvl) \
+ G_UNLIKELY(BT_LOG_ENABLED((_lvl)) && (_lvl) >= (_cur_lvl))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Writes the log message `msg` using the file name `file_name`, the
+ * function name `func_name`, the line number `line_no`, the log level
+ * `lvl`, and the tag `tag`.
+ *
+ * NOTE: This function writes unconditionally, without checking the
+ * current (run-time) log level.
+ */
+void bt_log_write(const char *file_name, const char *func_name,
+ unsigned int line_no, enum bt_log_level lvl, const char *tag,
+ const char *msg);
+
+/*
+ * Calls bt_log_write(), formatting the log message through sprintf()
+ * with `fmt` and the following arguments.
+ */
+void bt_log_write_printf(const char *file_name, const char *func_name,
+ unsigned int line_no, enum bt_log_level lvl, const char *tag,
+ const char *fmt, ...) _BT_LOG_PRINTFLIKE(6, 7);
+
+/*
+ * Writes the log message `msg` using the file name `file_name`, the
+ * function name `func_name`, the line number `line_no`, the log level
+ * `lvl`, and the tag `tag`, and also dumps `mem_len` bytes of
+ * `mem_data`.
+ *
+ * NOTE: This function writes unconditionally, without checking the
+ * current (run-time) log level.
+ */
+void bt_log_write_mem(const char *file_name, const char *func_name,
+ unsigned int line_no, enum bt_log_level lvl, const char *tag,
+ const void *mem_data, size_t mem_len,
+ const char *msg);
+
+/*
+ * Calls bt_log_write_mem(), formatting the log message through
+ * sprintf() with `fmt` and the following arguments.
+ */
+void bt_log_write_mem_printf(const char *file_name, const char *func_name,
+ unsigned int line_no, enum bt_log_level lvl, const char *tag,
+ const void *mem_data, size_t mem_len,
+ const char *fmt, ...) _BT_LOG_PRINTFLIKE(8, 9);
+
+/*
+ * Writes:
+ *
+ * 1. `init_msg`
+ * 2. The string `: `
+ * 3. The message corresponding to `errno` (current error number)
+ * 4. `msg`
+ *
+ * This function uses the file name `file_name`, the function name
+ * `func_name`, the line number `line_no`, the log level `lvl`, and the
+ * tag `tag`.
+ *
+ * NOTE: This function writes unconditionally, without checking the
+ * current (run-time) log level.
+ */
+void bt_log_write_errno(const char *file_name, const char *func_name,
+ unsigned int line_no, enum bt_log_level lvl, const char *tag,
+ const char *init_msg, const char *msg);
+
+/*
+ * Calls bt_log_write_errno(), formatting the log message through
+ * sprintf() with `fmt` and the following arguments.
+ */
+void bt_log_write_errno_printf(const char *file_name, const char *func_name,
+ unsigned int line_no, enum bt_log_level lvl, const char *tag,
+ const char *init_msg,
+ const char *fmt, ...) _BT_LOG_PRINTFLIKE(7, 8);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * Calls bt_log_write() if logging is enabled at run time for the
+ * current level `_cur_lvl`.
+ *
+ * Passes the current file name, function name, and line number to
+ * bt_log_write().
+ */
+#define BT_LOG_WRITE_CUR_LVL(_lvl, _cur_lvl, _tag, _msg) \
+ do { \
+ if (BT_LOG_ON_CUR_LVL((_lvl), (_cur_lvl))) { \
+ bt_log_write(__FILE__, __func__, __LINE__, \
+ (_lvl), (_tag), (_msg)); \
+ } \
+ } while (0)
+
+/*
+ * Calls bt_log_write_printf() if logging is enabled at run time for the
+ * current level `_cur_lvl`.
+ *
+ * Passes the current file name, function name, and line number to
+ * bt_log_write_printf().
+ */
+#define BT_LOG_WRITE_PRINTF_CUR_LVL(_lvl, _cur_lvl, _tag, _fmt, ...) \
+ do { \
+ if (BT_LOG_ON_CUR_LVL((_lvl), (_cur_lvl))) { \
+ bt_log_write_printf(__FILE__, __func__, \
+ __LINE__, (_lvl), (_tag), (_fmt), \
+ ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+/*
+ * Calls bt_log_write_mem() if logging is enabled at run time for the
+ * current level `_cur_lvl`.
+ *
+ * Passes the current file name, function name, and line number to
+ * bt_log_write_mem().
+ */
+#define BT_LOG_WRITE_MEM_CUR_LVL(_lvl, _cur_lvl, _tag, _mem_data, _mem_len, _msg) \
+ do { \
+ if (BT_LOG_ON_CUR_LVL((_lvl), (_cur_lvl))) { \
+ bt_log_write_mem(__FILE__, __func__, __LINE__, \
+ (_lvl), (_tag), (_mem_data), \
+ (_mem_len), (_msg)); \
+ } \
+ } while (0)
+
+/*
+ * Calls bt_log_write_mem_printf() if logging is enabled at run time for
+ * the current level `_cur_lvl`.
+ *
+ * Passes the current file name, function name, and line number to
+ * bt_log_write_mem_printf().
+ */
+#define BT_LOG_WRITE_MEM_PRINTF_CUR_LVL(_lvl, _cur_lvl, _tag, _mem_data, _mem_len, _fmt, ...) \
+ do { \
+ if (BT_LOG_ON_CUR_LVL((_lvl), (_cur_lvl))) { \
+ bt_log_write_mem_printf(__FILE__, __func__, \
+ __LINE__, (_lvl), (_tag), (_mem_data), \
+ (_mem_len), (_fmt), ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+/*
+ * Calls bt_log_write_errno() if logging is enabled at run time for the
+ * current level `_cur_lvl`.
+ *
+ * Passes the current file name, function name, and line number to
+ * bt_log_write_errno().
+ */
+#define BT_LOG_WRITE_ERRNO_CUR_LVL(_lvl, _cur_lvl, _tag, _init_msg, _msg) \
+ do { \
+ if (BT_LOG_ON_CUR_LVL((_lvl), (_cur_lvl))) { \
+ bt_log_write_errno(__FILE__, __func__, \
+ __LINE__, (_lvl), (_tag), (_init_msg), \
+ (_msg)); \
+ } \
+ } while (0)
+
+/*
+ * Calls bt_log_write_errno_printf() if logging is enabled at run time
+ * for the current level `_cur_lvl`.
+ *
+ * Passes the current file name, function name, and line number to
+ * bt_log_write_errno_printf().
+ */
+#define BT_LOG_WRITE_ERRNO_PRINTF_CUR_LVL(_lvl, _cur_lvl, _tag, _init_msg, _fmt, ...) \
+ do { \
+ if (BT_LOG_ON_CUR_LVL((_lvl), (_cur_lvl))) { \
+ bt_log_write_errno_printf(__FILE__, __func__, \
+ __LINE__, (_lvl), (_tag), (_init_msg), \
+ (_fmt), ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+/*
+ * Returns the equivalent letter of the log level `level`.
+ *
+ * `level` must be a valid log level.
+ */
+static inline
+char bt_log_get_letter_from_level(const enum bt_log_level level)
+{
+ char letter;
+
+ switch (level) {
+ case BT_LOG_TRACE:
+ letter = 'T';
+ break;
+ case BT_LOG_DEBUG:
+ letter = 'D';
+ break;
+ case BT_LOG_INFO:
+ letter = 'I';
+ break;
+ case BT_LOG_WARNING:
+ letter = 'W';
+ break;
+ case BT_LOG_ERROR:
+ letter = 'E';
+ break;
+ case BT_LOG_FATAL:
+ letter = 'F';
+ break;
+ case BT_LOG_NONE:
+ letter = 'N';
+ break;
+ default:
+ abort();
+ }
+
+ return letter;
+}
+
+/*
+ * Returns the log level as an integer for the string `str`, or -1 if
+ * `str` is not a valid log level string.
+ */
+static inline
+int bt_log_get_level_from_string(const char * const str)
+{
+ int level = -1;
+
+ BT_ASSERT(str);
+
+ if (strcmp(str, "TRACE") == 0 || strcmp(str, "T") == 0) {
+ level = BT_LOG_TRACE;
+ } else if (strcmp(str, "DEBUG") == 0 || strcmp(str, "D") == 0) {
+ level = BT_LOG_DEBUG;
+ } else if (strcmp(str, "INFO") == 0 || strcmp(str, "I") == 0) {
+ level = BT_LOG_INFO;
+ } else if (strcmp(str, "WARN") == 0 ||
+ strcmp(str, "WARNING") == 0 ||
+ strcmp(str, "W") == 0) {
+ level = BT_LOG_WARNING;
+ } else if (strcmp(str, "ERROR") == 0 || strcmp(str, "E") == 0) {
+ level = BT_LOG_ERROR;
+ } else if (strcmp(str, "FATAL") == 0 || strcmp(str, "F") == 0) {
+ level = BT_LOG_FATAL;
+ } else if (strcmp(str, "NONE") == 0 || strcmp(str, "N") == 0) {
+ level = BT_LOG_NONE;
+ } else {
+ /* FIXME: Should we warn here? How? */
+ }
+
+ return level;
+}
+
+/*
+ * Returns the log level as an integer for the letter `letter`, or -1 if
+ * `letter` is not a valid log level string.
+ */
+static inline
+int bt_log_get_level_from_letter(const char letter)
+{
+ const char str[] = {letter, '\0'};
+
+ return bt_log_get_level_from_string(str);
+}
+
+/*
+ * Returns the log level for the value of the environment variable named
+ * `env_var_name`, or `BT_LOG_NONE` if not a valid log level string.
+ */
+static inline
+enum bt_log_level bt_log_get_level_from_env(const char *env_var_name)
+{
+ const char * const varval = getenv(env_var_name);
+ enum bt_log_level level = BT_LOG_NONE;
+ int int_level;
+
+ if (!varval) {
+ goto end;
+ }
+
+ int_level = bt_log_get_level_from_string(varval);
+ if (int_level < 0) {
+ /* FIXME: Should we warn here? How? */
+ int_level = BT_LOG_NONE;
+ }
+
+ level = (enum bt_log_level) int_level;
+
+end:
+ return level;
+}
+
+/*
+ * Declares the variable named `_level_sym` as an external symbol
+ * containing a log level.
+ */
+#define BT_LOG_LEVEL_EXTERN_SYMBOL(_level_sym) \
+ extern enum bt_log_level _level_sym
+
+/*
+ * 1. Defines the log level variable `_level_sym`, initializing it to
+ * `BT_LOG_NONE` (logging disabled).
+ *
+ * 2. Defines a library constructor named _bt_log_level_ctor() which
+ * initializes the log level variable `_level_sym` from the value of
+ * the environment variable named `_env_var_name`.
+ */
+#define BT_LOG_INIT_LOG_LEVEL(_level_sym, _env_var_name) \
+ enum bt_log_level _level_sym = BT_LOG_NONE; \
+ static \
+ void __attribute__((constructor)) _bt_log_level_ctor(void) \
+ { \
+ _level_sym = bt_log_get_level_from_env(_env_var_name); \
+ }
+
+#endif /* BABELTRACE_LOGGING_LOG_API_H */
+++ /dev/null
-/*
- * SPDX-License-Identifier: MIT
- *
- * Copyright (c) 2016 wonder-mice
- *
- * This is zf_log.c, modified with Babeltrace prefixes.
- * See <https://github.com/wonder-mice/zf_log/>.
- */
-
-#include "common/macros.h"
-#include "common/common.h"
-#include <pthread.h>
-#include "common/assert.h"
-
-#ifdef __CYGWIN__
-extern unsigned long pthread_getsequence_np(pthread_t *);
-#endif
-
-/* When defined, Android log (android/log.h) will be used by default instead of
- * stderr (ignored on non-Android platforms). Date, time, pid and tid (context)
- * will be provided by Android log. Android log features will be used to output
- * log level and tag.
- */
-#ifdef BT_LOG_USE_ANDROID_LOG
- #undef BT_LOG_USE_ANDROID_LOG
- #if defined(__ANDROID__)
- #define BT_LOG_USE_ANDROID_LOG 1
- #else
- #define BT_LOG_USE_ANDROID_LOG 0
- #endif
-#else
- #define BT_LOG_USE_ANDROID_LOG 0
-#endif
-/* When defined, NSLog (uses Apple System Log) will be used instead of stderr
- * (ignored on non-Apple platforms). Date, time, pid and tid (context) will be
- * provided by NSLog. Curiously, doesn't use NSLog() directly, but piggybacks on
- * non-public CFLog() function. Both use Apple System Log internally, but it's
- * easier to call CFLog() from C than NSLog(). Current implementation doesn't
- * support "%@" format specifier.
- */
-#ifdef BT_LOG_USE_NSLOG
- #undef BT_LOG_USE_NSLOG
- #if defined(__APPLE__) && defined(__MACH__)
- #define BT_LOG_USE_NSLOG 1
- #else
- #define BT_LOG_USE_NSLOG 0
- #endif
-#else
- #define BT_LOG_USE_NSLOG 0
-#endif
-/* When defined, OutputDebugString() will be used instead of stderr (ignored on
- * non-Windows platforms). Uses OutputDebugStringA() variant and feeds it with
- * UTF-8 data.
- */
-#ifdef BT_LOG_USE_DEBUGSTRING
- #undef BT_LOG_USE_DEBUGSTRING
- #if defined(_WIN32) || defined(_WIN64)
- #define BT_LOG_USE_DEBUGSTRING 1
- #else
- #define BT_LOG_USE_DEBUGSTRING 0
- #endif
-#else
- #define BT_LOG_USE_DEBUGSTRING 0
-#endif
-/* When defined, bt_log library will not contain definition of tag prefix
- * variable. In that case it must be defined elsewhere using
- * BT_LOG_DEFINE_TAG_PREFIX macro, for example:
- *
- * BT_LOG_DEFINE_TAG_PREFIX = "ProcessName";
- *
- * This allows to specify custom value for static initialization and avoid
- * overhead of setting this value in runtime.
- */
-#ifdef BT_LOG_EXTERN_TAG_PREFIX
- #undef BT_LOG_EXTERN_TAG_PREFIX
- #define BT_LOG_EXTERN_TAG_PREFIX 1
-#else
- #define BT_LOG_EXTERN_TAG_PREFIX 0
-#endif
-/* When defined, bt_log library will not contain definition of global format
- * variable. In that case it must be defined elsewhere using
- * BT_LOG_DEFINE_GLOBAL_FORMAT macro, for example:
- *
- * BT_LOG_DEFINE_GLOBAL_FORMAT = {MEM_WIDTH};
- *
- * This allows to specify custom value for static initialization and avoid
- * overhead of setting this value in runtime.
- */
-#ifdef BT_LOG_EXTERN_GLOBAL_FORMAT
- #undef BT_LOG_EXTERN_GLOBAL_FORMAT
- #define BT_LOG_EXTERN_GLOBAL_FORMAT 1
-#else
- #define BT_LOG_EXTERN_GLOBAL_FORMAT 0
-#endif
-/* When defined, bt_log library will not contain definition of global output
- * variable. In that case it must be defined elsewhere using
- * BT_LOG_DEFINE_GLOBAL_OUTPUT macro, for example:
- *
- * BT_LOG_DEFINE_GLOBAL_OUTPUT = {BT_LOG_PUT_STD, custom_output_callback};
- *
- * This allows to specify custom value for static initialization and avoid
- * overhead of setting this value in runtime.
- */
-#ifdef BT_LOG_EXTERN_GLOBAL_OUTPUT
- #undef BT_LOG_EXTERN_GLOBAL_OUTPUT
- #define BT_LOG_EXTERN_GLOBAL_OUTPUT 1
-#else
- #define BT_LOG_EXTERN_GLOBAL_OUTPUT 0
-#endif
-/* When defined, bt_log library will not contain definition of global output
- * level variable. In that case it must be defined elsewhere using
- * BT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL macro, for example:
- *
- * BT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL = BT_LOG_WARNING;
- *
- * This allows to specify custom value for static initialization and avoid
- * overhead of setting this value in runtime.
- */
-#ifdef BT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL
- #undef BT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL
- #define BT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL 1
-#else
- #define BT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL 0
-#endif
-/* When defined, implementation will prefer smaller code size over speed.
- * Very rough estimate is that code will be up to 2x smaller and up to 2x
- * slower. Disabled by default.
- */
-#ifdef BT_LOG_OPTIMIZE_SIZE
- #undef BT_LOG_OPTIMIZE_SIZE
- #define BT_LOG_OPTIMIZE_SIZE 1
-#else
- #define BT_LOG_OPTIMIZE_SIZE 0
-#endif
-/* Size of the log line buffer. The buffer is a globally allocated per thread.
- */
-#ifndef BT_LOG_BUF_SZ
- #define BT_LOG_BUF_SZ (4 * 4096)
-#endif
-/* Default number of bytes in one line of memory output. For large values
- * BT_LOG_BUF_SZ also must be increased.
- */
-#ifndef BT_LOG_MEM_WIDTH
- #define BT_LOG_MEM_WIDTH 32
-#endif
-/* String to put in the end of each log line (can be empty). Its value used by
- * stderr output callback. Its size used as a default value for BT_LOG_EOL_SZ.
- */
-#ifndef BT_LOG_EOL
- #define BT_LOG_EOL "\n"
-#endif
-/* Default delimiter that separates parts of log message. Can NOT contain '%'
- * or '\0'.
- *
- * Log message format specifications can override (or ignore) this value. For
- * more details see BT_LOG_MESSAGE_CTX_FORMAT, BT_LOG_MESSAGE_SRC_FORMAT and
- * BT_LOG_MESSAGE_TAG_FORMAT.
- */
-#ifndef BT_LOG_DEF_DELIMITER
- #define BT_LOG_DEF_DELIMITER " "
-#endif
-/* Specifies log message context format. Log message context includes date,
- * time, process id, thread id and message's log level. Custom information can
- * be added as well. Supported fields: YEAR, MONTH, DAY, HOUR, MINUTE, SECOND,
- * MILLISECOND, PID, TID, LEVEL, S(str), F_INIT(statements),
- * F_UINT(width, value).
- *
- * Must be defined as a tuple, for example:
- *
- * #define BT_LOG_MESSAGE_CTX_FORMAT (YEAR, S("."), MONTH, S("."), DAY, S(" > "))
- *
- * In that case, resulting log message will be:
- *
- * 2016.12.22 > TAG function@filename.c:line Message text
- *
- * Note, that tag, source location and message text are not impacted by
- * this setting. See BT_LOG_MESSAGE_TAG_FORMAT and BT_LOG_MESSAGE_SRC_FORMAT.
- *
- * If message context must be visually separated from the rest of the message,
- * it must be reflected in context format (notice trailing S(" > ") in the
- * example above).
- *
- * S(str) adds constant string str. String can NOT contain '%' or '\0'.
- *
- * F_INIT(statements) adds initialization statement(s) that will be evaluated
- * once for each log message. All statements are evaluated in specified order.
- * Several F_INIT() fields can be used in every log message format
- * specification. Fields, like F_UINT(width, value), are allowed to use results
- * of initialization statements. If statement introduces variables (or other
- * names, like structures) they must be prefixed with "f_". Statements must be
- * enclosed into additional "()". Example:
- *
- * #define BT_LOG_MESSAGE_CTX_FORMAT \
- * (F_INIT(( struct rusage f_ru; getrusage(RUSAGE_SELF, &f_ru); )), \
- * YEAR, S("."), MONTH, S("."), DAY, S(" "), \
- * F_UINT(5, f_ru.ru_nsignals), \
- * S(" "))
- *
- * F_UINT(width, value) adds unsigned integer value extended with up to width
- * spaces (for alignment purposes). Value can be any expression that evaluates
- * to unsigned integer. If expression contains non-standard functions, they
- * must be declared with F_INIT(). Example:
- *
- * #define BT_LOG_MESSAGE_CTX_FORMAT \
- * (YEAR, S("."), MONTH, S("."), DAY, S(" "), \
- * F_INIT(( unsigned tickcount(); )), \
- * F_UINT(5, tickcount()), \
- * S(" "))
- *
- * Other log message format specifications follow same rules, but have a
- * different set of supported fields.
- */
-#ifndef BT_LOG_MESSAGE_CTX_FORMAT
- #define BT_LOG_MESSAGE_CTX_FORMAT \
- (MONTH, S("-"), DAY, S(BT_LOG_DEF_DELIMITER), \
- HOUR, S(":"), MINUTE, S(":"), SECOND, S("."), MILLISECOND, S(BT_LOG_DEF_DELIMITER), \
- PID, S(BT_LOG_DEF_DELIMITER), TID, S(BT_LOG_DEF_DELIMITER), \
- LEVEL, S(BT_LOG_DEF_DELIMITER))
-#endif
-/* Example:
- */
-/* Specifies log message tag format. It includes tag prefix and tag. Custom
- * information can be added as well. Supported fields:
- * TAG(prefix_delimiter, tag_delimiter), S(str), F_INIT(statements),
- * F_UINT(width, value).
- *
- * TAG(prefix_delimiter, tag_delimiter) adds following string to log message:
- *
- * PREFIX<prefix_delimiter>TAG<tag_delimiter>
- *
- * Prefix delimiter will be used only when prefix is not empty. Tag delimiter
- * will be used only when prefixed tag is not empty. Example:
- *
- * #define BT_LOG_TAG_FORMAT (S("["), TAG(".", ""), S("] "))
- *
- * See BT_LOG_MESSAGE_CTX_FORMAT for details.
- */
-#ifndef BT_LOG_MESSAGE_TAG_FORMAT
- #define BT_LOG_MESSAGE_TAG_FORMAT \
- (TAG(".", BT_LOG_DEF_DELIMITER))
-#endif
-/* Specifies log message source location format. It includes function name,
- * file name and file line. Custom information can be added as well. Supported
- * fields: FUNCTION, FILENAME, FILELINE, S(str), F_INIT(statements),
- * F_UINT(width, value).
- *
- * See BT_LOG_MESSAGE_CTX_FORMAT for details.
- */
-#ifndef BT_LOG_MESSAGE_SRC_FORMAT
- #define BT_LOG_MESSAGE_SRC_FORMAT \
- (FUNCTION, S("@"), FILENAME, S(":"), FILELINE, S(BT_LOG_DEF_DELIMITER))
-#endif
-/* Fields that can be used in log message format specifications (see above).
- * Mentioning them here explicitly, so we know that nobody else defined them
- * before us. See BT_LOG_MESSAGE_CTX_FORMAT for details.
- */
-#define YEAR YEAR
-#define MONTH MONTH
-#define DAY DAY
-#define MINUTE MINUTE
-#define SECOND SECOND
-#define MILLISECOND MILLISECOND
-#define PID PID
-#define TID TID
-#define LEVEL LEVEL
-#define TAG(prefix_delim, tag_delim) TAG(prefix_delim, tag_delim)
-#define FUNCTION FUNCTION
-#define FILENAME FILENAME
-#define FILELINE FILELINE
-#define S(str) S(str)
-#define F_INIT(statements) F_INIT(statements)
-#define F_UINT(width, value) F_UINT(width, value)
-/* Number of bytes to reserve for EOL in the log line buffer (must be >0).
- * Must be larger than or equal to length of BT_LOG_EOL with terminating null.
- */
-#ifndef BT_LOG_EOL_SZ
- #define BT_LOG_EOL_SZ sizeof(BT_LOG_EOL)
-#endif
-/* Compile instrumented version of the library to facilitate unit testing.
- */
-#ifndef BT_LOG_INSTRUMENTED
- #define BT_LOG_INSTRUMENTED 0
-#endif
-
-#if defined(__linux__)
- #if !defined(__ANDROID__) && !defined(_GNU_SOURCE)
- #define _GNU_SOURCE
- #endif
-#endif
-#if defined(__MINGW32__)
- #ifdef __STRICT_ANSI__
- #undef __STRICT_ANSI__
- #endif
-#endif
-#include "common/assert.h"
-#include <ctype.h>
-#include <string.h>
-#include <time.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define BT_LOG_OUTPUT_LEVEL dummy
-
-#include "log.h"
-#include <babeltrace2/logging.h>
-
-#if defined(_WIN32) || defined(_WIN64)
- #include <windows.h>
-#else
- #include <unistd.h>
- #include <sys/time.h>
- #if defined(__linux__)
- #include <linux/limits.h>
- #elif (defined(__sun__) || defined(__CYGWIN__) || defined(__GNU__))
- /* Solaris, Cygwin and Hurd have no sys/syslimits.h */
- #else
- #include <sys/syslimits.h>
- #endif
-#endif
-
-#if defined(__linux__)
- #include <sys/prctl.h>
- #include <sys/types.h>
- #if !defined(__ANDROID__)
- #include <sys/syscall.h>
- #endif
-#endif
-#if defined(__MACH__)
- #include <pthread.h>
-#endif
-#if defined(__GNU__)
- #include <mach.h>
-#endif
-
-#define INLINE _BT_LOG_INLINE
-#define VAR_UNUSED(var) (void)var
-#define RETVAL_UNUSED(expr) do { while(expr) break; } while(0)
-#define STATIC_ASSERT(name, cond) \
- typedef char assert_##name[(cond)? 1: -1]
-#define ASSERT_UNREACHABLE(why) assert(!sizeof(why))
-#ifndef _countof
- #define _countof(xs) (sizeof(xs) / sizeof((xs)[0]))
-#endif
-
-#if BT_LOG_INSTRUMENTED
- #define INSTRUMENTED_CONST
-#else
- #define INSTRUMENTED_CONST const
-#endif
-
-#define _PP_PASTE_2(a, b) a ## b
-#define _PP_CONCAT_2(a, b) _PP_PASTE_2(a, b)
-
-#define _PP_PASTE_3(a, b, c) a ## b ## c
-#define _PP_CONCAT_3(a, b, c) _PP_PASTE_3(a, b, c)
-
-/* Microsoft C preprocessor is a piece of shit. This moron treats __VA_ARGS__
- * as a single token and requires additional expansion to realize that it's
- * actually a list. If not for it, there would be no need in this extra
- * expansion.
- */
-#define _PP_ID(x) x
-#define _PP_NARGS_N(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,...) _24
-#define _PP_NARGS(...) _PP_ID(_PP_NARGS_N(__VA_ARGS__,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))
-
-/* There is a more efficient way to implement this, but it requires
- * working C preprocessor. Unfortunately, Microsoft Visual Studio doesn't
- * have one.
- */
-#define _PP_HEAD__(x, ...) x
-#define _PP_HEAD_(...) _PP_ID(_PP_HEAD__(__VA_ARGS__, ~))
-#define _PP_HEAD(xs) _PP_HEAD_ xs
-#define _PP_TAIL_(x, ...) (__VA_ARGS__)
-#define _PP_TAIL(xs) _PP_TAIL_ xs
-#define _PP_UNTUPLE_(...) __VA_ARGS__
-#define _PP_UNTUPLE(xs) _PP_UNTUPLE_ xs
-
-/* Apply function macro to each element in tuple. Output is not
- * enforced to be a tuple.
- */
-#define _PP_MAP_1(f, xs) f(_PP_HEAD(xs))
-#define _PP_MAP_2(f, xs) f(_PP_HEAD(xs)) _PP_MAP_1(f, _PP_TAIL(xs))
-#define _PP_MAP_3(f, xs) f(_PP_HEAD(xs)) _PP_MAP_2(f, _PP_TAIL(xs))
-#define _PP_MAP_4(f, xs) f(_PP_HEAD(xs)) _PP_MAP_3(f, _PP_TAIL(xs))
-#define _PP_MAP_5(f, xs) f(_PP_HEAD(xs)) _PP_MAP_4(f, _PP_TAIL(xs))
-#define _PP_MAP_6(f, xs) f(_PP_HEAD(xs)) _PP_MAP_5(f, _PP_TAIL(xs))
-#define _PP_MAP_7(f, xs) f(_PP_HEAD(xs)) _PP_MAP_6(f, _PP_TAIL(xs))
-#define _PP_MAP_8(f, xs) f(_PP_HEAD(xs)) _PP_MAP_7(f, _PP_TAIL(xs))
-#define _PP_MAP_9(f, xs) f(_PP_HEAD(xs)) _PP_MAP_8(f, _PP_TAIL(xs))
-#define _PP_MAP_10(f, xs) f(_PP_HEAD(xs)) _PP_MAP_9(f, _PP_TAIL(xs))
-#define _PP_MAP_11(f, xs) f(_PP_HEAD(xs)) _PP_MAP_10(f, _PP_TAIL(xs))
-#define _PP_MAP_12(f, xs) f(_PP_HEAD(xs)) _PP_MAP_11(f, _PP_TAIL(xs))
-#define _PP_MAP_13(f, xs) f(_PP_HEAD(xs)) _PP_MAP_12(f, _PP_TAIL(xs))
-#define _PP_MAP_14(f, xs) f(_PP_HEAD(xs)) _PP_MAP_13(f, _PP_TAIL(xs))
-#define _PP_MAP_15(f, xs) f(_PP_HEAD(xs)) _PP_MAP_14(f, _PP_TAIL(xs))
-#define _PP_MAP_16(f, xs) f(_PP_HEAD(xs)) _PP_MAP_15(f, _PP_TAIL(xs))
-#define _PP_MAP_17(f, xs) f(_PP_HEAD(xs)) _PP_MAP_16(f, _PP_TAIL(xs))
-#define _PP_MAP_18(f, xs) f(_PP_HEAD(xs)) _PP_MAP_17(f, _PP_TAIL(xs))
-#define _PP_MAP_19(f, xs) f(_PP_HEAD(xs)) _PP_MAP_18(f, _PP_TAIL(xs))
-#define _PP_MAP_20(f, xs) f(_PP_HEAD(xs)) _PP_MAP_19(f, _PP_TAIL(xs))
-#define _PP_MAP_21(f, xs) f(_PP_HEAD(xs)) _PP_MAP_20(f, _PP_TAIL(xs))
-#define _PP_MAP_22(f, xs) f(_PP_HEAD(xs)) _PP_MAP_21(f, _PP_TAIL(xs))
-#define _PP_MAP_23(f, xs) f(_PP_HEAD(xs)) _PP_MAP_22(f, _PP_TAIL(xs))
-#define _PP_MAP_24(f, xs) f(_PP_HEAD(xs)) _PP_MAP_23(f, _PP_TAIL(xs))
-#define _PP_MAP(f, xs) _PP_CONCAT_2(_PP_MAP_, _PP_NARGS xs) (f, xs)
-
-/* Apply function macro to each element in tuple in reverse order.
- * Output is not enforced to be a tuple.
- */
-#define _PP_RMAP_1(f, xs) f(_PP_HEAD(xs))
-#define _PP_RMAP_2(f, xs) _PP_RMAP_1(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_3(f, xs) _PP_RMAP_2(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_4(f, xs) _PP_RMAP_3(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_5(f, xs) _PP_RMAP_4(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_6(f, xs) _PP_RMAP_5(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_7(f, xs) _PP_RMAP_6(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_8(f, xs) _PP_RMAP_7(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_9(f, xs) _PP_RMAP_8(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_10(f, xs) _PP_RMAP_9(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_11(f, xs) _PP_RMAP_10(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_12(f, xs) _PP_RMAP_11(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_13(f, xs) _PP_RMAP_12(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_14(f, xs) _PP_RMAP_13(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_15(f, xs) _PP_RMAP_14(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_16(f, xs) _PP_RMAP_15(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_17(f, xs) _PP_RMAP_16(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_18(f, xs) _PP_RMAP_17(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_19(f, xs) _PP_RMAP_18(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_20(f, xs) _PP_RMAP_19(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_21(f, xs) _PP_RMAP_20(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_22(f, xs) _PP_RMAP_21(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_23(f, xs) _PP_RMAP_22(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP_24(f, xs) _PP_RMAP_23(f, _PP_TAIL(xs)) f(_PP_HEAD(xs))
-#define _PP_RMAP(f, xs) _PP_CONCAT_2(_PP_RMAP_, _PP_NARGS xs) (f, xs)
-
-/* Used to implement _BT_LOG_MESSAGE_FORMAT_CONTAINS() macro. All possible
- * fields must be mentioned here. Not counting F_INIT() here because it's
- * somewhat special and is handled spearatly (at least for now).
- */
-#define _BT_LOG_MESSAGE_FORMAT_MASK__ (0<<0)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__YEAR (1<<1)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__MONTH (1<<2)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__DAY (1<<3)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__HOUR (1<<4)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__MINUTE (1<<5)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__SECOND (1<<6)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__MILLISECOND (1<<7)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__PID (1<<8)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__TID (1<<9)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__LEVEL (1<<10)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__TAG(ps, ts) (1<<11)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__FUNCTION (1<<12)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__FILENAME (1<<13)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__FILELINE (1<<14)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__S(s) (1<<15)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__F_INIT(expr) (0<<16)
-#define _BT_LOG_MESSAGE_FORMAT_MASK__F_UINT(w, v) (1<<17)
-#define _BT_LOG_MESSAGE_FORMAT_MASK(field) \
- _PP_CONCAT_3(_BT_LOG_MESSAGE_FORMAT_MASK_, _, field)
-
-/* Logical "or" of masks of fields used in specified format specification.
- */
-#define _BT_LOG_MESSAGE_FORMAT_FIELDS(format) \
- (0 _PP_MAP(| _BT_LOG_MESSAGE_FORMAT_MASK, format))
-
-/* Expands to expressions that evaluates to true if field is used in
- * specified format specification. Example:
- *
- * #if _BT_LOG_MESSAGE_FORMAT_CONTAINS(F_UINT, BT_LOG_MESSAGE_CTX_FORMAT)
- * ...
- * #endif
- */
-#define _BT_LOG_MESSAGE_FORMAT_CONTAINS(field, format) \
- (_BT_LOG_MESSAGE_FORMAT_MASK(field) & _BT_LOG_MESSAGE_FORMAT_FIELDS(format))
-
-/* Same, but checks all supported format specifications.
- */
-#define _BT_LOG_MESSAGE_FORMAT_FIELD_USED(field) \
- (_BT_LOG_MESSAGE_FORMAT_CONTAINS(field, BT_LOG_MESSAGE_CTX_FORMAT) || \
- _BT_LOG_MESSAGE_FORMAT_CONTAINS(field, BT_LOG_MESSAGE_TAG_FORMAT) || \
- _BT_LOG_MESSAGE_FORMAT_CONTAINS(field, BT_LOG_MESSAGE_SRC_FORMAT))
-
-#define _BT_LOG_MESSAGE_FORMAT_DATETIME_USED \
- (_BT_LOG_MESSAGE_FORMAT_CONTAINS(YEAR, BT_LOG_MESSAGE_CTX_FORMAT) || \
- _BT_LOG_MESSAGE_FORMAT_CONTAINS(MONTH, BT_LOG_MESSAGE_CTX_FORMAT) || \
- _BT_LOG_MESSAGE_FORMAT_CONTAINS(DAY, BT_LOG_MESSAGE_CTX_FORMAT) || \
- _BT_LOG_MESSAGE_FORMAT_CONTAINS(HOUR, BT_LOG_MESSAGE_CTX_FORMAT) || \
- _BT_LOG_MESSAGE_FORMAT_CONTAINS(MINUTE, BT_LOG_MESSAGE_CTX_FORMAT) || \
- _BT_LOG_MESSAGE_FORMAT_CONTAINS(SECOND, BT_LOG_MESSAGE_CTX_FORMAT) || \
- _BT_LOG_MESSAGE_FORMAT_CONTAINS(MILLISECOND, BT_LOG_MESSAGE_CTX_FORMAT))
-
-#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
- #pragma warning(disable:4204) /* nonstandard extension used: non-constant aggregate initializer */
- #define memccpy _memccpy
-#endif
-
-#if (defined(_MSC_VER) && !defined(__INTEL_COMPILER)) || \
- (defined(__MINGW64__) && !defined(__USE_MINGW_ANSI_STDIO))
- #define vsnprintf(s, sz, fmt, va) fake_vsnprintf(s, sz, fmt, va)
- static int fake_vsnprintf(char *s, size_t sz, const char *fmt, va_list ap)
- {
- const int n = vsnprintf_s(s, sz, _TRUNCATE, fmt, ap);
- return 0 < n? n: (int)sz + 1; /* no need in _vscprintf() for now */
- }
- #if BT_LOG_OPTIMIZE_SIZE
- #define snprintf(s, sz, ...) fake_snprintf(s, sz, __VA_ARGS__)
- static int fake_snprintf(char *s, size_t sz, const char *fmt, ...)
- {
- va_list va;
- va_start(va, fmt);
- const int n = fake_vsnprintf(s, sz, fmt, va);
- va_end(va);
- return n;
- }
- #endif
-#endif
-
-typedef void (*time_cb)(struct tm *const tm, unsigned *const usec);
-typedef void (*pid_cb)(int *const pid, int *const tid);
-typedef void (*buffer_cb)(bt_log_message *msg, char *buf);
-
-typedef struct src_location
-{
- const char *const func;
- const char *const file;
- const unsigned line;
-}
-src_location;
-
-typedef struct mem_block
-{
- const void *const d;
- const unsigned d_sz;
-}
-mem_block;
-
-static void time_callback(struct tm *const tm, unsigned *const usec);
-static void pid_callback(int *const pid, int *const tid);
-static void buffer_callback(bt_log_message *msg, char *buf);
-
-STATIC_ASSERT(eol_fits_eol_sz, sizeof(BT_LOG_EOL) <= BT_LOG_EOL_SZ);
-STATIC_ASSERT(eol_sz_greater_than_zero, 0 < BT_LOG_EOL_SZ);
-STATIC_ASSERT(eol_sz_less_than_buf_sz, BT_LOG_EOL_SZ < BT_LOG_BUF_SZ);
-static const char c_hex[] = "0123456789abcdef";
-
-static __thread char logging_buf[4 * 4096];
-
-static INSTRUMENTED_CONST unsigned g_buf_sz = BT_LOG_BUF_SZ - BT_LOG_EOL_SZ;
-static INSTRUMENTED_CONST time_cb g_time_cb = time_callback;
-static INSTRUMENTED_CONST pid_cb g_pid_cb = pid_callback;
-static INSTRUMENTED_CONST buffer_cb g_buffer_cb = buffer_callback;
-
-#if BT_LOG_USE_ANDROID_LOG
- #include <android/log.h>
-
- static INLINE int android_lvl(const int lvl)
- {
- switch (lvl)
- {
- case BT_LOG_TRACE:
- return ANDROID_LOG_VERBOSE;
- case BT_LOG_DEBUG:
- return ANDROID_LOG_DEBUG;
- case BT_LOG_INFO:
- return ANDROID_LOG_INFO;
- case BT_LOG_WARNING:
- return ANDROID_LOG_WARN;
- case BT_LOG_ERROR:
- return ANDROID_LOG_ERROR;
- case BT_LOG_FATAL:
- return ANDROID_LOG_FATAL;
- default:
- ASSERT_UNREACHABLE("Bad log level");
- return ANDROID_LOG_UNKNOWN;
- }
- }
-
- static void out_android_callback(const bt_log_message *const msg, void *arg)
- {
- VAR_UNUSED(arg);
- *msg->p = 0;
- const char *tag = msg->p;
- if (msg->tag_e != msg->tag_b)
- {
- tag = msg->tag_b;
- *msg->tag_e = 0;
- }
- __android_log_print(android_lvl(msg->lvl), tag, "%s", msg->msg_b);
- }
-
- enum { OUT_ANDROID_MASK = BT_LOG_PUT_STD & ~BT_LOG_PUT_CTX };
- #define OUT_ANDROID OUT_ANDROID_MASK, 0, out_android_callback
-#endif
-
-#if BT_LOG_USE_NSLOG
- #include <CoreFoundation/CoreFoundation.h>
- CF_EXPORT void CFLog(int32_t level, CFStringRef format, ...);
-
- static INLINE int apple_lvl(const int lvl)
- {
- switch (lvl)
- {
- case BT_LOG_TRACE:
- return 7; /* ASL_LEVEL_DEBUG / kCFLogLevelDebug */;
- case BT_LOG_DEBUG:
- return 7; /* ASL_LEVEL_DEBUG / kCFLogLevelDebug */;
- case BT_LOG_INFO:
- return 6; /* ASL_LEVEL_INFO / kCFLogLevelInfo */;
- case BT_LOG_WARNING:
- return 4; /* ASL_LEVEL_WARNING / kCFLogLevelWarning */;
- case BT_LOG_ERROR:
- return 3; /* ASL_LEVEL_ERR / kCFLogLevelError */;
- case BT_LOG_FATAL:
- return 0; /* ASL_LEVEL_EMERG / kCFLogLevelEmergency */;
- default:
- ASSERT_UNREACHABLE("Bad log level");
- return 0; /* ASL_LEVEL_EMERG / kCFLogLevelEmergency */;
- }
- }
-
- static void out_nslog_callback(const bt_log_message *const msg, void *arg)
- {
- VAR_UNUSED(arg);
- *msg->p = 0;
- CFLog(apple_lvl(msg->lvl), CFSTR("%s"), msg->tag_b);
- }
-
- enum { OUT_NSLOG_MASK = BT_LOG_PUT_STD & ~BT_LOG_PUT_CTX };
- #define OUT_NSLOG OUT_NSLOG_MASK, 0, out_nslog_callback
-#endif
-
-#if BT_LOG_USE_DEBUGSTRING
- #include <windows.h>
-
- static void out_debugstring_callback(const bt_log_message *const msg, void *arg)
- {
- VAR_UNUSED(arg);
- msg->p[0] = '\n';
- msg->p[1] = '\0';
- OutputDebugStringA(msg->buf);
- }
-
- enum { OUT_DEBUGSTRING_MASK = BT_LOG_PUT_STD };
- #define OUT_DEBUGSTRING OUT_DEBUGSTRING_MASK, 0, out_debugstring_callback
-#endif
-
-void bt_log_out_stderr_callback(const bt_log_message *const msg, void *arg)
-{
- VAR_UNUSED(arg);
- const size_t eol_len = sizeof(BT_LOG_EOL) - 1;
- memcpy(msg->p, BT_LOG_EOL, eol_len);
-#if defined(_WIN32) || defined(_WIN64)
- /* WriteFile() is atomic for local files opened with FILE_APPEND_DATA and
- without FILE_WRITE_DATA */
- WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg->buf,
- (DWORD)(msg->p - msg->buf + eol_len), 0, 0);
-#else
- /* write() is atomic for buffers less than or equal to PIPE_BUF. */
- RETVAL_UNUSED(write(STDERR_FILENO, msg->buf,
- (size_t)(msg->p - msg->buf) + eol_len));
-#endif
-}
-
-static const bt_log_output out_stderr = {BT_LOG_OUT_STDERR};
-
-#if !BT_LOG_EXTERN_TAG_PREFIX
- BT_LOG_DEFINE_TAG_PREFIX = 0;
-#endif
-
-#if !BT_LOG_EXTERN_GLOBAL_FORMAT
- BT_LOG_DEFINE_GLOBAL_FORMAT = {BT_LOG_MEM_WIDTH};
-#endif
-
-#if !BT_LOG_EXTERN_GLOBAL_OUTPUT
- #if BT_LOG_USE_ANDROID_LOG
- BT_LOG_DEFINE_GLOBAL_OUTPUT = {OUT_ANDROID};
- #elif BT_LOG_USE_NSLOG
- BT_LOG_DEFINE_GLOBAL_OUTPUT = {OUT_NSLOG};
- #elif BT_LOG_USE_DEBUGSTRING
- BT_LOG_DEFINE_GLOBAL_OUTPUT = {OUT_DEBUGSTRING};
- #else
- BT_LOG_DEFINE_GLOBAL_OUTPUT = {BT_LOG_OUT_STDERR};
- #endif
-#endif
-
-#if !BT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL
- BT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL = 0;
-#endif
-
-const bt_log_spec _bt_log_stderr_spec =
-{
- BT_LOG_GLOBAL_FORMAT,
- &out_stderr,
-};
-
-static const bt_log_spec global_spec =
-{
- BT_LOG_GLOBAL_FORMAT,
- BT_LOG_GLOBAL_OUTPUT,
-};
-
-#if _BT_LOG_MESSAGE_FORMAT_CONTAINS(LEVEL, BT_LOG_MESSAGE_CTX_FORMAT)
-static char lvl_char(const int lvl)
-{
- switch (lvl)
- {
- case BT_LOG_TRACE:
- return 'T';
- case BT_LOG_DEBUG:
- return 'D';
- case BT_LOG_INFO:
- return 'I';
- case BT_LOG_WARNING:
- return 'W';
- case BT_LOG_ERROR:
- return 'E';
- case BT_LOG_FATAL:
- return 'F';
- default:
- ASSERT_UNREACHABLE("Bad log level");
- return '?';
- }
-}
-#endif
-
-#define GCCVER_LESS(MAJOR, MINOR, PATCH) \
- (__GNUC__ < MAJOR || \
- (__GNUC__ == MAJOR && (__GNUC_MINOR__ < MINOR || \
- (__GNUC_MINOR__ == MINOR && __GNUC_PATCHLEVEL__ < PATCH))))
-
-#if !defined(__clang__) && defined(__GNUC__) && GCCVER_LESS(4,7,0)
- #define __atomic_load_n(vp, model) __sync_fetch_and_add(vp, 0)
- #define __atomic_fetch_add(vp, n, model) __sync_fetch_and_add(vp, n)
- #define __atomic_sub_fetch(vp, n, model) __sync_sub_and_fetch(vp, n)
- #define __atomic_or_fetch(vp, n, model) __sync_or_and_fetch(vp, n)
- #define __atomic_and_fetch(vp, n, model) __sync_and_and_fetch(vp, n)
- /* Note: will not store old value of *vp in *ep (non-standard behaviour) */
- #define __atomic_compare_exchange_n(vp, ep, d, weak, smodel, fmodel) \
- __sync_bool_compare_and_swap(vp, *(ep), d)
-#endif
-
-#if !BT_LOG_OPTIMIZE_SIZE && !defined(_WIN32) && !defined(_WIN64)
-#define TCACHE
-#define TCACHE_STALE (0x40000000)
-#define TCACHE_FLUID (0x40000000 | 0x80000000)
-static unsigned g_tcache_mode = TCACHE_STALE;
-static struct timeval g_tcache_tv = {0, 0};
-static struct tm g_tcache_tm = {0};
-
-static INLINE int tcache_get(const struct timeval *const tv, struct tm *const tm)
-{
- unsigned mode;
- mode = __atomic_load_n(&g_tcache_mode, __ATOMIC_RELAXED);
- if (0 == (mode & TCACHE_FLUID))
- {
- mode = __atomic_fetch_add(&g_tcache_mode, 1, __ATOMIC_ACQUIRE);
- if (0 == (mode & TCACHE_FLUID))
- {
- if (g_tcache_tv.tv_sec == tv->tv_sec)
- {
- *tm = g_tcache_tm;
- __atomic_sub_fetch(&g_tcache_mode, 1, __ATOMIC_RELEASE);
- return !0;
- }
- __atomic_or_fetch(&g_tcache_mode, TCACHE_STALE, __ATOMIC_RELAXED);
- }
- __atomic_sub_fetch(&g_tcache_mode, 1, __ATOMIC_RELEASE);
- }
- return 0;
-}
-
-static INLINE void tcache_set(const struct timeval *const tv, struct tm *const tm)
-{
- unsigned stale = TCACHE_STALE;
- if (__atomic_compare_exchange_n(&g_tcache_mode, &stale, TCACHE_FLUID,
- 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
- {
- g_tcache_tv = *tv;
- g_tcache_tm = *tm;
- __atomic_and_fetch(&g_tcache_mode, ~TCACHE_FLUID, __ATOMIC_RELEASE);
- }
-}
-#endif
-
-static void time_callback(struct tm *const tm, unsigned *const msec)
-{
-#if !_BT_LOG_MESSAGE_FORMAT_DATETIME_USED
- VAR_UNUSED(tm);
- VAR_UNUSED(msec);
-#else
- #if defined(_WIN32) || defined(_WIN64)
- SYSTEMTIME st;
- GetLocalTime(&st);
- tm->tm_year = st.wYear;
- tm->tm_mon = st.wMonth;
- tm->tm_mday = st.wDay;
- tm->tm_wday = st.wDayOfWeek;
- tm->tm_hour = st.wHour;
- tm->tm_min = st.wMinute;
- tm->tm_sec = st.wSecond;
- *msec = st.wMilliseconds;
- #else
- struct timeval tv;
- gettimeofday(&tv, 0);
- #ifndef TCACHE
- localtime_r(&tv.tv_sec, tm);
- #else
- if (!tcache_get(&tv, tm))
- {
- localtime_r(&tv.tv_sec, tm);
- tcache_set(&tv, tm);
- }
- #endif
- *msec = (unsigned)tv.tv_usec / 1000;
- #endif
-#endif
-}
-
-static void pid_callback(int *const pid, int *const tid)
-{
-#if !_BT_LOG_MESSAGE_FORMAT_CONTAINS(PID, BT_LOG_MESSAGE_CTX_FORMAT)
- VAR_UNUSED(pid);
-#else
- #if defined(_WIN32) || defined(_WIN64)
- *pid = GetCurrentProcessId();
- #else
- *pid = getpid();
- #endif
-#endif
-
-#if !_BT_LOG_MESSAGE_FORMAT_CONTAINS(TID, BT_LOG_MESSAGE_CTX_FORMAT)
- VAR_UNUSED(tid);
-#else
- #if defined(_WIN32) || defined(_WIN64)
- *tid = GetCurrentThreadId();
- #elif defined(__CYGWIN__)
- pthread_t thr = pthread_self();
- *tid = (int)pthread_getsequence_np(&thr);
- #elif defined(__sun__)
- *tid = (int)pthread_self();
- #elif defined(__ANDROID__)
- *tid = gettid();
- #elif defined(__linux__)
- *tid = syscall(SYS_gettid);
- #elif defined(__APPLE__) && defined(__MACH__)
- *tid = (int)pthread_mach_thread_np(pthread_self());
- #elif defined(__GNU__)
- mach_port_t mach_port = mach_thread_self();
- mach_port_deallocate(mach_task_self(), mach_port);
- *tid = (int)mach_port;
- #else
- #define Platform not supported
- #endif
-#endif
-}
-
-static void buffer_callback(bt_log_message *msg, char *buf)
-{
- msg->e = (msg->p = msg->buf = buf) + g_buf_sz;
-}
-
-#if _BT_LOG_MESSAGE_FORMAT_CONTAINS(FUNCTION, BT_LOG_MESSAGE_SRC_FORMAT)
-static const char *funcname(const char *func)
-{
- return func? func: "";
-}
-#endif
-
-#if _BT_LOG_MESSAGE_FORMAT_CONTAINS(FILENAME, BT_LOG_MESSAGE_SRC_FORMAT)
-static const char *filename(const char *file)
-{
- const char *f = file;
- for (const char *p = file; 0 != *p; ++p)
- {
- if ('/' == *p || '\\' == *p)
- {
- f = p + 1;
- }
- }
- return f;
-}
-#endif
-
-static INLINE size_t nprintf_size(bt_log_message *const msg)
-{
- // *nprintf() always puts 0 in the end when input buffer is not empty. This
- // 0 is not desired because its presence sets (ctx->p) to (ctx->e - 1) which
- // leaves space for one more character. Some put_xxx() functions don't use
- // *nprintf() and could use that last character. In that case log line will
- // have multiple (two) half-written parts which is confusing. To workaround
- // that we allow *nprintf() to write its 0 in the eol area (which is always
- // not empty).
- return (size_t)(msg->e - msg->p + 1);
-}
-
-static INLINE void put_nprintf(bt_log_message *const msg, const int n)
-{
- if (0 < n)
- {
- msg->p = n < msg->e - msg->p? msg->p + n: msg->e;
- }
-}
-
-static INLINE char *put_padding_r(const unsigned w, const char wc,
- char *p, char *e)
-{
- for (char *const b = e - w; b < p; *--p = wc) {}
- return p;
-}
-
-static char *put_integer_r(unsigned v, const int sign,
- const unsigned w, const char wc, char *const e)
-{
- static const char _signs[] = {'-', '0', '+'};
- const char *const signs = _signs + 1;
- char *p = e;
- do { *--p = '0' + v % 10; } while (0 != (v /= 10));
- if (0 == sign) return put_padding_r(w, wc, p, e);
- if ('0' != wc)
- {
- *--p = signs[sign];
- return put_padding_r(w, wc, p, e);
- }
- p = put_padding_r(w, wc, p, e + 1);
- *--p = signs[sign];
- return p;
-}
-
-static INLINE char *put_uint_r(const unsigned v, const unsigned w, const char wc,
- char *const e)
-{
- return put_integer_r(v, 0, w, wc, e);
-}
-
-static INLINE char *put_int_r(const int v, const unsigned w, const char wc,
- char *const e)
-{
- return 0 <= v? put_integer_r((unsigned)v, 0, w, wc, e)
- : put_integer_r((unsigned)-v, -1, w, wc, e);
-}
-
-static INLINE char *put_stringn(const char *const s_p, const char *const s_e,
- char *const p, char *const e)
-{
- const ptrdiff_t m = e - p;
- ptrdiff_t n = s_e - s_p;
- if (n > m)
- {
- n = m;
- }
- memcpy(p, s_p, n);
- return p + n;
-}
-
-static INLINE char *put_string(const char *s, char *p, char *const e)
-{
- const ptrdiff_t n = e - p;
- char *const c = (char *)memccpy(p, s, '\0', n);
- return 0 != c? c - 1: e;
-}
-
-static INLINE char *put_uint(unsigned v, const unsigned w, const char wc,
- char *const p, char *const e)
-{
- char buf[16];
- char *const se = buf + _countof(buf);
- char *sp = put_uint_r(v, w, wc, se);
- return put_stringn(sp, se, p, e);
-}
-
-#define PUT_CSTR_R(p, STR) \
- do { \
- for (unsigned i = sizeof(STR) - 1; 0 < i--;) { \
- *--(p) = (STR)[i]; \
- } \
- } _BT_LOG_ONCE
-
-#define PUT_CSTR_CHECKED(p, e, STR) \
- do { \
- for (unsigned i = 0; (e) > (p) && (sizeof(STR) - 1) > i; ++i) { \
- *(p)++ = (STR)[i]; \
- } \
- } _BT_LOG_ONCE
-
-/* F_INIT field support.
- */
-#define _BT_LOG_MESSAGE_FORMAT_INIT__
-#define _BT_LOG_MESSAGE_FORMAT_INIT__YEAR
-#define _BT_LOG_MESSAGE_FORMAT_INIT__MONTH
-#define _BT_LOG_MESSAGE_FORMAT_INIT__DAY
-#define _BT_LOG_MESSAGE_FORMAT_INIT__HOUR
-#define _BT_LOG_MESSAGE_FORMAT_INIT__MINUTE
-#define _BT_LOG_MESSAGE_FORMAT_INIT__SECOND
-#define _BT_LOG_MESSAGE_FORMAT_INIT__MILLISECOND
-#define _BT_LOG_MESSAGE_FORMAT_INIT__PID
-#define _BT_LOG_MESSAGE_FORMAT_INIT__TID
-#define _BT_LOG_MESSAGE_FORMAT_INIT__LEVEL
-#define _BT_LOG_MESSAGE_FORMAT_INIT__TAG(ps, ts)
-#define _BT_LOG_MESSAGE_FORMAT_INIT__FUNCTION
-#define _BT_LOG_MESSAGE_FORMAT_INIT__FILENAME
-#define _BT_LOG_MESSAGE_FORMAT_INIT__FILELINE
-#define _BT_LOG_MESSAGE_FORMAT_INIT__S(s)
-#define _BT_LOG_MESSAGE_FORMAT_INIT__F_INIT(expr) _PP_UNTUPLE(expr);
-#define _BT_LOG_MESSAGE_FORMAT_INIT__F_UINT(w, v)
-#define _BT_LOG_MESSAGE_FORMAT_INIT(field) \
- _PP_CONCAT_3(_BT_LOG_MESSAGE_FORMAT_INIT_, _, field)
-
-/* Implements generation of printf-like format string for log message
- * format specification.
- */
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__ ""
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__YEAR "%04u"
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__MONTH "%02u"
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__DAY "%02u"
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__HOUR "%02u"
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__MINUTE "%02u"
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__SECOND "%02u"
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__MILLISECOND "%03u"
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__PID "%5i"
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__TID "%5i"
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__LEVEL "%c"
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__TAG UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__FUNCTION "%s"
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__FILENAME "%s"
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__FILELINE "%u"
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__S(s) s
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__F_INIT(expr) ""
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT__F_UINT(w, v) "%" #w "u"
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_FMT(field) \
- _PP_CONCAT_3(_BT_LOG_MESSAGE_FORMAT_PRINTF_FMT_, _, field)
-
-/* Implements generation of printf-like format parameters for log message
- * format specification.
- */
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__YEAR ,(unsigned)(tm.tm_year + 1900)
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__MONTH ,(unsigned)(tm.tm_mon + 1)
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__DAY ,(unsigned)tm.tm_mday
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__HOUR ,(unsigned)tm.tm_hour
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__MINUTE ,(unsigned)tm.tm_min
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__SECOND ,(unsigned)tm.tm_sec
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__MILLISECOND ,(unsigned)msec
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__PID ,pid
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__TID ,tid
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__LEVEL ,(char)lvl_char(msg->lvl)
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__TAG UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__FUNCTION ,funcname(src->func)
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__FILENAME ,filename(src->file)
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__FILELINE ,src->line
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__S(s)
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__F_INIT(expr)
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL__F_UINT(w, v) ,v
-#define _BT_LOG_MESSAGE_FORMAT_PRINTF_VAL(field) \
- _PP_CONCAT_3(_BT_LOG_MESSAGE_FORMAT_PRINTF_VAL_, _, field)
-
-/* Implements generation of put_xxx_t statements for log message specification.
- */
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__YEAR p = put_uint_r(tm.tm_year + 1900, 4, '0', p);
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__MONTH p = put_uint_r((unsigned)tm.tm_mon + 1, 2, '0', p);
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__DAY p = put_uint_r((unsigned)tm.tm_mday, 2, '0', p);
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__HOUR p = put_uint_r((unsigned)tm.tm_hour, 2, '0', p);
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__MINUTE p = put_uint_r((unsigned)tm.tm_min, 2, '0', p);
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__SECOND p = put_uint_r((unsigned)tm.tm_sec, 2, '0', p);
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__MILLISECOND p = put_uint_r(msec, 3, '0', p);
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__PID p = put_int_r(pid, 5, ' ', p);
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__TID p = put_int_r(tid, 5, ' ', p);
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__LEVEL *--p = lvl_char(msg->lvl);
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__TAG UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__FUNCTION UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__FILENAME UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__FILELINE UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__S(s) PUT_CSTR_R(p, s);
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__F_INIT(expr)
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R__F_UINT(w, v) p = put_uint_r(v, w, ' ', p);
-#define _BT_LOG_MESSAGE_FORMAT_PUT_R(field) \
- _PP_CONCAT_3(_BT_LOG_MESSAGE_FORMAT_PUT_R_, _, field)
-
-static void put_ctx(bt_log_message *const msg)
-{
- _PP_MAP(_BT_LOG_MESSAGE_FORMAT_INIT, BT_LOG_MESSAGE_CTX_FORMAT)
-#if !_BT_LOG_MESSAGE_FORMAT_FIELDS(BT_LOG_MESSAGE_CTX_FORMAT)
- VAR_UNUSED(msg);
-#else
- #if _BT_LOG_MESSAGE_FORMAT_DATETIME_USED
- struct tm tm;
- unsigned msec;
- g_time_cb(&tm, &msec);
- #endif
- #if _BT_LOG_MESSAGE_FORMAT_CONTAINS(PID, BT_LOG_MESSAGE_CTX_FORMAT) || \
- _BT_LOG_MESSAGE_FORMAT_CONTAINS(TID, BT_LOG_MESSAGE_CTX_FORMAT)
- int pid, tid;
- g_pid_cb(&pid, &tid);
- #endif
-
- #if BT_LOG_OPTIMIZE_SIZE
- int n;
- n = snprintf(msg->p, nprintf_size(msg),
- _PP_MAP(_BT_LOG_MESSAGE_FORMAT_PRINTF_FMT, BT_LOG_MESSAGE_CTX_FORMAT)
- _PP_MAP(_BT_LOG_MESSAGE_FORMAT_PRINTF_VAL, BT_LOG_MESSAGE_CTX_FORMAT));
- put_nprintf(msg, n);
- #else
- char buf[64];
- char *const e = buf + sizeof(buf);
- char *p = e;
- _PP_RMAP(_BT_LOG_MESSAGE_FORMAT_PUT_R, BT_LOG_MESSAGE_CTX_FORMAT)
- msg->p = put_stringn(p, e, msg->p, msg->e);
- #endif
-#endif
-}
-
-#define PUT_TAG(msg, tag, prefix_delim, tag_delim) \
- do { \
- const char *ch; \
- msg->tag_b = msg->p; \
- if (0 != (ch = _bt_log_tag_prefix)) { \
- for (;msg->e != msg->p && 0 != (*msg->p = *ch); ++msg->p, ++ch) {} \
- } \
- if (0 != (ch = tag) && 0 != tag[0]) { \
- if (msg->tag_b != msg->p) { \
- PUT_CSTR_CHECKED(msg->p, msg->e, prefix_delim); \
- } \
- for (;msg->e != msg->p && 0 != (*msg->p = *ch); ++msg->p, ++ch) {} \
- } \
- msg->tag_e = msg->p; \
- if (msg->tag_b != msg->p) { \
- PUT_CSTR_CHECKED(msg->p, msg->e, tag_delim); \
- } \
- } _BT_LOG_ONCE
-
-/* Implements simple put statements for log message specification.
- */
-#define _BT_LOG_MESSAGE_FORMAT_PUT__
-#define _BT_LOG_MESSAGE_FORMAT_PUT__YEAR UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PUT__MONTH UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PUT__DAY UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PUT__HOUR UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PUT__MINUTE UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PUT__SECOND UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PUT__MILLISECOND UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PUT__PID UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PUT__TID UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PUT__LEVEL UNDEFINED
-#define _BT_LOG_MESSAGE_FORMAT_PUT__TAG(pd, td) PUT_TAG(msg, tag, pd, td);
-#define _BT_LOG_MESSAGE_FORMAT_PUT__FUNCTION msg->p = put_string(funcname(src->func), msg->p, msg->e);
-#define _BT_LOG_MESSAGE_FORMAT_PUT__FILENAME msg->p = put_string(filename(src->file), msg->p, msg->e);
-#define _BT_LOG_MESSAGE_FORMAT_PUT__FILELINE msg->p = put_uint(src->line, 0, '\0', msg->p, msg->e);
-#define _BT_LOG_MESSAGE_FORMAT_PUT__S(s) PUT_CSTR_CHECKED(msg->p, msg->e, s);
-#define _BT_LOG_MESSAGE_FORMAT_PUT__F_INIT(expr)
-#define _BT_LOG_MESSAGE_FORMAT_PUT__F_UINT(w, v) msg->p = put_uint(v, w, ' ', msg->p, msg->e);
-#define _BT_LOG_MESSAGE_FORMAT_PUT(field) \
- _PP_CONCAT_3(_BT_LOG_MESSAGE_FORMAT_PUT_, _, field)
-
-static void put_tag(bt_log_message *const msg, const char *const tag)
-{
- _PP_MAP(_BT_LOG_MESSAGE_FORMAT_INIT, BT_LOG_MESSAGE_TAG_FORMAT)
-
-/*
- * This generates a -Wundef warning. The issue was reported upstream:
- *
- * https://github.com/wonder-mice/zf_log/issues/40
- *
- * but there's not much we can do here, so just silence it.
- */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wundef"
-#if !_BT_LOG_MESSAGE_FORMAT_CONTAINS(TAG, BT_LOG_MESSAGE_TAG_FORMAT)
- VAR_UNUSED(tag);
-#endif
-#pragma GCC diagnostic pop
-
-#if !_BT_LOG_MESSAGE_FORMAT_FIELDS(BT_LOG_MESSAGE_TAG_FORMAT)
- VAR_UNUSED(msg);
-#else
- _PP_MAP(_BT_LOG_MESSAGE_FORMAT_PUT, BT_LOG_MESSAGE_TAG_FORMAT)
-#endif
-}
-
-static void put_src(bt_log_message *const msg, const src_location *const src)
-{
- _PP_MAP(_BT_LOG_MESSAGE_FORMAT_INIT, BT_LOG_MESSAGE_SRC_FORMAT)
-#if !_BT_LOG_MESSAGE_FORMAT_CONTAINS(FUNCTION, BT_LOG_MESSAGE_SRC_FORMAT) && \
- !_BT_LOG_MESSAGE_FORMAT_CONTAINS(FILENAME, BT_LOG_MESSAGE_SRC_FORMAT) && \
- !_BT_LOG_MESSAGE_FORMAT_CONTAINS(FILELINE, BT_LOG_MESSAGE_SRC_FORMAT)
- VAR_UNUSED(src);
-#endif
-#if !_BT_LOG_MESSAGE_FORMAT_FIELDS(BT_LOG_MESSAGE_SRC_FORMAT)
- VAR_UNUSED(msg);
-#else
- #if BT_LOG_OPTIMIZE_SIZE
- int n;
- n = snprintf(msg->p, nprintf_size(msg),
- _PP_MAP(_BT_LOG_MESSAGE_FORMAT_PRINTF_FMT, BT_LOG_MESSAGE_SRC_FORMAT)
- _PP_MAP(_BT_LOG_MESSAGE_FORMAT_PRINTF_VAL, BT_LOG_MESSAGE_SRC_FORMAT));
- put_nprintf(msg, n);
- #else
- _PP_MAP(_BT_LOG_MESSAGE_FORMAT_PUT, BT_LOG_MESSAGE_SRC_FORMAT)
- #endif
-#endif
-}
-
-static _BT_LOG_PRINTFLIKE(2, 0)
-void put_msg(bt_log_message *const msg,
- const char *const fmt, va_list va)
-{
- int n;
- msg->msg_b = msg->p;
- n = vsnprintf(msg->p, nprintf_size(msg), fmt, va);
- put_nprintf(msg, n);
-}
-
-static void output_mem(const bt_log_spec *log, bt_log_message *const msg,
- const mem_block *const mem)
-{
- if (0 == mem->d || 0 == mem->d_sz)
- {
- return;
- }
- const unsigned char *mem_p = (const unsigned char *)mem->d;
- const unsigned char *const mem_e = mem_p + mem->d_sz;
- const unsigned char *mem_cut;
- const ptrdiff_t mem_width = (ptrdiff_t)log->format->mem_width;
- char *const hex_b = msg->msg_b;
- char *const ascii_b = hex_b + 2 * mem_width + 2;
- char *const ascii_e = ascii_b + mem_width;
- if (msg->e < ascii_e)
- {
- return;
- }
- while (mem_p != mem_e)
- {
- char *hex = hex_b;
- char *ascii = ascii_b;
- for (mem_cut = mem_width < mem_e - mem_p? mem_p + mem_width: mem_e;
- mem_cut != mem_p; ++mem_p)
- {
- const unsigned char ch = *mem_p;
- *hex++ = c_hex[(0xf0 & ch) >> 4];
- *hex++ = c_hex[(0x0f & ch)];
- *ascii++ = isprint(ch)? (char)ch: '?';
- }
- while (hex != ascii_b)
- {
- *hex++ = ' ';
- }
- msg->p = ascii;
- log->output->callback(msg, log->output->arg);
- }
-}
-
-void bt_log_set_tag_prefix(const char *const prefix)
-{
- _bt_log_tag_prefix = prefix;
-}
-
-void bt_log_set_mem_width(const unsigned w)
-{
- _bt_log_global_format.mem_width = w;
-}
-
-void bt_log_set_output_level(const int lvl)
-{
- _bt_log_global_output_lvl = lvl;
-}
-
-void bt_log_set_output_v(const unsigned mask, void *const arg,
- const bt_log_output_cb callback)
-{
- _bt_log_global_output.mask = mask;
- _bt_log_global_output.arg = arg;
- _bt_log_global_output.callback = callback;
-}
-
-static _BT_LOG_PRINTFLIKE(6, 0)
-void _bt_log_write_imp(
- const bt_log_spec *log,
- const src_location *const src, const mem_block *const mem,
- const int lvl, const char *const tag, const char *const fmt, va_list va)
-{
- bt_log_message msg;
- char *buf = logging_buf;
- const unsigned mask = log->output->mask;
- msg.lvl = lvl;
- msg.tag = tag;
- g_buffer_cb(&msg, buf);
- const char *rst_color_p = bt_common_color_reset();
- const char *rst_color_e = rst_color_p + strlen(rst_color_p);
- const char *color_p = "";
- const char *color_e = color_p;
-
- switch (lvl) {
- case BT_LOG_INFO:
- color_p = bt_common_color_fg_blue();
- color_e = color_p + strlen(color_p);
- break;
- case BT_LOG_WARNING:
- color_p = bt_common_color_fg_yellow();
- color_e = color_p + strlen(color_p);
- break;
- case BT_LOG_ERROR:
- case BT_LOG_FATAL:
- color_p = bt_common_color_fg_red();
- color_e = color_p + strlen(color_p);
- break;
- default:
- break;
- }
-
- msg.p = put_stringn(color_p, color_e, msg.p, msg.e);
-
- if (BT_LOG_PUT_CTX & mask)
- {
- put_ctx(&msg);
- }
- if (BT_LOG_PUT_TAG & mask)
- {
- put_tag(&msg, tag);
- }
- if (0 != src && BT_LOG_PUT_SRC & mask)
- {
- put_src(&msg, src);
- }
- if (BT_LOG_PUT_MSG & mask)
- {
- put_msg(&msg, fmt, va);
- }
- msg.p = put_stringn(rst_color_p, rst_color_e, msg.p, msg.e);
- log->output->callback(&msg, log->output->arg);
- if (0 != mem && BT_LOG_PUT_MSG & mask)
- {
- output_mem(log, &msg, mem);
- }
-}
-
-void _bt_log_write_d(
- const char *const func, const char *const file, const unsigned line,
- const int lvl, const char *const tag,
- const char *const fmt, ...)
-{
- const src_location src = {func, file, line};
- va_list va;
- va_start(va, fmt);
- _bt_log_write_imp(&global_spec, &src, 0, lvl, tag, fmt, va);
- va_end(va);
-}
-
-void _bt_log_write_aux_d(
- const char *const func, const char *const file, const unsigned line,
- const bt_log_spec *const log, const int lvl, const char *const tag,
- const char *const fmt, ...)
-{
- const src_location src = {func, file, line};
- va_list va;
- va_start(va, fmt);
- _bt_log_write_imp(log, &src, 0, lvl, tag, fmt, va);
- va_end(va);
-}
-
-void _bt_log_write(const int lvl, const char *const tag,
- const char *const fmt, ...)
-{
- va_list va;
- va_start(va, fmt);
- _bt_log_write_imp(&global_spec, 0, 0, lvl, tag, fmt, va);
- va_end(va);
-}
-
-void _bt_log_write_aux(
- const bt_log_spec *const log, const int lvl, const char *const tag,
- const char *const fmt, ...)
-{
- va_list va;
- va_start(va, fmt);
- _bt_log_write_imp(log, 0, 0, lvl, tag, fmt, va);
- va_end(va);
-}
-
-void _bt_log_write_mem_d(
- const char *const func, const char *const file, const unsigned line,
- const int lvl, const char *const tag,
- const void *const d, const unsigned d_sz,
- const char *const fmt, ...)
-{
- const src_location src = {func, file, line};
- const mem_block mem = {d, d_sz};
- va_list va;
- va_start(va, fmt);
- _bt_log_write_imp(&global_spec, &src, &mem, lvl, tag, fmt, va);
- va_end(va);
-}
-
-void _bt_log_write_mem_aux_d(
- const char *const func, const char *const file, const unsigned line,
- const bt_log_spec *const log, const int lvl, const char *const tag,
- const void *const d, const unsigned d_sz,
- const char *const fmt, ...)
-{
- const src_location src = {func, file, line};
- const mem_block mem = {d, d_sz};
- va_list va;
- va_start(va, fmt);
- _bt_log_write_imp(log, &src, &mem, lvl, tag, fmt, va);
- va_end(va);
-}
-
-void _bt_log_write_mem(const int lvl, const char *const tag,
- const void *const d, const unsigned d_sz,
- const char *const fmt, ...)
-{
- const mem_block mem = {d, d_sz};
- va_list va;
- va_start(va, fmt);
- _bt_log_write_imp(&global_spec, 0, &mem, lvl, tag, fmt, va);
- va_end(va);
-}
-
-void _bt_log_write_mem_aux(
- const bt_log_spec *const log, const int lvl, const char *const tag,
- const void *const d, const unsigned d_sz,
- const char *const fmt, ...)
-{
- const mem_block mem = {d, d_sz};
- va_list va;
- va_start(va, fmt);
- _bt_log_write_imp(log, 0, &mem, lvl, tag, fmt, va);
- va_end(va);
-}
* SPDX-License-Identifier: MIT
*
* Copyright (c) 2016 wonder-mice
+ * Copyright (c) 2016-2023 Philippe Proulx <pproulx@efficios.com>
*
- * This is zf_log.h, modified with Babeltrace prefixes.
- * See <https://github.com/wonder-mice/zf_log/>.
+ * This is very inspired by zf_log.h (see
+ * <https://github.com/wonder-mice/zf_log/>), but modified (mostly
+ * stripped down) for the use cases of Babeltrace.
*/
-#pragma once
-
-#ifndef BABELTRACE_LOGGING_INTERNAL_H
-#define BABELTRACE_LOGGING_INTERNAL_H
+#ifndef BABELTRACE_LOGGING_LOG_H
+#define BABELTRACE_LOGGING_LOG_H
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <glib.h>
#include <babeltrace2/babeltrace.h>
-/* Access private __BT_LOGGING_LEVEL_* macros. */
-#define __BT_IN_BABELTRACE_H
-#include <babeltrace2/logging-defs.h>
-#undef __BT_IN_BABELTRACE_H
-
-#include "common/macros.h"
-#include "common/assert.h"
-
-/* To detect incompatible changes you can define BT_LOG_VERSION_REQUIRED to be
- * the current value of BT_LOG_VERSION before including this file (or via
- * compiler command line):
- *
- * #define BT_LOG_VERSION_REQUIRED 4
- * #include "logging.h"
- *
- * Compilation will fail when included file has different version.
- */
-#define BT_LOG_VERSION 4
-#if defined(BT_LOG_VERSION_REQUIRED)
- #if BT_LOG_VERSION_REQUIRED != BT_LOG_VERSION
- #error different bt_log version required
- #endif
-#endif
-
-/* Log level guideline:
- * - BT_LOG_FATAL - happened something impossible and absolutely unexpected.
- * Process can't continue and must be terminated.
- * Example: division by zero, unexpected modifications from other thread.
- * - BT_LOG_ERROR - happened something possible, but highly unexpected. The
- * process is able to recover and continue execution.
- * Example: out of memory (could also be FATAL if not handled properly).
- * - BT_LOG_WARNING - happened something that *usually* should not happen and
- * significantly changes application behavior for some period of time.
- * Example: configuration file not found, auth error.
- * - BT_LOG_INFO - happened significant life cycle event or major state
- * transition.
- * Example: app started, user logged in.
- * - BT_LOG_DEBUG - minimal set of events that could help to reconstruct the
- * execution path. Usually disabled in release builds.
- * - BT_LOG_TRACE - all other events. Usually disabled in release builds.
- *
- * *Ideally*, log file of debugged, well tested, production ready application
- * should be empty or very small. Choosing a right log level is as important as
- * providing short and self descriptive log message.
- */
-#define BT_LOG_TRACE __BT_LOGGING_LEVEL_TRACE
-#define BT_LOG_DEBUG __BT_LOGGING_LEVEL_DEBUG
-#define BT_LOG_INFO __BT_LOGGING_LEVEL_INFO
-#define BT_LOG_WARNING __BT_LOGGING_LEVEL_WARNING
-#define BT_LOG_ERROR __BT_LOGGING_LEVEL_ERROR
-#define BT_LOG_FATAL __BT_LOGGING_LEVEL_FATAL
-#define BT_LOG_NONE __BT_LOGGING_LEVEL_NONE
-
-/* "Current" log level is a compile time check and has no runtime overhead. Log
- * level that is below current log level it said to be "disabled".
- * Otherwise, it's "enabled". Log messages that are disabled has no
- * runtime overhead - they are converted to no-op by preprocessor and
- * then eliminated by compiler. Current log level is configured per
- * compilation module (.c/.cpp/.m file) by defining BT_LOG_DEF_LEVEL or
- * BT_MINIMAL_LOG_LEVEL. BT_MINIMAL_LOG_LEVEL has higer priority and
- * when defined overrides value provided by BT_LOG_DEF_LEVEL.
- *
- * Common practice is to define default current log level with BT_LOG_DEF_LEVEL
- * in build script (e.g. Makefile, CMakeLists.txt, gyp, etc.) for the entire
- * project or target:
- *
- * CC_ARGS := -DBT_LOG_DEF_LEVEL=BT_LOG_INFO
- *
- * And when necessary to override it with BT_MINIMAL_LOG_LEVEL in .c/.cpp/.m files
- * before including bt_log.h:
- *
- * #define BT_MINIMAL_LOG_LEVEL BT_LOG_TRACE
- * #include "logging.h"
- *
- * If both BT_LOG_DEF_LEVEL and BT_MINIMAL_LOG_LEVEL are undefined, then
- * BT_LOG_INFO will be used for release builds (BT_DEBUG_MODE is NOT
- * defined) and BT_LOG_DEBUG otherwise (BT_DEBUG_MODE is defined).
- */
-#if defined(BT_MINIMAL_LOG_LEVEL)
- #define _BT_MINIMAL_LOG_LEVEL BT_MINIMAL_LOG_LEVEL
-#elif defined(BT_LOG_DEF_LEVEL)
- #define _BT_MINIMAL_LOG_LEVEL BT_LOG_DEF_LEVEL
-#else
- #ifdef BT_DEBUG_MODE
- #define _BT_MINIMAL_LOG_LEVEL BT_LOG_DEBUG
- #else
- #define _BT_MINIMAL_LOG_LEVEL BT_LOG_INFO
- #endif
-#endif
+#include "log-api.h"
-/* "Output" log level is a runtime check. When log level is below output log
- * level it said to be "turned off" (or just "off" for short). Otherwise
- * it's "turned on" (or just "on"). Log levels that were "disabled" (see
- * BT_MINIMAL_LOG_LEVEL and BT_LOG_DEF_LEVEL) can't be "turned on", but
- * "enabled" log levels could be "turned off". Only messages with log
- * level which is "turned on" will reach output facility. All other
- * messages will be ignored (and their arguments will not be evaluated).
- * Output log level is a global property and configured per process
- * using bt_log_set_output_level() function which can be called at any
- * time.
+/*
+ * `BT_LOG_OUTPUT_LEVEL` (expression having the type `int`, optional):
+ * valid expression evaluating to the current (run-time) log level.
*
- * Though in some cases it could be useful to configure output log level per
- * compilation module or per library. There are two ways to achieve that:
- * - Define BT_LOG_OUTPUT_LEVEL to expresion that evaluates to desired output
- * log level.
- * - Copy bt_log.h and bt_log.c files into your library and build it with
- * BT_LOG_LIBRARY_PREFIX defined to library specific prefix. See
- * BT_LOG_LIBRARY_PREFIX for more details.
+ * This is configured per translation unit.
*
- * When defined, BT_LOG_OUTPUT_LEVEL must evaluate to integral value
- * that corresponds to desired output log level. Use it only when
- * compilation module is required to have output log level which is
- * different from global output log level set by
- * bt_log_set_output_level() function. For other cases, consider
- * defining BT_MINIMAL_LOG_LEVEL or using bt_log_set_output_level()
- * function.
+ * Note that BT_LOG*() statements will evaluate this expression each
+ * time if their level is equally or less verbose than
+ * `BT_LOG_MINIMAL_LEVEL`. Keep this expression as simple as possible,
+ * otherwise it will not only add run-time overhead, but also will
+ * increase the size of call sites (which will result in larger
+ * executable).
*
* Example:
*
- * #define BT_LOG_OUTPUT_LEVEL g_module_log_level
- * #include "logging.h"
- * static int g_module_log_level = BT_LOG_INFO;
- * static void foo() {
- * BT_LOGI("Will check g_module_log_level for output log level");
- * }
- * void debug_log(bool on) {
- * g_module_log_level = on? BT_LOG_DEBUG: BT_LOG_INFO;
- * }
- *
- * Note on performance. This expression will be evaluated each time
- * message is logged (except when message log level is "disabled" - see
- * BT_MINIMAL_LOG_LEVEL for details). Keep this expression as simple as
- * possible, otherwise it will not only add runtime overhead, but also
- * will increase size of call site (which will result in larger
- * executable). The prefered way is to use integer variable (as in
- * example above). If structure must be used, log_level field must be
- * the first field in this structure:
+ * #define BT_LOG_OUTPUT_LEVEL log_level
+ * #include "logging/log.h"
*
- * #define BT_LOG_OUTPUT_LEVEL (g_config.log_level)
- * #include "logging.h"
- * struct config {
- * int log_level;
- * unsigned other_field;
- * [...]
- * };
- * static config g_config = {BT_LOG_INFO, 0, ...};
- *
- * This allows compiler to generate more compact load instruction (no need to
- * specify offset since it's zero). Calling a function to get output log level
- * is generaly a bad idea, since it will increase call site size and runtime
- * overhead even further.
+ * If missing, you may only use logging macros having a `_cur_lvl`
+ * parameter.
*/
-#if defined(BT_LOG_OUTPUT_LEVEL)
- #define _BT_LOG_OUTPUT_LEVEL BT_LOG_OUTPUT_LEVEL
-#endif
-
-/* "Tag" is a compound string that could be associated with a log message. It
- * consists of tag prefix and tag (both are optional).
- *
- * Tag prefix is a global property and configured per process using
- * bt_log_set_tag_prefix() function. Tag prefix identifies context in which
- * component or module is running (e.g. process name). For example, the same
- * library could be used in both client and server processes that work on the
- * same machine. Tag prefix could be used to easily distinguish between them.
- * For more details about tag prefix see bt_log_set_tag_prefix() function. Tag
- * prefix
- *
- * Tag identifies component or module. It is configured per compilation module
- * (.c/.cpp/.m file) by defining BT_LOG_TAG or BT_LOG_DEF_TAG. BT_LOG_TAG has
- * higer priority and when defined overrides value provided by BT_LOG_DEF_TAG.
- * When defined, value must evaluate to (const char *), so for strings double
- * quotes must be used.
- *
- * Default tag could be defined with BT_LOG_DEF_TAG in build script (e.g.
- * Makefile, CMakeLists.txt, gyp, etc.) for the entire project or target:
- *
- * CC_ARGS := -DBT_LOG_DEF_TAG=\"MISC\"
- *
- * And when necessary could be overriden with BT_LOG_TAG in .c/.cpp/.m files
- * before including bt_log.h:
- *
- * #define BT_LOG_TAG "MAIN"
- * #include "logging.h"
- *
- * If both BT_LOG_DEF_TAG and BT_LOG_TAG are undefined no tag will be added to
- * the log message (tag prefix still could be added though).
- *
- * Output example:
- *
- * 04-29 22:43:20.244 40059 1299 I hello.MAIN Number of arguments: 1
- * | |
- * | +- tag (e.g. module)
- * +- tag prefix (e.g. process name)
- */
-#if defined(BT_LOG_TAG)
- #define _BT_LOG_TAG BT_LOG_TAG
-#elif defined(BT_LOG_DEF_TAG)
- #define _BT_LOG_TAG BT_LOG_DEF_TAG
-#else
- #define _BT_LOG_TAG 0
-#endif
-
-/* Source location is part of a log line that describes location (function or
- * method name, file name and line number, e.g. "runloop@main.cpp:68") of a
- * log statement that produced it.
- * Source location formats are:
- * - BT_LOG_SRCLOC_NONE - don't add source location to log line.
- * - BT_LOG_SRCLOC_SHORT - add source location in short form (file and line
- * number, e.g. "@main.cpp:68").
- * - BT_LOG_SRCLOC_LONG - add source location in long form (function or method
- * name, file and line number, e.g. "runloop@main.cpp:68").
- */
-#define BT_LOG_SRCLOC_NONE 0
-#define BT_LOG_SRCLOC_SHORT 1
-#define BT_LOG_SRCLOC_LONG 2
-
-#define _BT_LOG_SRCLOC BT_LOG_SRCLOC_LONG
-
-#if BT_LOG_SRCLOC_LONG == _BT_LOG_SRCLOC
- #define _BT_LOG_SRCLOC_FUNCTION _BT_LOG_FUNCTION
+#ifdef BT_LOG_OUTPUT_LEVEL
+# define _BT_LOG_OUTPUT_LEVEL BT_LOG_OUTPUT_LEVEL
#else
- #define _BT_LOG_SRCLOC_FUNCTION 0
+# define _BT_LOG_OUTPUT_LEVEL "Please define `BT_LOG_OUTPUT_LEVEL`"
#endif
-/* Censoring provides conditional logging of secret information, also known as
- * Personally Identifiable Information (PII) or Sensitive Personal Information
- * (SPI). Censoring can be either enabled (BT_LOG_CENSORED) or disabled
- * (BT_LOG_UNCENSORED). When censoring is enabled, log statements marked as
- * "secrets" will be ignored and will have zero overhead (arguments also will
- * not be evaluated).
- */
-#define BT_LOG_CENSORED 1
-#define BT_LOG_UNCENSORED 0
-
-/* Censoring is configured per compilation module (.c/.cpp/.m file) by defining
- * BT_LOG_DEF_CENSORING or BT_LOG_CENSORING. BT_LOG_CENSORING has higer priority
- * and when defined overrides value provided by BT_LOG_DEF_CENSORING.
- *
- * Common practice is to define default censoring with BT_LOG_DEF_CENSORING in
- * build script (e.g. Makefile, CMakeLists.txt, gyp, etc.) for the entire
- * project or target:
- *
- * CC_ARGS := -DBT_LOG_DEF_CENSORING=BT_LOG_CENSORED
- *
- * And when necessary to override it with BT_LOG_CENSORING in .c/.cpp/.m files
- * before including bt_log.h (consider doing it only for debug purposes and be
- * very careful not to push such temporary changes to source control):
- *
- * #define BT_LOG_CENSORING BT_LOG_UNCENSORED
- * #include "logging.h"
- *
- * If both BT_LOG_DEF_CENSORING and BT_LOG_CENSORING are undefined, then
- * BT_LOG_CENSORED will be used for release builds (BT_DEBUG_MODE is NOT
- * defined) and BT_LOG_UNCENSORED otherwise (BT_DEBUG_MODE is defined).
- */
-#if defined(BT_LOG_CENSORING)
- #define _BT_LOG_CENSORING BT_LOG_CENSORING
-#elif defined(BT_LOG_DEF_CENSORING)
- #define _BT_LOG_CENSORING BT_LOG_DEF_CENSORING
-#else
- #ifdef BT_DEBUG_MODE
- #define _BT_LOG_CENSORING BT_LOG_UNCENSORED
- #else
- #define _BT_LOG_CENSORING BT_LOG_CENSORED
- #endif
-#endif
-
-/* Check censoring at compile time. Evaluates to true when censoring is disabled
- * (i.e. when secrets will be logged). For example:
- *
- * #if BT_LOG_SECRETS
- * char ssn[16];
- * getSocialSecurityNumber(ssn);
- * BT_LOGI("Customer ssn: %s", ssn);
- * #endif
- *
- * See BT_LOG_SECRET() macro for a more convenient way of guarding single log
- * statement.
- */
-#define BT_LOG_SECRETS (BT_LOG_UNCENSORED == _BT_LOG_CENSORING)
-
-/* Static (compile-time) initialization support allows to configure logging
- * before entering main() function. This mostly useful in C++ where functions
- * and methods could be called during initialization of global objects. Those
- * functions and methods could record log messages too and for that reason
- * static initialization of logging configuration is customizable.
- *
- * Macros below allow to specify values to use for initial configuration:
- * - BT_LOG_EXTERN_TAG_PREFIX - tag prefix (default: none)
- * - BT_LOG_EXTERN_GLOBAL_FORMAT - global format options (default: see
- * BT_LOG_MEM_WIDTH in bt_log.c)
- * - BT_LOG_EXTERN_GLOBAL_OUTPUT - global output facility (default: stderr or
- * platform specific, see BT_LOG_USE_XXX macros in bt_log.c)
- * - BT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL - global output log level (default: 0 -
- * all levals are "turned on")
- *
- * For example, in log_config.c:
- *
- * #include "logging.h"
- * BT_LOG_DEFINE_TAG_PREFIX = "MyApp";
- * BT_LOG_DEFINE_GLOBAL_FORMAT = {CUSTOM_MEM_WIDTH};
- * BT_LOG_DEFINE_GLOBAL_OUTPUT = {BT_LOG_PUT_STD, custom_output_callback, 0};
- * BT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL = BT_LOG_INFO;
- *
- * However, to use any of those macros bt_log library must be compiled with
- * following macros defined:
- * - to use BT_LOG_DEFINE_TAG_PREFIX define BT_LOG_EXTERN_TAG_PREFIX
- * - to use BT_LOG_DEFINE_GLOBAL_FORMAT define BT_LOG_EXTERN_GLOBAL_FORMAT
- * - to use BT_LOG_DEFINE_GLOBAL_OUTPUT define BT_LOG_EXTERN_GLOBAL_OUTPUT
- * - to use BT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL define
- * BT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL
- *
- * When bt_log library compiled with one of BT_LOG_EXTERN_XXX macros defined,
- * corresponding BT_LOG_DEFINE_XXX macro MUST be used exactly once somewhere.
- * Otherwise build will fail with link error (undefined symbol).
- */
-#define BT_LOG_DEFINE_TAG_PREFIX const char *_bt_log_tag_prefix
-#define BT_LOG_DEFINE_GLOBAL_FORMAT bt_log_format _bt_log_global_format
-#define BT_LOG_DEFINE_GLOBAL_OUTPUT bt_log_output _bt_log_global_output
-#define BT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL int _bt_log_global_output_lvl
-
-/* Pointer to global format options. Direct modification is not allowed. Use
- * bt_log_set_mem_width() instead. Could be used to initialize bt_log_spec
- * structure:
- *
- * const bt_log_output g_output = {BT_LOG_PUT_STD, output_callback, 0};
- * const bt_log_spec g_spec = {BT_LOG_GLOBAL_FORMAT, &g_output};
- * BT_LOGI_AUX(&g_spec, "Hello");
- */
-#define BT_LOG_GLOBAL_FORMAT ((const bt_log_format *)&_bt_log_global_format)
-
-/* Pointer to global output variable. Direct modification is not allowed. Use
- * bt_log_set_output_v() or bt_log_set_output_p() instead. Could be used to
- * initialize bt_log_spec structure:
- *
- * const bt_log_format g_format = {40};
- * const bt_log_spec g_spec = {g_format, BT_LOG_GLOBAL_OUTPUT};
- * BT_LOGI_AUX(&g_spec, "Hello");
- */
-#define BT_LOG_GLOBAL_OUTPUT ((const bt_log_output *)&_bt_log_global_output)
-
-/* When defined, all library symbols produced by linker will be prefixed with
- * provided value. That allows to use bt_log library privately in another
- * libraries without exposing bt_log symbols in their original form (to avoid
- * possible conflicts with other libraries / components that also could use
- * bt_log for logging). Value must be without quotes, for example:
- *
- * CC_ARGS := -DBT_LOG_LIBRARY_PREFIX=my_lib_
- *
- * Note, that in this mode BT_LOG_LIBRARY_PREFIX must be defined when building
- * bt_log library AND it also must be defined to the same value when building
- * a library that uses it. For example, consider fictional KittyHttp library
- * that wants to use bt_log for logging. First approach that could be taken is
- * to add bt_log.h and bt_log.c to the KittyHttp's source code tree directly.
- * In that case it will be enough just to define BT_LOG_LIBRARY_PREFIX in
- * KittyHttp's build script:
- *
- * // KittyHttp/CMakeLists.txt
- * target_compile_definitions(KittyHttp PRIVATE
- * "BT_LOG_LIBRARY_PREFIX=KittyHttp_")
+/*
+ * `BT_LOG_TAG` (expression having the type `const char *`, optional):
+ * component or module identifier.
*
- * If KittyHttp doesn't want to include bt_log source code in its source tree
- * and wants to build bt_log as a separate library than bt_log library must be
- * built with BT_LOG_LIBRARY_PREFIX defined to KittyHttp_ AND KittyHttp library
- * itself also needs to define BT_LOG_LIBRARY_PREFIX to KittyHttp_. It can do
- * so either in its build script, as in example above, or by providing a
- * wrapper header that KittyHttp library will need to use instead of bt_log.h:
+ * This is configured per translation unit.
*
- * // KittyHttpLogging.h
- * #define BT_LOG_LIBRARY_PREFIX KittyHttp_
- * #include "logging.h"
+ * Example:
*
- * Regardless of the method chosen, the end result is that bt_log symbols will
- * be prefixed with "KittyHttp_", so if a user of KittyHttp (say DogeBrowser)
- * also uses bt_log for logging, they will not interferer with each other. Both
- * will have their own log level, output facility, format options etc.
+ * // ...
+ * #define BT_LOG_TAG "MY.MODULE"
+ * #include "logging/log.h"
*/
-#ifdef BT_LOG_LIBRARY_PREFIX
- #define _BT_LOG_DECOR__(prefix, name) prefix ## name
- #define _BT_LOG_DECOR_(prefix, name) _BT_LOG_DECOR__(prefix, name)
- #define _BT_LOG_DECOR(name) _BT_LOG_DECOR_(BT_LOG_LIBRARY_PREFIX, name)
-
- #define bt_log_set_tag_prefix _BT_LOG_DECOR(bt_log_set_tag_prefix)
- #define bt_log_set_mem_width _BT_LOG_DECOR(bt_log_set_mem_width)
- #define bt_log_set_output_level _BT_LOG_DECOR(bt_log_set_output_level)
- #define bt_log_set_output_v _BT_LOG_DECOR(bt_log_set_output_v)
- #define bt_log_set_output_p _BT_LOG_DECOR(bt_log_set_output_p)
- #define bt_log_out_stderr_callback _BT_LOG_DECOR(bt_log_out_stderr_callback)
- #define _bt_log_tag_prefix _BT_LOG_DECOR(_bt_log_tag_prefix)
- #define _bt_log_global_format _BT_LOG_DECOR(_bt_log_global_format)
- #define _bt_log_global_output _BT_LOG_DECOR(_bt_log_global_output)
- #define _bt_log_global_output_lvl _BT_LOG_DECOR(_bt_log_global_output_lvl)
- #define _bt_log_write_d _BT_LOG_DECOR(_bt_log_write_d)
- #define _bt_log_write_aux_d _BT_LOG_DECOR(_bt_log_write_aux_d)
- #define _bt_log_write _BT_LOG_DECOR(_bt_log_write)
- #define _bt_log_write_aux _BT_LOG_DECOR(_bt_log_write_aux)
- #define _bt_log_write_mem_d _BT_LOG_DECOR(_bt_log_write_mem_d)
- #define _bt_log_write_mem_aux_d _BT_LOG_DECOR(_bt_log_write_mem_aux_d)
- #define _bt_log_write_mem _BT_LOG_DECOR(_bt_log_write_mem)
- #define _bt_log_write_mem_aux _BT_LOG_DECOR(_bt_log_write_mem_aux)
- #define _bt_log_stderr_spec _BT_LOG_DECOR(_bt_log_stderr_spec)
-#endif
-
-#if defined(__printflike)
- #define _BT_LOG_PRINTFLIKE(str_index, first_to_check) \
- __printflike(str_index, first_to_check)
-#elif defined(__MINGW_PRINTF_FORMAT)
- #define _BT_LOG_PRINTFLIKE(str_index, first_to_check) \
- __attribute__((format(__MINGW_PRINTF_FORMAT, str_index, first_to_check)))
-#elif defined(__GNUC__)
- #define _BT_LOG_PRINTFLIKE(str_index, first_to_check) \
- __attribute__((format(__printf__, str_index, first_to_check)))
-#else
- #define _BT_LOG_PRINTFLIKE(str_index, first_to_check)
-#endif
-
-#if (defined(_WIN32) || defined(_WIN64)) && !defined(__GNUC__)
- #define _BT_LOG_FUNCTION __FUNCTION__
-#else
- #define _BT_LOG_FUNCTION __func__
-#endif
-
-#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
- #define _BT_LOG_INLINE __inline
- #define _BT_LOG_IF(cond) \
- __pragma(warning(push)) \
- __pragma(warning(disable:4127)) \
- if(cond) \
- __pragma(warning(pop))
- #define _BT_LOG_WHILE(cond) \
- __pragma(warning(push)) \
- __pragma(warning(disable:4127)) \
- while(cond) \
- __pragma(warning(pop))
+#ifdef BT_LOG_TAG
+# define _BT_LOG_TAG BT_LOG_TAG
#else
- #define _BT_LOG_INLINE inline
- #define _BT_LOG_IF(cond) if(cond)
- #define _BT_LOG_WHILE(cond) while(cond)
+# define _BT_LOG_TAG NULL
#endif
-#define _BT_LOG_NEVER _BT_LOG_IF(0)
-#define _BT_LOG_ONCE _BT_LOG_WHILE(0)
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Set tag prefix. Prefix will be separated from the tag with dot ('.').
- * Use 0 or empty string to disable (default). Common use is to set it to
- * the process (or build target) name (e.g. to separate client and server
- * processes). Function will NOT copy provided prefix string, but will store the
- * pointer. Hence specified prefix string must remain valid. See
- * BT_LOG_DEFINE_TAG_PREFIX for a way to set it before entering main() function.
- * See BT_LOG_TAG for more information about tag and tag prefix.
- */
-void bt_log_set_tag_prefix(const char *const prefix);
-
-/* Set number of bytes per log line in memory (ASCII-HEX) output. Example:
- *
- * I hello.MAIN 4c6f72656d20697073756d20646f6c6f Lorem ipsum dolo
- * |<- w bytes ->| |<- w chars ->|
- *
- * See BT_LOGF_MEM and BT_LOGF_MEM_AUX for more details.
+/*
+ * BT_LOG_ON_CUR_LVL() using `BT_LOG_OUTPUT_LEVEL` as the current
+ * (run-time) level.
*/
-void bt_log_set_mem_width(const unsigned w);
+#define BT_LOG_ON(_lvl) BT_LOG_ON_CUR_LVL(_lvl, _BT_LOG_OUTPUT_LEVEL)
+#define BT_LOG_ON_TRACE BT_LOG_ON(BT_LOG_TRACE)
+#define BT_LOG_ON_DEBUG BT_LOG_ON(BT_LOG_DEBUG)
+#define BT_LOG_ON_INFO BT_LOG_ON(BT_LOG_INFO)
+#define BT_LOG_ON_WARNING BT_LOG_ON(BT_LOG_WARNING)
+#define BT_LOG_ON_ERROR BT_LOG_ON(BT_LOG_ERROR)
+#define BT_LOG_ON_FATAL BT_LOG_ON(BT_LOG_FATAL)
-/* Set "output" log level. See BT_MINIMAL_LOG_LEVEL and BT_LOG_OUTPUT_LEVEL for more
- * info about log levels.
+/*
+ * BT_LOG_WRITE_CUR_LVL() using `BT_LOG_OUTPUT_LEVEL` as the current
+ * (run-time) level.
*/
-void bt_log_set_output_level(const int lvl);
+#define BT_LOG_WRITE(_lvl, _tag, _msg) \
+ BT_LOG_WRITE_CUR_LVL((_lvl), _BT_LOG_OUTPUT_LEVEL, (_tag), (_msg))
-/* Put mask is a set of flags that define what fields will be added to each
- * log message. Default value is BT_LOG_PUT_STD and other flags could be used to
- * alter its behavior. See bt_log_set_output_v() for more details.
- *
- * Note about BT_LOG_PUT_SRC: it will be added only in debug builds
- * (BT_DEBUG_MODE is defined).
+/*
+ * BT_LOG_WRITE_PRINTF_CUR_LVL() using `BT_LOG_OUTPUT_LEVEL` as the
+ * current (run-time) level.
*/
-enum
-{
- BT_LOG_PUT_CTX = 1 << 0, /* context (time, pid, tid, log level) */
- BT_LOG_PUT_TAG = 1 << 1, /* tag (including tag prefix) */
- BT_LOG_PUT_SRC = 1 << 2, /* source location (file, line, function) */
- BT_LOG_PUT_MSG = 1 << 3, /* message text (formatted string) */
- BT_LOG_PUT_STD = 0xffff, /* everything (default) */
-};
-
-typedef struct bt_log_message
-{
- int lvl; /* Log level of the message */
- const char *tag; /* Associated tag (without tag prefix) */
- char *buf; /* Buffer start */
- char *e; /* Buffer end (last position where EOL with 0 could be written) */
- char *p; /* Buffer content end (append position) */
- char *tag_b; /* Prefixed tag start */
- char *tag_e; /* Prefixed tag end (if != tag_b, points to msg separator) */
- char *msg_b; /* Message start (expanded format string) */
-}
-bt_log_message;
+#define BT_LOG_WRITE_PRINTF(_lvl, _tag, _fmt, ...) \
+ BT_LOG_WRITE_PRINTF_CUR_LVL((_lvl), _BT_LOG_OUTPUT_LEVEL, \
+ (_tag), (_fmt), ##__VA_ARGS__)
-/* Type of output callback function. It will be called for each log line allowed
- * by both "current" and "output" log levels ("enabled" and "turned on").
- * Callback function is allowed to modify content of the buffers pointed by the
- * msg, but it's not allowed to modify any of msg fields. Buffer pointed by msg
- * is UTF-8 encoded (no BOM mark).
+/*
+ * BT_LOG_WRITE_MEM_CUR_LVL() using `BT_LOG_OUTPUT_LEVEL` as the current
+ * (run-time) level.
*/
-typedef void (*bt_log_output_cb)(const bt_log_message *msg, void *arg);
+#define BT_LOG_WRITE_MEM(_lvl, _tag, _mem_data, _mem_len, _msg) \
+ BT_LOG_WRITE_MEM_CUR_LVL((_lvl), _BT_LOG_OUTPUT_LEVEL, (_tag), \
+ (_mem_data), (_mem_len), (_msg))
-/* Format options. For more details see bt_log_set_mem_width().
+/*
+ * BT_LOG_WRITE_MEM_PRINTF_CUR_LVL() using `BT_LOG_OUTPUT_LEVEL` as the
+ * current (run-time) level.
*/
-typedef struct bt_log_format
-{
- unsigned mem_width; /* Bytes per line in memory (ASCII-HEX) dump */
-}
-bt_log_format;
+#define BT_LOG_WRITE_MEM_PRINTF(_lvl, _tag, _mem_data, _mem_len, _fmt, ...) \
+ BT_LOG_WRITE_MEM_PRINTF_CUR_LVL((_lvl), _BT_LOG_OUTPUT_LEVEL, \
+ (_tag), (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__)
-/* Output facility.
+/*
+ * BT_LOG_WRITE_ERRNO_CUR_LVL() using `BT_LOG_OUTPUT_LEVEL` as the
+ * current (run-time) level.
*/
-typedef struct bt_log_output
-{
- unsigned mask; /* What to put into log line buffer (see BT_LOG_PUT_XXX) */
- void *arg; /* User provided output callback argument */
- bt_log_output_cb callback; /* Output callback function */
-}
-bt_log_output;
+#define BT_LOG_WRITE_ERRNO(_lvl, _tag, _init_msg, _msg) \
+ BT_LOG_WRITE_ERRNO_CUR_LVL((_lvl), _BT_LOG_OUTPUT_LEVEL, \
+ (_tag), (_init_msg), (_msg))
-/* Set output callback function.
- *
- * Mask allows to control what information will be added to the log line buffer
- * before callback function is invoked. Default mask value is BT_LOG_PUT_STD.
+/*
+ * BT_LOG_WRITE_ERRNO_PRINTF_CUR_LVL() using `BT_LOG_OUTPUT_LEVEL` as
+ * the current (run-time) level.
*/
-void bt_log_set_output_v(const unsigned mask, void *const arg,
- const bt_log_output_cb callback);
-static _BT_LOG_INLINE void bt_log_set_output_p(const bt_log_output *const output)
-{
- bt_log_set_output_v(output->mask, output->arg, output->callback);
-}
+#define BT_LOG_WRITE_ERRNO_PRINTF(_lvl, _tag, _init_msg, _fmt, ...) \
+ BT_LOG_WRITE_ERRNO_PRINTF_CUR_LVL((_lvl), _BT_LOG_OUTPUT_LEVEL, \
+ (_tag), (_init_msg), (_fmt), ##__VA_ARGS__)
-/* Used with _AUX macros and allows to override global format and output
- * facility. Use BT_LOG_GLOBAL_FORMAT and BT_LOG_GLOBAL_OUTPUT for values from
- * global configuration. Example:
- *
- * static const bt_log_output module_output = {
- * BT_LOG_PUT_STD, 0, custom_output_callback
- * };
- * static const bt_log_spec module_spec = {
- * BT_LOG_GLOBAL_FORMAT, &module_output
- * };
- * BT_LOGI_AUX(&module_spec, "Position: %ix%i", x, y);
- *
- * See BT_LOGF_AUX and BT_LOGF_MEM_AUX for details.
- */
-typedef struct bt_log_spec
+/* Internal: no-op function when a log level is disabled */
+static inline
+void _bt_log_unused(int dummy __attribute__((unused)), ...)
{
- const bt_log_format *format;
- const bt_log_output *output;
-}
-bt_log_spec;
-
-#ifdef __cplusplus
}
-#endif
-
-/* Execute log statement if condition is true. Example:
- *
- * BT_LOG_IF(1 < 2, BT_LOGI("Log this"));
- * BT_LOG_IF(1 > 2, BT_LOGI("Don't log this"));
- *
- * Keep in mind though, that if condition can't be evaluated at compile time,
- * then it will be evaluated at run time. This will increase exectuable size
- * and can have noticeable performance overhead. Try to limit conditions to
- * expressions that can be evaluated at compile time.
- */
-#define BT_LOG_IF(cond, f) do { _BT_LOG_IF((cond)) { f; } } _BT_LOG_ONCE
-
-/* Mark log statement as "secret". Log statements that are marked as secrets
- * will NOT be executed when censoring is enabled (see BT_LOG_CENSORED).
- * Example:
- *
- * BT_LOG_SECRET(BT_LOGI("Credit card: %s", credit_card));
- * BT_LOG_SECRET(BT_LOGD_MEM(cipher, cipher_sz, "Cipher bytes:"));
- */
-#define BT_LOG_SECRET(f) BT_LOG_IF(BT_LOG_SECRETS, f)
-
-/* Check "current" log level at compile time (ignoring "output" log level).
- * Evaluates to true when specified log level is enabled. For example:
- *
- * #if BT_LOG_ENABLED_DEBUG
- * const char *const g_enum_strings[] = {
- * "enum_value_0", "enum_value_1", "enum_value_2"
- * };
- * #endif
- * // ...
- * #if BT_LOG_ENABLED_DEBUG
- * BT_LOGD("enum value: %s", g_enum_strings[v]);
- * #endif
- *
- * See BT_MINIMAL_LOG_LEVEL for details.
- */
-#define BT_LOG_ENABLED(lvl) ((lvl) >= _BT_MINIMAL_LOG_LEVEL)
-#define BT_LOG_ENABLED_TRACE BT_LOG_ENABLED(BT_LOG_TRACE)
-#define BT_LOG_ENABLED_DEBUG BT_LOG_ENABLED(BT_LOG_DEBUG)
-#define BT_LOG_ENABLED_INFO BT_LOG_ENABLED(BT_LOG_INFO)
-#define BT_LOG_ENABLED_WARNING BT_LOG_ENABLED(BT_LOG_WARNING)
-#define BT_LOG_ENABLED_ERROR BT_LOG_ENABLED(BT_LOG_ERROR)
-#define BT_LOG_ENABLED_FATAL BT_LOG_ENABLED(BT_LOG_FATAL)
-
-/* Check "output" log level at run time (taking into account "current" log
- * level as well). Evaluates to true when specified log level is turned on AND
- * enabled. For example:
- *
- * if (BT_LOG_ON_DEBUG)
- * {
- * char hash[65];
- * sha256(data_ptr, data_sz, hash);
- * BT_LOGD("data: len=%u, sha256=%s", data_sz, hash);
- * }
- *
- * See BT_LOG_OUTPUT_LEVEL for details.
- */
-#define BT_LOG_ON_CUR_LVL(lvl, cur_lvl) \
- G_UNLIKELY(BT_LOG_ENABLED((lvl)) && (lvl) >= (cur_lvl))
-#define BT_LOG_ON(lvl) \
- G_UNLIKELY(BT_LOG_ENABLED((lvl)) && (lvl) >= _BT_LOG_OUTPUT_LEVEL)
-#define BT_LOG_ON_TRACE BT_LOG_ON(BT_LOG_TRACE)
-#define BT_LOG_ON_DEBUG BT_LOG_ON(BT_LOG_DEBUG)
-#define BT_LOG_ON_INFO BT_LOG_ON(BT_LOG_INFO)
-#define BT_LOG_ON_WARNING BT_LOG_ON(BT_LOG_WARNING)
-#define BT_LOG_ON_ERROR BT_LOG_ON(BT_LOG_ERROR)
-#define BT_LOG_ON_FATAL BT_LOG_ON(BT_LOG_FATAL)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern const char *_bt_log_tag_prefix;
-extern bt_log_format _bt_log_global_format;
-extern bt_log_output _bt_log_global_output;
-extern int _bt_log_global_output_lvl;
-extern const bt_log_spec _bt_log_stderr_spec;
-
-void _bt_log_write_d(
- const char *const func, const char *const file, const unsigned line,
- const int lvl, const char *const tag,
- const char *const fmt, ...) _BT_LOG_PRINTFLIKE(6, 7);
-
-void _bt_log_write_aux_d(
- const char *const func, const char *const file, const unsigned line,
- const bt_log_spec *const log, const int lvl, const char *const tag,
- const char *const fmt, ...) _BT_LOG_PRINTFLIKE(7, 8);
-
-void _bt_log_write(
- const int lvl, const char *const tag,
- const char *const fmt, ...) _BT_LOG_PRINTFLIKE(3, 4);
-
-void _bt_log_write_aux(
- const bt_log_spec *const log, const int lvl, const char *const tag,
- const char *const fmt, ...) _BT_LOG_PRINTFLIKE(4, 5);
-
-void _bt_log_write_mem_d(
- const char *const func, const char *const file, const unsigned line,
- const int lvl, const char *const tag,
- const void *const d, const unsigned d_sz,
- const char *const fmt, ...) _BT_LOG_PRINTFLIKE(8, 9);
-
-void _bt_log_write_mem_aux_d(
- const char *const func, const char *const file, const unsigned line,
- const bt_log_spec *const log, const int lvl, const char *const tag,
- const void *const d, const unsigned d_sz,
- const char *const fmt, ...) _BT_LOG_PRINTFLIKE(9, 10);
-
-void _bt_log_write_mem(
- const int lvl, const char *const tag,
- const void *const d, const unsigned d_sz,
- const char *const fmt, ...) _BT_LOG_PRINTFLIKE(5, 6);
-
-void _bt_log_write_mem_aux(
- const bt_log_spec *const log, const int lvl, const char *const tag,
- const void *const d, const unsigned d_sz,
- const char *const fmt, ...) _BT_LOG_PRINTFLIKE(6, 7);
-
-#ifdef __cplusplus
-}
-#endif
-
-/* Message logging macros:
- * - BT_LOGT("format string", args, ...)
- * - BT_LOGD("format string", args, ...)
- * - BT_LOGI("format string", args, ...)
- * - BT_LOGW("format string", args, ...)
- * - BT_LOGE("format string", args, ...)
- * - BT_LOGF("format string", args, ...)
- *
- * Message and error string (errno) logging macros:
- * - BT_LOGT_ERRNO("initial message", "format string", args, ...)
- * - BT_LOGD_ERRNO("initial message", "format string", args, ...)
- * - BT_LOGI_ERRNO("initial message", "format string", args, ...)
- * - BT_LOGW_ERRNO("initial message", "format string", args, ...)
- * - BT_LOGE_ERRNO("initial message", "format string", args, ...)
- * - BT_LOGF_ERRNO("initial message", "format string", args, ...)
- *
- * Memory logging macros:
- * - BT_LOGT_MEM(data_ptr, data_sz, "format string", args, ...)
- * - BT_LOGD_MEM(data_ptr, data_sz, "format string", args, ...)
- * - BT_LOGI_MEM(data_ptr, data_sz, "format string", args, ...)
- * - BT_LOGW_MEM(data_ptr, data_sz, "format string", args, ...)
- * - BT_LOGE_MEM(data_ptr, data_sz, "format string", args, ...)
- * - BT_LOGF_MEM(data_ptr, data_sz, "format string", args, ...)
- *
- * Auxiliary logging macros:
- * - BT_LOGT_AUX(&log_instance, "format string", args, ...)
- * - BT_LOGD_AUX(&log_instance, "format string", args, ...)
- * - BT_LOGI_AUX(&log_instance, "format string", args, ...)
- * - BT_LOGW_AUX(&log_instance, "format string", args, ...)
- * - BT_LOGE_AUX(&log_instance, "format string", args, ...)
- * - BT_LOGF_AUX(&log_instance, "format string", args, ...)
- *
- * Auxiliary memory logging macros:
- * - BT_LOGT_MEM_AUX(&log_instance, data_ptr, data_sz, "format string", args, ...)
- * - BT_LOGD_MEM_AUX(&log_instance, data_ptr, data_sz, "format string", args, ...)
- * - BT_LOGI_MEM_AUX(&log_instance, data_ptr, data_sz, "format string", args, ...)
- * - BT_LOGW_MEM_AUX(&log_instance, data_ptr, data_sz, "format string", args, ...)
- * - BT_LOGE_MEM_AUX(&log_instance, data_ptr, data_sz, "format string", args, ...)
- * - BT_LOGF_MEM_AUX(&log_instance, data_ptr, data_sz, "format string", args, ...)
- *
- * Preformatted string logging macros:
- * - BT_LOGT_STR("preformatted string");
- * - BT_LOGD_STR("preformatted string");
- * - BT_LOGI_STR("preformatted string");
- * - BT_LOGW_STR("preformatted string");
- * - BT_LOGE_STR("preformatted string");
- * - BT_LOGF_STR("preformatted string");
- *
- * Explicit log level and tag macros:
- * - BT_LOG_WRITE(level, tag, "format string", args, ...)
- * - BT_LOG_WRITE_MEM(level, tag, data_ptr, data_sz, "format string", args, ...)
- * - BT_LOG_WRITE_AUX(&log_instance, level, tag, "format string", args, ...)
- * - BT_LOG_WRITE_MEM_AUX(&log_instance, level, tag, data_ptr, data_sz,
- * "format string", args, ...)
- *
- * Explicit log level, current log level, and tag:
- * - BT_LOG_WRITE_CUR_LVL(level, cur_level, tag, "format string", args, ...)
- *
- * Format string follows printf() conventions. Both data_ptr and data_sz could
- * be 0. Tag can be 0 as well. Most compilers will verify that type of arguments
- * match format specifiers in format string.
- *
- * Library assuming UTF-8 encoding for all strings (char *), including format
- * string itself.
- */
-#if BT_LOG_SRCLOC_NONE == _BT_LOG_SRCLOC
- #define BT_LOG_WRITE(lvl, tag, ...) \
- do { \
- if (BT_LOG_ON(lvl)) \
- _bt_log_write(lvl, tag, __VA_ARGS__); \
- } _BT_LOG_ONCE
- #define BT_LOG_WRITE_CUR_LVL(lvl, cur_lvl, tag, ...) \
- do { \
- if (BT_LOG_ON_CUR_LVL((lvl), (cur_lvl))) \
- _bt_log_write(lvl, tag, __VA_ARGS__); \
- } _BT_LOG_ONCE
- #define BT_LOG_WRITE_MEM(lvl, tag, d, d_sz, ...) \
- do { \
- if (BT_LOG_ON(lvl)) \
- _bt_log_write_mem(lvl, tag, d, d_sz, __VA_ARGS__); \
- } _BT_LOG_ONCE
- #define BT_LOG_WRITE_AUX(log, lvl, tag, ...) \
- do { \
- if (BT_LOG_ON(lvl)) \
- _bt_log_write_aux(log, lvl, tag, __VA_ARGS__); \
- } _BT_LOG_ONCE
- #define BT_LOG_WRITE_MEM_AUX(log, lvl, tag, d, d_sz, ...) \
- do { \
- if (BT_LOG_ON(lvl)) \
- _bt_log_write_mem_aux(log, lvl, tag, d, d_sz, __VA_ARGS__); \
- } _BT_LOG_ONCE
-#else
- #define BT_LOG_WRITE(lvl, tag, ...) \
- do { \
- if (BT_LOG_ON(lvl)) \
- _bt_log_write_d(_BT_LOG_SRCLOC_FUNCTION, __FILE__, __LINE__, \
- lvl, tag, __VA_ARGS__); \
- } _BT_LOG_ONCE
- #define BT_LOG_WRITE_CUR_LVL(lvl, cur_lvl, tag, ...) \
- do { \
- if (BT_LOG_ON_CUR_LVL((lvl), (cur_lvl))) \
- _bt_log_write_d(_BT_LOG_SRCLOC_FUNCTION, __FILE__, __LINE__, \
- lvl, tag, __VA_ARGS__); \
- } _BT_LOG_ONCE
- #define BT_LOG_WRITE_MEM(lvl, tag, d, d_sz, ...) \
- do { \
- if (BT_LOG_ON(lvl)) \
- _bt_log_write_mem_d(_BT_LOG_SRCLOC_FUNCTION, __FILE__, __LINE__, \
- lvl, tag, d, d_sz, __VA_ARGS__); \
- } _BT_LOG_ONCE
- #define BT_LOG_WRITE_AUX(log, lvl, tag, ...) \
- do { \
- if (BT_LOG_ON(lvl)) \
- _bt_log_write_aux_d(_BT_LOG_SRCLOC_FUNCTION, __FILE__, __LINE__, \
- log, lvl, tag, __VA_ARGS__); \
- } _BT_LOG_ONCE
- #define BT_LOG_WRITE_MEM_AUX(log, lvl, tag, d, d_sz, ...) \
- do { \
- if (BT_LOG_ON(lvl)) \
- _bt_log_write_mem_aux_d(_BT_LOG_SRCLOC_FUNCTION, __FILE__, __LINE__, \
- log, lvl, tag, d, d_sz, __VA_ARGS__); \
- } _BT_LOG_ONCE
-#endif
-
-#define BT_LOG_WRITE_ERRNO_CUR_LVL(lvl, cur_lvl, tag, _msg, _fmt, args...) \
- do { \
- const char *error_str; \
- error_str = g_strerror(errno); \
- BT_LOG_WRITE_CUR_LVL(lvl, cur_lvl, tag, _msg ": %s" _fmt, error_str, ## args); \
- } _BT_LOG_ONCE
-
-#define BT_LOG_WRITE_ERRNO(lvl, tag, _msg, _fmt, args...) \
- do { \
- BT_LOG_WRITE_ERRNO_CUR_LVL(lvl, _BT_LOG_OUTPUT_LEVEL, tag, _msg, _fmt, ## args); \
- } _BT_LOG_ONCE
-
-static _BT_LOG_INLINE void _bt_log_unused(const int dummy, ...) {(void)dummy;}
#define _BT_LOG_UNUSED(...) \
- do { _BT_LOG_NEVER _bt_log_unused(0, __VA_ARGS__); } _BT_LOG_ONCE
+ do { if (0) _bt_log_unused(0, ##__VA_ARGS__); } while (0)
+/* Trace level logging macros using `BT_LOG_TAG` */
#if BT_LOG_ENABLED_TRACE
- #define BT_LOGT(...) \
- BT_LOG_WRITE(BT_LOG_TRACE, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGT_ERRNO(...) \
- BT_LOG_WRITE_ERRNO(BT_LOG_TRACE, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGT_AUX(log, ...) \
- BT_LOG_WRITE_AUX(log, BT_LOG_TRACE, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGT_MEM(d, d_sz, ...) \
- BT_LOG_WRITE_MEM(BT_LOG_TRACE, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
- #define BT_LOGT_MEM_AUX(log, d, d_sz, ...) \
- BT_LOG_WRITE_MEM(log, BT_LOG_TRACE, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
+# define BT_LOGT_STR_CUR_LVL(_cur_lvl, _msg) \
+ BT_LOG_WRITE_CUR_LVL(BT_LOG_TRACE, (_cur_lvl), _BT_LOG_TAG, (_msg))
+# define BT_LOGT_STR(_msg) \
+ BT_LOG_WRITE(BT_LOG_TRACE, _BT_LOG_TAG, (_msg))
+# define BT_LOGT_CUR_LVL(_cur_lvl, _fmt, ...) \
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_TRACE, (_cur_lvl), _BT_LOG_TAG, (_fmt), ##__VA_ARGS__)
+# define BT_LOGT(_fmt, ...) \
+ BT_LOG_WRITE_PRINTF(BT_LOG_TRACE, _BT_LOG_TAG, (_fmt), ##__VA_ARGS__)
+# define BT_LOGT_MEM_STR_CUR_LVL(_cur_lvl, _mem_data, _mem_len, _msg) \
+ BT_LOG_WRITE_MEM_CUR_LVL(BT_LOG_TRACE, (_cur_lvl), _BT_LOG_TAG, (_mem_data), (_mem_len), (_msg))
+# define BT_LOGT_MEM_STR(_mem_data, _mem_len, _msg) \
+ BT_LOG_WRITE_MEM(BT_LOG_TRACE, _BT_LOG_TAG, (_mem_data), (_mem_len), (_msg))
+# define BT_LOGT_MEM_CUR_LVL(_cur_lvl, _mem_data, _mem_len, _fmt, ...) \
+ BT_LOG_WRITE_MEM_PRINTF_CUR_LVL(BT_LOG_TRACE, (_cur_lvl), _BT_LOG_TAG, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__)
+# define BT_LOGT_MEM(_mem_data, _mem_len, _fmt, ...) \
+ BT_LOG_WRITE_MEM_PRINTF(BT_LOG_TRACE, _BT_LOG_TAG, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__)
+# define BT_LOGT_ERRNO_STR_CUR_LVL(_cur_lvl, _init_msg, _msg) \
+ BT_LOG_WRITE_ERRNO_CUR_LVL(BT_LOG_TRACE, (_cur_lvl), _BT_LOG_TAG, (_init_msg), (_msg))
+# define BT_LOGT_ERRNO_STR(_init_msg, _msg) \
+ BT_LOG_WRITE_ERRNO(BT_LOG_TRACE, _BT_LOG_TAG, (_init_msg), (_msg))
+# define BT_LOGT_ERRNO_CUR_LVL(_cur_lvl, _init_msg, _fmt, ...) \
+ BT_LOG_WRITE_ERRNO_PRINTF_CUR_LVL(BT_LOG_TRACE, (_cur_lvl), _BT_LOG_TAG, (_init_msg), (_fmt), ##__VA_ARGS__)
+# define BT_LOGT_ERRNO(_init_msg, _fmt, ...) \
+ BT_LOG_WRITE_ERRNO_PRINTF(BT_LOG_TRACE, _BT_LOG_TAG, (_init_msg), (_fmt), ##__VA_ARGS__)
#else
- #define BT_LOGT(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGT_ERRNO(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGT_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGT_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGT_MEM_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
-#endif
-
+# define BT_LOGT_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGT_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGT_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGT(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGT_MEM_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGT_MEM_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGT_MEM_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGT_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGT_ERRNO_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGT_ERRNO_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGT_ERRNO_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGT_ERRNO(...) _BT_LOG_UNUSED(__VA_ARGS__)
+#endif /* BT_LOG_ENABLED_TRACE */
+
+/* Debug level logging macros using `BT_LOG_TAG` */
#if BT_LOG_ENABLED_DEBUG
- #define BT_LOGD(...) \
- BT_LOG_WRITE(BT_LOG_DEBUG, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGD_ERRNO(...) \
- BT_LOG_WRITE_ERRNO(BT_LOG_DEBUG, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGD_AUX(log, ...) \
- BT_LOG_WRITE_AUX(log, BT_LOG_DEBUG, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGD_MEM(d, d_sz, ...) \
- BT_LOG_WRITE_MEM(BT_LOG_DEBUG, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
- #define BT_LOGD_MEM_AUX(log, d, d_sz, ...) \
- BT_LOG_WRITE_MEM_AUX(log, BT_LOG_DEBUG, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
+# define BT_LOGD_STR_CUR_LVL(_cur_lvl, _msg) \
+ BT_LOG_WRITE_CUR_LVL(BT_LOG_DEBUG, (_cur_lvl), _BT_LOG_TAG, (_msg))
+# define BT_LOGD_STR(_msg) \
+ BT_LOG_WRITE(BT_LOG_DEBUG, _BT_LOG_TAG, (_msg))
+# define BT_LOGD_CUR_LVL(_cur_lvl, _fmt, ...) \
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_DEBUG, (_cur_lvl), _BT_LOG_TAG, (_fmt), ##__VA_ARGS__)
+# define BT_LOGD(_fmt, ...) \
+ BT_LOG_WRITE_PRINTF(BT_LOG_DEBUG, _BT_LOG_TAG, (_fmt), ##__VA_ARGS__)
+# define BT_LOGD_MEM_STR_CUR_LVL(_cur_lvl, _mem_data, _mem_len, _msg) \
+ BT_LOG_WRITE_MEM_CUR_LVL(BT_LOG_DEBUG, (_cur_lvl), _BT_LOG_TAG, (_mem_data), (_mem_len), (_msg))
+# define BT_LOGD_MEM_STR(_mem_data, _mem_len, _msg) \
+ BT_LOG_WRITE_MEM(BT_LOG_DEBUG, _BT_LOG_TAG, (_mem_data), (_mem_len), (_msg))
+# define BT_LOGD_MEM_CUR_LVL(_cur_lvl, _mem_data, _mem_len, _fmt, ...) \
+ BT_LOG_WRITE_MEM_PRINTF_CUR_LVL(BT_LOG_DEBUG, (_cur_lvl), _BT_LOG_TAG, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__)
+# define BT_LOGD_MEM(_mem_data, _mem_len, _fmt, ...) \
+ BT_LOG_WRITE_MEM_PRINTF(BT_LOG_DEBUG, _BT_LOG_TAG, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__)
+# define BT_LOGD_ERRNO_STR_CUR_LVL(_cur_lvl, _init_msg, _msg) \
+ BT_LOG_WRITE_ERRNO_CUR_LVL(BT_LOG_DEBUG, (_cur_lvl), _BT_LOG_TAG, (_init_msg), (_msg))
+# define BT_LOGD_ERRNO_STR(_init_msg, _msg) \
+ BT_LOG_WRITE_ERRNO(BT_LOG_DEBUG, _BT_LOG_TAG, (_init_msg), (_msg))
+# define BT_LOGD_ERRNO_CUR_LVL(_cur_lvl, _init_msg, _fmt, ...) \
+ BT_LOG_WRITE_ERRNO_PRINTF_CUR_LVL(BT_LOG_DEBUG, (_cur_lvl), _BT_LOG_TAG, (_init_msg), (_fmt), ##__VA_ARGS__)
+# define BT_LOGD_ERRNO(_init_msg, _fmt, ...) \
+ BT_LOG_WRITE_ERRNO_PRINTF(BT_LOG_DEBUG, _BT_LOG_TAG, (_init_msg), (_fmt), ##__VA_ARGS__)
#else
- #define BT_LOGD(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGD_ERRNO(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGD_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGD_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGD_MEM_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
-#endif
-
+# define BT_LOGD_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGD_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGD_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGD(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGD_MEM_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGD_MEM_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGD_MEM_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGD_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGD_ERRNO_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGD_ERRNO_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGD_ERRNO_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGD_ERRNO(...) _BT_LOG_UNUSED(__VA_ARGS__)
+#endif /* BT_LOG_ENABLED_DEBUG */
+
+/* Info level logging macros using `BT_LOG_TAG` */
#if BT_LOG_ENABLED_INFO
- #define BT_LOGI(...) \
- BT_LOG_WRITE(BT_LOG_INFO, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGI_ERRNO(...) \
- BT_LOG_WRITE_ERRNO(BT_LOG_INFO, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGI_AUX(log, ...) \
- BT_LOG_WRITE_AUX(log, BT_LOG_INFO, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGI_MEM(d, d_sz, ...) \
- BT_LOG_WRITE_MEM(BT_LOG_INFO, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
- #define BT_LOGI_MEM_AUX(log, d, d_sz, ...) \
- BT_LOG_WRITE_MEM_AUX(log, BT_LOG_INFO, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
+# define BT_LOGI_STR_CUR_LVL(_cur_lvl, _msg) \
+ BT_LOG_WRITE_CUR_LVL(BT_LOG_INFO, (_cur_lvl), _BT_LOG_TAG, (_msg))
+# define BT_LOGI_STR(_msg) \
+ BT_LOG_WRITE(BT_LOG_INFO, _BT_LOG_TAG, (_msg))
+# define BT_LOGI_CUR_LVL(_cur_lvl, _fmt, ...) \
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_INFO, (_cur_lvl), _BT_LOG_TAG, (_fmt), ##__VA_ARGS__)
+# define BT_LOGI(_fmt, ...) \
+ BT_LOG_WRITE_PRINTF(BT_LOG_INFO, _BT_LOG_TAG, (_fmt), ##__VA_ARGS__)
+# define BT_LOGI_MEM_STR_CUR_LVL(_cur_lvl, _mem_data, _mem_len, _msg) \
+ BT_LOG_WRITE_MEM_CUR_LVL(BT_LOG_INFO, (_cur_lvl), _BT_LOG_TAG, (_mem_data), (_mem_len), (_msg))
+# define BT_LOGI_MEM_STR(_mem_data, _mem_len, _msg) \
+ BT_LOG_WRITE_MEM(BT_LOG_INFO, _BT_LOG_TAG, (_mem_data), (_mem_len), (_msg))
+# define BT_LOGI_MEM_CUR_LVL(_cur_lvl, _mem_data, _mem_len, _fmt, ...) \
+ BT_LOG_WRITE_MEM_PRINTF_CUR_LVL(BT_LOG_INFO, (_cur_lvl), _BT_LOG_TAG, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__)
+# define BT_LOGI_MEM(_mem_data, _mem_len, _fmt, ...) \
+ BT_LOG_WRITE_MEM_PRINTF(BT_LOG_INFO, _BT_LOG_TAG, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__)
+# define BT_LOGI_ERRNO_STR_CUR_LVL(_cur_lvl, _init_msg, _msg) \
+ BT_LOG_WRITE_ERRNO_CUR_LVL(BT_LOG_INFO, (_cur_lvl), _BT_LOG_TAG, (_init_msg), (_msg))
+# define BT_LOGI_ERRNO_STR(_init_msg, _msg) \
+ BT_LOG_WRITE_ERRNO(BT_LOG_INFO, _BT_LOG_TAG, (_init_msg), (_msg))
+# define BT_LOGI_ERRNO_CUR_LVL(_cur_lvl, _init_msg, _fmt, ...) \
+ BT_LOG_WRITE_ERRNO_PRINTF_CUR_LVL(BT_LOG_INFO, (_cur_lvl), _BT_LOG_TAG, (_init_msg), (_fmt), ##__VA_ARGS__)
+# define BT_LOGI_ERRNO(_init_msg, _fmt, ...) \
+ BT_LOG_WRITE_ERRNO_PRINTF(BT_LOG_INFO, _BT_LOG_TAG, (_init_msg), (_fmt), ##__VA_ARGS__)
#else
- #define BT_LOGI(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGI_ERRNO(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGI_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGI_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGI_MEM_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
-#endif
-
+# define BT_LOGI_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGI_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGI_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGI(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGI_MEM_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGI_MEM_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGI_MEM_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGI_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGI_ERRNO_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGI_ERRNO_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGI_ERRNO_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGI_ERRNO(...) _BT_LOG_UNUSED(__VA_ARGS__)
+#endif /* BT_LOG_ENABLED_INFO */
+
+/* Warning level logging macros using `BT_LOG_TAG` */
#if BT_LOG_ENABLED_WARNING
- #define BT_LOGW(...) \
- BT_LOG_WRITE(BT_LOG_WARNING, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGW_ERRNO(...) \
- BT_LOG_WRITE_ERRNO(BT_LOG_WARNING, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGW_AUX(log, ...) \
- BT_LOG_WRITE_AUX(log, BT_LOG_WARNING, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGW_MEM(d, d_sz, ...) \
- BT_LOG_WRITE_MEM(BT_LOG_WARNING, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
- #define BT_LOGW_MEM_AUX(log, d, d_sz, ...) \
- BT_LOG_WRITE_MEM_AUX(log, BT_LOG_WARNING, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
+# define BT_LOGW_STR_CUR_LVL(_cur_lvl, _msg) \
+ BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, (_cur_lvl), _BT_LOG_TAG, (_msg))
+# define BT_LOGW_STR(_msg) \
+ BT_LOG_WRITE(BT_LOG_WARNING, _BT_LOG_TAG, (_msg))
+# define BT_LOGW_CUR_LVL(_cur_lvl, _fmt, ...) \
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_WARNING, (_cur_lvl), _BT_LOG_TAG, (_fmt), ##__VA_ARGS__)
+# define BT_LOGW(_fmt, ...) \
+ BT_LOG_WRITE_PRINTF(BT_LOG_WARNING, _BT_LOG_TAG, (_fmt), ##__VA_ARGS__)
+# define BT_LOGW_MEM_STR_CUR_LVL(_cur_lvl, _mem_data, _mem_len, _msg) \
+ BT_LOG_WRITE_MEM_CUR_LVL(BT_LOG_WARNING, (_cur_lvl), _BT_LOG_TAG, (_mem_data), (_mem_len), (_msg))
+# define BT_LOGW_MEM_STR(_mem_data, _mem_len, _msg) \
+ BT_LOG_WRITE_MEM(BT_LOG_WARNING, _BT_LOG_TAG, (_mem_data), (_mem_len), (_msg))
+# define BT_LOGW_MEM_CUR_LVL(_cur_lvl, _mem_data, _mem_len, _fmt, ...) \
+ BT_LOG_WRITE_MEM_PRINTF_CUR_LVL(BT_LOG_WARNING, (_cur_lvl), _BT_LOG_TAG, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__)
+# define BT_LOGW_MEM(_mem_data, _mem_len, _fmt, ...) \
+ BT_LOG_WRITE_MEM_PRINTF(BT_LOG_WARNING, _BT_LOG_TAG, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__)
+# define BT_LOGW_ERRNO_STR_CUR_LVL(_cur_lvl, _init_msg, _msg) \
+ BT_LOG_WRITE_ERRNO_CUR_LVL(BT_LOG_WARNING, (_cur_lvl), _BT_LOG_TAG, (_init_msg), (_msg))
+# define BT_LOGW_ERRNO_STR(_init_msg, _msg) \
+ BT_LOG_WRITE_ERRNO(BT_LOG_WARNING, _BT_LOG_TAG, (_init_msg), (_msg))
+# define BT_LOGW_ERRNO_CUR_LVL(_cur_lvl, _init_msg, _fmt, ...) \
+ BT_LOG_WRITE_ERRNO_PRINTF_CUR_LVL(BT_LOG_WARNING, (_cur_lvl), _BT_LOG_TAG, (_init_msg), (_fmt), ##__VA_ARGS__)
+# define BT_LOGW_ERRNO(_init_msg, _fmt, ...) \
+ BT_LOG_WRITE_ERRNO_PRINTF(BT_LOG_WARNING, _BT_LOG_TAG, (_init_msg), (_fmt), ##__VA_ARGS__)
#else
- #define BT_LOGW(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGW_ERRNO(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGW_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGW_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGW_MEM_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
-#endif
-
+# define BT_LOGW_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGW_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGW_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGW(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGW_MEM_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGW_MEM_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGW_MEM_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGW_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGW_ERRNO_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGW_ERRNO_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGW_ERRNO_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGW_ERRNO(...) _BT_LOG_UNUSED(__VA_ARGS__)
+#endif /* BT_LOG_ENABLED_WARNING */
+
+/* Error level logging macros using `BT_LOG_TAG` */
#if BT_LOG_ENABLED_ERROR
- #define BT_LOGE(...) \
- BT_LOG_WRITE(BT_LOG_ERROR, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGE_ERRNO(...) \
- BT_LOG_WRITE_ERRNO(BT_LOG_ERROR, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGE_AUX(log, ...) \
- BT_LOG_WRITE_AUX(log, BT_LOG_ERROR, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGE_MEM(d, d_sz, ...) \
- BT_LOG_WRITE_MEM(BT_LOG_ERROR, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
- #define BT_LOGE_MEM_AUX(log, d, d_sz, ...) \
- BT_LOG_WRITE_MEM_AUX(log, BT_LOG_ERROR, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
+# define BT_LOGE_STR_CUR_LVL(_cur_lvl, _msg) \
+ BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, (_cur_lvl), _BT_LOG_TAG, (_msg))
+# define BT_LOGE_STR(_msg) \
+ BT_LOG_WRITE(BT_LOG_ERROR, _BT_LOG_TAG, (_msg))
+# define BT_LOGE_CUR_LVL(_cur_lvl, _fmt, ...) \
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_ERROR, (_cur_lvl), _BT_LOG_TAG, (_fmt), ##__VA_ARGS__)
+# define BT_LOGE(_fmt, ...) \
+ BT_LOG_WRITE_PRINTF(BT_LOG_ERROR, _BT_LOG_TAG, (_fmt), ##__VA_ARGS__)
+# define BT_LOGE_MEM_STR_CUR_LVL(_cur_lvl, _mem_data, _mem_len, _msg) \
+ BT_LOG_WRITE_MEM_CUR_LVL(BT_LOG_ERROR, (_cur_lvl), _BT_LOG_TAG, (_mem_data), (_mem_len), (_msg))
+# define BT_LOGE_MEM_STR(_mem_data, _mem_len, _msg) \
+ BT_LOG_WRITE_MEM(BT_LOG_ERROR, _BT_LOG_TAG, (_mem_data), (_mem_len), (_msg))
+# define BT_LOGE_MEM_CUR_LVL(_cur_lvl, _mem_data, _mem_len, _fmt, ...) \
+ BT_LOG_WRITE_MEM_PRINTF_CUR_LVL(BT_LOG_ERROR, (_cur_lvl), _BT_LOG_TAG, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__)
+# define BT_LOGE_MEM(_mem_data, _mem_len, _fmt, ...) \
+ BT_LOG_WRITE_MEM_PRINTF(BT_LOG_ERROR, _BT_LOG_TAG, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__)
+# define BT_LOGE_ERRNO_STR_CUR_LVL(_cur_lvl, _init_msg, _msg) \
+ BT_LOG_WRITE_ERRNO_CUR_LVL(BT_LOG_ERROR, (_cur_lvl), _BT_LOG_TAG, (_init_msg), (_msg))
+# define BT_LOGE_ERRNO_STR(_init_msg, _msg) \
+ BT_LOG_WRITE_ERRNO(BT_LOG_ERROR, _BT_LOG_TAG, (_init_msg), (_msg))
+# define BT_LOGE_ERRNO_CUR_LVL(_cur_lvl, _init_msg, _fmt, ...) \
+ BT_LOG_WRITE_ERRNO_PRINTF_CUR_LVL(BT_LOG_ERROR, (_cur_lvl), _BT_LOG_TAG, (_init_msg), (_fmt), ##__VA_ARGS__)
+# define BT_LOGE_ERRNO(_init_msg, _fmt, ...) \
+ BT_LOG_WRITE_ERRNO_PRINTF(BT_LOG_ERROR, _BT_LOG_TAG, (_init_msg), (_fmt), ##__VA_ARGS__)
#else
- #define BT_LOGE(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGE_ERRNO(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGE_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGE_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGE_MEM_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
-#endif
-
+# define BT_LOGE_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGE_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGE_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGE(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGE_MEM_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGE_MEM_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGE_MEM_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGE_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGE_ERRNO_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGE_ERRNO_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGE_ERRNO_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGE_ERRNO(...) _BT_LOG_UNUSED(__VA_ARGS__)
+#endif /* BT_LOG_ENABLED_ERROR */
+
+/* Fatal level logging macros using `BT_LOG_TAG` */
#if BT_LOG_ENABLED_FATAL
- #define BT_LOGF(...) \
- BT_LOG_WRITE(BT_LOG_FATAL, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGF_ERRNO(...) \
- BT_LOG_WRITE_ERRNO(BT_LOG_FATAL, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGF_AUX(log, ...) \
- BT_LOG_WRITE_AUX(log, BT_LOG_FATAL, _BT_LOG_TAG, __VA_ARGS__)
- #define BT_LOGF_MEM(d, d_sz, ...) \
- BT_LOG_WRITE_MEM(BT_LOG_FATAL, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
- #define BT_LOGF_MEM_AUX(log, d, d_sz, ...) \
- BT_LOG_WRITE_MEM_AUX(log, BT_LOG_FATAL, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
+# define BT_LOGF_STR_CUR_LVL(_cur_lvl, _msg) \
+ BT_LOG_WRITE_CUR_LVL(BT_LOG_FATAL, (_cur_lvl), _BT_LOG_TAG, (_msg))
+# define BT_LOGF_STR(_msg) \
+ BT_LOG_WRITE(BT_LOG_FATAL, _BT_LOG_TAG, (_msg))
+# define BT_LOGF_CUR_LVL(_cur_lvl, _fmt, ...) \
+ BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_FATAL, (_cur_lvl), _BT_LOG_TAG, (_fmt), ##__VA_ARGS__)
+# define BT_LOGF(_fmt, ...) \
+ BT_LOG_WRITE_PRINTF(BT_LOG_FATAL, _BT_LOG_TAG, (_fmt), ##__VA_ARGS__)
+# define BT_LOGF_MEM_STR_CUR_LVL(_cur_lvl, _mem_data, _mem_len, _msg) \
+ BT_LOG_WRITE_MEM_CUR_LVL(BT_LOG_FATAL, (_cur_lvl), _BT_LOG_TAG, (_mem_data), (_mem_len), (_msg))
+# define BT_LOGF_MEM_STR(_mem_data, _mem_len, _msg) \
+ BT_LOG_WRITE_MEM(BT_LOG_FATAL, _BT_LOG_TAG, (_mem_data), (_mem_len), (_msg))
+# define BT_LOGF_MEM_CUR_LVL(_cur_lvl, _mem_data, _mem_len, _fmt, ...) \
+ BT_LOG_WRITE_MEM_PRINTF_CUR_LVL(BT_LOG_FATAL, (_cur_lvl), _BT_LOG_TAG, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__)
+# define BT_LOGF_MEM(_mem_data, _mem_len, _fmt, ...) \
+ BT_LOG_WRITE_MEM_PRINTF(BT_LOG_FATAL, _BT_LOG_TAG, (_mem_data), (_mem_len), (_fmt), ##__VA_ARGS__)
+# define BT_LOGF_ERRNO_STR_CUR_LVL(_cur_lvl, _init_msg, _msg) \
+ BT_LOG_WRITE_ERRNO_CUR_LVL(BT_LOG_FATAL, (_cur_lvl), _BT_LOG_TAG, (_init_msg), (_msg))
+# define BT_LOGF_ERRNO_STR(_init_msg, _msg) \
+ BT_LOG_WRITE_ERRNO(BT_LOG_FATAL, _BT_LOG_TAG, (_init_msg), (_msg))
+# define BT_LOGF_ERRNO_CUR_LVL(_cur_lvl, _init_msg, _fmt, ...) \
+ BT_LOG_WRITE_ERRNO_PRINTF_CUR_LVL(BT_LOG_FATAL, (_cur_lvl), _BT_LOG_TAG, (_init_msg), (_fmt), ##__VA_ARGS__)
+# define BT_LOGF_ERRNO(_init_msg, _fmt, ...) \
+ BT_LOG_WRITE_ERRNO_PRINTF(BT_LOG_FATAL, _BT_LOG_TAG, (_init_msg), (_fmt), ##__VA_ARGS__)
#else
- #define BT_LOGF(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGF_ERRNO(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGF_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGF_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
- #define BT_LOGF_MEM_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
-#endif
-
-#define BT_LOGT_STR(s) BT_LOGT("%s", (s))
-#define BT_LOGD_STR(s) BT_LOGD("%s", (s))
-#define BT_LOGI_STR(s) BT_LOGI("%s", (s))
-#define BT_LOGW_STR(s) BT_LOGW("%s", (s))
-#define BT_LOGE_STR(s) BT_LOGE("%s", (s))
-#define BT_LOGF_STR(s) BT_LOGF("%s", (s))
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Output to standard error stream. Library uses it by default, though in few
- * cases it could be necessary to specify it explicitly. For example, when
- * bt_log library is compiled with BT_LOG_EXTERN_GLOBAL_OUTPUT, application must
- * define and initialize global output variable:
- *
- * BT_LOG_DEFINE_GLOBAL_OUTPUT = {BT_LOG_OUT_STDERR};
- *
- * Another example is when using custom output, stderr could be used as a
- * fallback when custom output facility failed to initialize:
- *
- * bt_log_set_output_v(BT_LOG_OUT_STDERR);
- */
-enum { BT_LOG_OUT_STDERR_MASK = BT_LOG_PUT_STD };
-
-void bt_log_out_stderr_callback(const bt_log_message *const msg, void *arg);
-#define BT_LOG_OUT_STDERR BT_LOG_OUT_STDERR_MASK, 0, bt_log_out_stderr_callback
-
-/* Predefined spec for stderr. Uses global format options (BT_LOG_GLOBAL_FORMAT)
- * and BT_LOG_OUT_STDERR. Could be used to force output to stderr for a
- * particular message. Example:
- *
- * f = fopen("foo.log", "w");
- * if (!f)
- * BT_LOGE_AUX(BT_LOG_STDERR, "Failed to open log file");
- */
-#define BT_LOG_STDERR (&_bt_log_stderr_spec)
-
-/*
- * Returns the equivalent letter of the log level `level`.
- *
- * `level` must be a valid log level.
- */
-static inline
-char bt_log_get_letter_from_level(int level)
-{
- char letter;
-
- switch (level) {
- case BT_LOG_TRACE:
- letter = 'T';
- break;
- case BT_LOG_DEBUG:
- letter = 'D';
- break;
- case BT_LOG_INFO:
- letter = 'I';
- break;
- case BT_LOG_WARNING:
- letter = 'W';
- break;
- case BT_LOG_ERROR:
- letter = 'E';
- break;
- case BT_LOG_FATAL:
- letter = 'F';
- break;
- case BT_LOG_NONE:
- letter = 'N';
- break;
- default:
- abort();
- }
-
- return letter;
-}
-
-/*
- * Returns the log level for the string `str`, or -1 if `str` is not a
- * valid log level string.
- */
-static inline
-int bt_log_get_level_from_string(const char *str)
-{
- int level = -1;
-
- BT_ASSERT(str);
-
- if (strcmp(str, "TRACE") == 0 ||
- strcmp(str, "T") == 0) {
- level = BT_LOG_TRACE;
- } else if (strcmp(str, "DEBUG") == 0 ||
- strcmp(str, "D") == 0) {
- level = BT_LOG_DEBUG;
- } else if (strcmp(str, "INFO") == 0 ||
- strcmp(str, "I") == 0) {
- level = BT_LOG_INFO;
- } else if (strcmp(str, "WARN") == 0 ||
- strcmp(str, "WARNING") == 0 ||
- strcmp(str, "W") == 0) {
- level = BT_LOG_WARNING;
- } else if (strcmp(str, "ERROR") == 0 ||
- strcmp(str, "E") == 0) {
- level = BT_LOG_ERROR;
- } else if (strcmp(str, "FATAL") == 0 ||
- strcmp(str, "F") == 0) {
- level = BT_LOG_FATAL;
- } else if (strcmp(str, "NONE") == 0 ||
- strcmp(str, "N") == 0) {
- level = BT_LOG_NONE;
- } else {
- /* FIXME: Should we warn here? How? */
- }
-
- return level;
-}
+# define BT_LOGF_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGF_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGF_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGF(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGF_MEM_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGF_MEM_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGF_MEM_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGF_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGF_ERRNO_STR_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGF_ERRNO_STR(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGF_ERRNO_CUR_LVL(...) _BT_LOG_UNUSED(__VA_ARGS__)
+# define BT_LOGF_ERRNO(...) _BT_LOG_UNUSED(__VA_ARGS__)
+#endif /* BT_LOG_ENABLED_FATAL */
/*
- * Returns the log level for the letter `letter`, or -1 if `letter` is
- * not a valid log level string.
+ * Tell the world that `log.h` was included without having to rely on
+ * the specific include guard.
*/
-static inline
-int bt_log_get_level_from_letter(char letter)
-{
- char str[] = {letter, '\0'};
-
- return bt_log_get_level_from_string(str);
-}
-
-static inline
-int bt_log_get_level_from_env(const char *var)
-{
- const char *varval = getenv(var);
- int level = BT_LOG_NONE;
-
- if (!varval) {
- goto end;
- }
-
- level = bt_log_get_level_from_string(varval);
- if (level < 0) {
- /* FIXME: Should we warn here? How? */
- level = BT_LOG_NONE;
- }
-
-end:
- return level;
-}
-
-#define BT_LOG_LEVEL_EXTERN_SYMBOL(_level_sym) \
- extern int _level_sym
-
-#define BT_LOG_INIT_LOG_LEVEL(_level_sym, _env_var) \
- int _level_sym = BT_LOG_NONE; \
- static \
- void __attribute__((constructor)) _bt_log_level_ctor(void) \
- { \
- _level_sym = bt_log_get_level_from_env(_env_var); \
- }
-
#define BT_LOG_SUPPORTED
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* BABELTRACE_LOGGING_INTERNAL_H */
+#endif /* BABELTRACE_LOGGING_LOG_H */
#define BT_COMP_LOG_SELF_COMP (ctx->self_comp)
#define BT_COMP_LOG_SELF_COMP_CLASS (ctx->self_comp_class)
-#define BT_LOG_OUTPUT_LEVEL (ctx->log_level)
+#define BT_LOG_OUTPUT_LEVEL ((enum bt_log_level) ctx->log_level)
#define BT_LOG_TAG "PLUGIN/CTF/META/RESOLVE"
#include "logging.hpp"
#include "logging/comp-logging.h"
#define BT_COMP_LOG_SELF_COMP (mdec->config.self_comp)
#define BT_COMP_LOG_SELF_COMP_CLASS (mdec->config.self_comp_class)
-#define BT_LOG_OUTPUT_LEVEL (mdec->config.log_level)
+#define BT_LOG_OUTPUT_LEVEL ((enum bt_log_level) mdec->config.log_level)
#define BT_LOG_TAG "PLUGIN/CTF/META/DECODER"
#include "logging.hpp"
#include "logging/comp-logging.h"
*/
#define BT_LOG_OUTPUT_LEVEL ctf_plugin_metadata_log_level
-#include "logging/log.h"
+#include "logging/log-api.h"
BT_LOG_INIT_LOG_LEVEL(ctf_plugin_metadata_log_level, "BABELTRACE_PLUGIN_CTF_METADATA_LOG_LEVEL");
#include <babeltrace2/babeltrace.h>
#define BT_COMP_LOG_SELF_COMP self_comp
-#define BT_LOG_OUTPUT_LEVEL log_level
+#define BT_LOG_OUTPUT_LEVEL ((enum bt_log_level) log_level)
#define BT_LOG_TAG "PLUGIN/SRC.CTF.FS"
#include "logging/comp-logging.h"
#include <babeltrace2/babeltrace.h>
-#define BT_LOG_OUTPUT_LEVEL log_level
+#define BT_LOG_OUTPUT_LEVEL ((enum bt_log_level) log_level)
#define BT_LOG_TAG "PLUGIN/SRC.CTF.FS/QUERY"
#include "logging/comp-logging.h"
#include "logging/log.h"
#include <babeltrace2/babeltrace.h>
#define BT_COMP_LOG_SELF_COMP (viewer_connection->self_comp)
-#define BT_LOG_OUTPUT_LEVEL (viewer_connection->log_level)
+#define BT_LOG_OUTPUT_LEVEL ((enum bt_log_level) viewer_connection->log_level)
#define BT_LOG_TAG "PLUGIN/SRC.CTF.LTTNG-LIVE/VIEWER"
#include "logging/comp-logging.h"
goto end;
}
- BT_LOG_WRITE(log_level, BT_LOG_TAG,
+ BT_LOG_WRITE_PRINTF(log_level, BT_LOG_TAG,
"Exception occurred: Python traceback:\n%s", exc->str);
}
* Copyright EfficiOS, Inc.
*/
-#define BT_LOG_OUTPUT_LEVEL log_level
+#define BT_LOG_OUTPUT_LEVEL ((enum bt_log_level) log_level)
#define BT_LOG_TAG "COMMON/FORMAT-ERROR"
#include <logging/log.h>
* Babeltrace SO info tests
*/
-#define BT_LOG_OUTPUT_LEVEL BT_LOG_WARNING
+#define BT_LOG_OUTPUT_LEVEL ((bt_logging_level) BT_LOG_WARNING)
#define BT_LOG_TAG "TEST/BIN-INFO"
#include "logging/log.h"