/* See LICENSE file for copyright and license details. */ #ifndef LIBLOG_H #define LIBLOG_H #include #include #include #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wformat-nonliteral" # pragma clang diagnostic ignored "-Wpadded" #elif defined(__GNUC__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wformat-nonliteral" #endif /** * Mark the message as incomplete an deferred * printing until LIBLOG_XLOG_UNCORK is used. */ #define LIBLOG_XLOG_CORK 0x0001 /** * Output message printed since the first * LIBLOG_XLOG_CORK (after the last * LIBLOG_XLOG_UNCORK if any) as one complete * message. */ #define LIBLOG_XLOG_UNCORK 0x0002 /** * Output a backtrace even if the it is not * configured that backtraces should be printed * for the selected log level. */ #define LIBLOG_XLOG_BACKTRACE 0x0004 /** * Do not output a backtrace even if the it is * configured that backtraces should be printed * for the selected log level. */ #define LIBLOG_XLOG_NO_BACKTRACE 0x0008 /** * Do not output any new text (apport from potential * backtrace); allowing `fmt` to be `NULL`. */ #define LIBLOG_XLOG_NO_TEXT 0x0010 /** * Opaque data type for the internal state * of a `struct liblog_context` */ struct liblog_context_internal_state; /** * Log levels */ enum liblog_level { /** * System is unusable */ LIBLOG_EMERGENCY = 0, /** * Action must be taken immediately */ LIBLOG_ALERT = 100, /** * Critical condition */ LIBLOG_CRITICAL = 200, /** * Error condition */ LIBLOG_ERROR = 300, /** * Warning condition */ LIBLOG_WARNING = 400, /** * Normal, but significant, condition */ LIBLOG_NOTICE = 500, /** * Informational message */ LIBLOG_INFO = 600, /** * Less verbose debug-level message: what is happening on a high level */ LIBLOG_TRACE = 700, /** * More verbose debug-level message: detailed information about what is going on */ LIBLOG_DEBUG = 800 }; /** * Log channel types */ enum liblog_sink { /** * Output to syslog */ LIBLOG_SYSLOG, /** * Output to a file descriptor */ LIBLOG_FILE, /** * Output to a `FILE` */ LIBLOG_STREAM }; /** * Log output configurations; mapping of log levels to log channels * * Destroy with `liblog_destroy_output` if destroying manually */ struct liblog_output { /** * User defined data * * This could for example be a path name to the output * file so that the application knows which file that * should be subject to rotation when online log rotation * is performed */ void *userdata; /** * The prefix for each log line * * A string where the following special symbols will be replaced * - %{ltime: %} span that marks formatting of the current local time with strftime(3) * - %{utime: %} span that marks formatting of the current UTC time with strftime(3) * - %[nano] the nanoseconds of the current time, printed with 9 digits * - %[micro] the microseconds of the current time, printed with 6 digits * - %[milli] the milliseconds of the current time, printed with 3 digits * - %[centi] the centiseconds of the current time, printed with 2 digits * - %[deci] the deciseconds of the current time, printed with 1 digit * - %[function] function where the log message is being printed from * - %[file] file where the log message is being printed from * - %[line] line in file where the log message is being printed from * - %[level] log level for the message rounded down to a predefined value * (printed as string) * - %[xlevel] the exact log level for the message, printed as the name of * of the log level rounded down to a predfined value, followed * by an adjustment * - %[tid] the process's thread ID * - %[pid] the process's thread group ID (process ID) * - %[ppid] the process's parent process ID * - %[pgid] the process's process group ID * - %[sid] the process's session ID * - %[uid] the real user ID of the process * - %[euid] the effective user ID of the process * - %[gid] the real group ID of the process * - %[egid] the effective group ID of the process * - %[name] the name of process * - %[argv0] the value of the global `const char *argv0` * - %% a literal % * * If `NULL`, this with be replace with a default format */ const char *prefixfmt; /** * If set `.lowest_verbosity` is treated as set to * the lowest possible value */ unsigned lowest_verbosity_unlimited : 1; /** * If set `.higest_verbosity` is treated as set to * the highest possible value */ unsigned highest_verbosity_unlimited : 1; /** * If set, each log message will be prefixed with * a backtrace */ unsigned use_backtrace : 1; unsigned : 0; /** * The lowest log level, in regards to verbosity * but higest in regard to criticality, for which * this log output channel shall be used * * Must not be greater than `.highest_verbosity` */ enum liblog_level lowest_verbosity; /** * The higest log level, in regards to verbosity * but lowest in regard to criticality, for which * this log output channel shall be used * * Must not be less than `.lowest_verbosity` */ enum liblog_level highest_verbosity; /** * The output channel type */ enum liblog_sink sink_type; /** * The output channel */ union { /** * Used when `.sink_type` is `LIBLOG_SYSLOG` * * The application is responsible for opening and closing syslog */ struct { /** * The syslog log level to use */ int level; } syslog; /** * Used when `.sink_type` is `LIBLOG_FILE` */ struct { /** * The file descriptor to write to */ int fd; /** * Whether the library shall close the file descriptor * when destroying the `struct liblog_output` object */ unsigned owns_fd : 1; } file; /** * Used when `.sink_type` is `LIBLOG_STREAM` */ struct { /** * The stream to write to */ FILE *stream; /** * Whether the library shall close the stream * when destroying the `struct liblog_output` object */ unsigned owns_stream : 1; } stream; } sink; }; /** * Logging configurations and state * * Initialise with `liblog_init_context`, and then * configure output using any of the follow functions: * - liblog_use_fd * - liblog_use_fd_for_range * - liblog_use_file * - liblog_use_file_for_range * - liblog_use_stderr * - liblog_use_stderr_for_range * - liblog_use_stream * - liblog_use_stream_for_range * - liblog_use_syslog * - liblog_use_syslog_for_range * - liblog_use_output * * Destroy with `liblog_destroy_context` */ struct liblog_context { /** * Opaque state */ struct liblog_context_internal_state *internal_state; /** * Log output configurations; mapping of log levels to log channels */ struct liblog_output *outputs; /** * Number of elements in noutputs */ size_t noutputs; /** * Mask of log level groups to exclude when logging */ unsigned logmask; }; /* TODO add multithreading support */ /* for internal use { */ #define LIBLOG_VA__(FUNC, ...)\ int ret;\ va_list args;\ va_start(args, fmt);\ ret = FUNC(__VA_ARGS__, args);\ va_end(args);\ return ret #define LIBLOG_OUTPUT_UNRANGED__(...)\ (&(struct liblog_output){\ .userdata = NULL,\ .prefixfmt = prefixfmt,\ .lowest_verbosity_unlimited = 1U,\ .highest_verbosity_unlimited = 1U,\ .use_backtrace = (use_backtrace ? 1U : 0U),\ __VA_ARGS__\ }) #define LIBLOG_OUTPUT_RANGED__(...)\ (&(struct liblog_output){\ .userdata = NULL,\ .prefixfmt = prefixfmt,\ .lowest_verbosity_unlimited = 0U,\ .highest_verbosity_unlimited = 0U,\ .use_backtrace = (use_backtrace ? 1U : 0U),\ .lowest_verbosity = least_verbose,\ .highest_verbosity = most_verbose,\ __VA_ARGS__\ }) #if defined(__clang__) # define LIBLOG_PRINTF__(FMTIDX) __attribute__((__format__(__printf__, (FMTIDX), (FMTIDX) + 1))) # define LIBLOG_VPRINTF__(FMTIDX) __attribute__((__format__(__printf__, (FMTIDX), 0))) #elif defined(__GNUC__) # define LIBLOG_PRINTF__(FMTIDX) __attribute__((__format__(__gnu_printf__, (FMTIDX), (FMTIDX) + 1))) # define LIBLOG_VPRINTF__(FMTIDX) __attribute__((__format__(__gnu_printf__, (FMTIDX), 0))) #else # define LIBLOG_PRINTF__(FMTIDX) # define LIBLOG_VPRINTF__(FMTIDX) #endif #if defined(__GNUC__) # define LIBLOG_CONST__ __attribute__((__const__)) #else # define LIBLOG_CONST__ #endif LIBLOG_CONST__ unsigned liblog_logmask__(enum liblog_level least_verbose, enum liblog_level most_verbose); /* } */ /** * Initialise a `struct liblog_context` * * @param ctx That object to initialise * @return 0 on success, -1 on failure */ int liblog_init_context(struct liblog_context *ctx); /** * Destroy a `struct liblog_context` * * @param ctx That object to destroy * @return 0 on success, -1 on failure (object will * still be completely destroyed) */ int liblog_destroy_context(struct liblog_context *ctx); /** * Destroy a `struct liblog_output` * * @param output That object to destroy * @return 0 on success, -1 on failure (object will * still be completely destroyed) */ int liblog_destroy_output(struct liblog_output *output); /** * Remove log level mask, causing all log messages, that * have an output configured, to be printed * * @param ctx Logging configurations and state */ inline void liblog_clear_mask(struct liblog_context *ctx) { if (ctx) ctx->logmask = 0U; } /** * Apply log level mask that is configured in the * process's environment variable "LIBLOG_LOGMASK" * * This is done automatically by `liblog_init_context` * * If the LIBLOG_LOGMASK environment variable is * unset or empty, anything more verbose than a * some specific level (currently `LIBLOG_WARNING`) * will be filtered. * * @param ctx Logging configurations and state */ void liblog_apply_env_mask(struct liblog_context *ctx); /** * Stop log messages within a certain range of * log levels from being printed * * @param ctx Logging configurations and state * @param least_verbose The lowest (least verbose, most critical) log level * to filter out; will be rounded up or down (unspecified * which) to the closest predefined log level value * @param most_verbose The highest (most verbose, least critical) log level * to filter out; will be rounded up or down (unspecified * which) to the closest predefined log level value * * This function has no effect if, after rounding, `least_verbose > most_verbose` */ inline void liblog_mask_range(struct liblog_context *ctx, enum liblog_level least_verbose, enum liblog_level most_verbose) { if (ctx) ctx->logmask |= liblog_logmask__(least_verbose, most_verbose); } /** * Stop log messages with a certain log level or * higher (more verbose, less critical) from being printed * * @param ctx Logging configurations and state * @param least The lowest (least verbose, most critical) log level to * filter out; will be rounded up or down (unspecified * which) to the closest predefined log level value */ inline void liblog_mask_verbose(struct liblog_context *ctx, enum liblog_level least) { liblog_mask_range(ctx, least, LIBLOG_DEBUG); } /** * Stop log messages with a certain log level group * (all levels up to but excluding the next predefined * log level) from being printed * * @param ctx Logging configurations and state * @param group The log level to filter out; will be rounded * up or down (unspecified which) to the closest * predefined log level value */ inline void liblog_mask_level(struct liblog_context *ctx, enum liblog_level group) { liblog_mask_range(ctx, group, group); } /** * Stop filtering out log messages within a certain * range of log levels from being printed * * @param ctx Logging configurations and state * @param least_verbose The lowest (least verbose, most critical) log level to * stop filtering out; will be rounded up or down (unspecified * which) to the closest predefined log level value * @param most_verbose The highest (most verbose, least critical) log level to * filtering out; will be rounded up or down (unspecified * which) to the closest predefined log level value * * This function has no effect if, after rounding, `least_verbose > most_verbose` */ inline void liblog_unmask_range(struct liblog_context *ctx, enum liblog_level least_verbose, enum liblog_level most_verbose) { if (ctx) ctx->logmask &= ~liblog_logmask__(least_verbose, most_verbose); } /** * Stop filtering out log messages with a certain log level or * higher (more verbose, less critical) from being printed * * @param ctx Logging configurations and state * @param least The lowest (least verbose, most critical) log level to * stop filtering out; will be rounded up or down (unspecified * which) to the closest predefined log level value */ inline void liblog_unmask_verbose(struct liblog_context *ctx, enum liblog_level least) { liblog_unmask_range(ctx, least, LIBLOG_DEBUG); } /** * Stop filtering out log messages with a certain log level * group (all levels up to but excluding the next predefined * log level) from being printed * * @param ctx Logging configurations and state * @param group The log level to stop filtering out; will be * rounded up or down (unspecified which) to the * closest predefined log level value */ inline void liblog_unmask_level(struct liblog_context *ctx, enum liblog_level group) { liblog_unmask_range(ctx, group, group); } /** * Add a log output * * @param ctx Logging configurations and state * @param output The configurations for the additional output * @return The new output configuration (this is an object * owned by `ctx` and should not be deallocated, * it is returned so that changes can be made) * on success, `NULL` on failure */ struct liblog_output *liblog_use_output(struct liblog_context *ctx, const struct liblog_output *output); /** * Set up logging with syslog(3) * * @param ctx Logging configurations and state * @param prefixfmt See `.prefixfmt` in `struct liblog_output` * @param use_backtrace Whether each log message should be prefix with a log backtrace * @return 0 on success, -1 on failure * * This function adds multi new output configurations to `ctx` */ int liblog_use_syslog(struct liblog_context *ctx, const char *prefixfmt, int use_backtrace); /** * Set up logging with syslog(3) * * @param ctx Logging configurations and state * @param syslog_level The syslog(3) log level that shall be used * @param prefixfmt See `.prefixfmt` in `struct liblog_output` * @param use_backtrace Whether each log message should be prefix with a log backtrace * @param least_verbose Lower (in regard to verbosity, upper in regards to criticality), * inclusive bound for the range liblog log level for which log * messages should be output to the new output * @param most_verbose Upper (in regard to verbosity, lower in regards to criticality), * inclusive bound for the range liblog log level for which log * messages should be output to the new output * @return The new output configuration (this is an object * owned by `ctx` and should not be deallocated, * it is returned so that changes can be made) * on success, `NULL` on failure */ inline struct liblog_output * liblog_use_syslog_for_range(struct liblog_context *ctx, int syslog_level, const char *prefixfmt, int use_backtrace, enum liblog_level least_verbose, enum liblog_level most_verbose) { return liblog_use_output(ctx, LIBLOG_OUTPUT_RANGED__(.sink_type = LIBLOG_SYSLOG, .sink.syslog = {syslog_level})); } /** * Set up logging to a file descriptor * * @param ctx Logging configurations and state * @param fd The file descriptor to log to * @param prefixfmt See `.prefixfmt` in `struct liblog_output` * @param use_backtrace Whether each log message should be prefix with a log backtrace * @return The new output configuration (this is an object * owned by `ctx` and should not be deallocated, * it is returned so that changes can be made) * on success, `NULL` on failure */ inline struct liblog_output * liblog_use_fd(struct liblog_context *ctx, int fd, const char *prefixfmt, int use_backtrace) { return liblog_use_output(ctx, LIBLOG_OUTPUT_UNRANGED__(.sink_type = LIBLOG_FILE, .sink.file = {fd, 0})); } /** * Set up logging to a file descriptor * * @param ctx Logging configurations and state * @param fd The file descriptor to log to * @param prefixfmt See `.prefixfmt` in `struct liblog_output` * @param use_backtrace Whether each log message should be prefix with a log backtrace * @param least_verbose Lower (in regard to verbosity, upper in regards to criticality), * inclusive bound for the range liblog log level for which log * messages should be output to the new output * @param most_verbose Upper (in regard to verbosity, lower in regards to criticality), * inclusive bound for the range liblog log level for which log * messages should be output to the new output * @return The new output configuration (this is an object * owned by `ctx` and should not be deallocated, * it is returned so that changes can be made) * on success, `NULL` on failure */ inline struct liblog_output * liblog_use_fd_for_range(struct liblog_context *ctx, int fd, const char *prefixfmt, int use_backtrace, enum liblog_level least_verbose, enum liblog_level most_verbose) { return liblog_use_output(ctx, LIBLOG_OUTPUT_RANGED__(.sink_type = LIBLOG_FILE, .sink.file = {fd, 0})); } /** * Set up logging to an output stream * * @param ctx Logging configurations and state * @param stream The stream to log to * @param prefixfmt See `.prefixfmt` in `struct liblog_output` * @param use_backtrace Whether each log message should be prefix with a log backtrace * @return The new output configuration (this is an object * owned by `ctx` and should not be deallocated, * it is returned so that changes can be made) * on success, `NULL` on failure */ inline struct liblog_output * liblog_use_stream(struct liblog_context *ctx, FILE *stream, const char *prefixfmt, int use_backtrace) { return liblog_use_output(ctx, LIBLOG_OUTPUT_UNRANGED__(.sink_type = LIBLOG_STREAM, .sink.stream = {stream, 0})); } /** * Set up logging to an output stream * * @param ctx Logging configurations and state * @param stream The stream to log to * @param prefixfmt See `.prefixfmt` in `struct liblog_output` * @param use_backtrace Whether each log message should be prefix with a log backtrace * @param least_verbose Lower (in regard to verbosity, upper in regards to criticality), * inclusive bound for the range liblog log level for which log * messages should be output to the new output * @param most_verbose Upper (in regard to verbosity, lower in regards to criticality), * inclusive bound for the range liblog log level for which log * messages should be output to the new output * @return The new output configuration (this is an object * owned by `ctx` and should not be deallocated, * it is returned so that changes can be made) * on success, `NULL` on failure */ inline struct liblog_output * liblog_use_stream_for_range(struct liblog_context *ctx, FILE *stream, const char *prefixfmt, int use_backtrace, enum liblog_level least_verbose, enum liblog_level most_verbose) { return liblog_use_output(ctx, LIBLOG_OUTPUT_RANGED__(.sink_type = LIBLOG_STREAM, .sink.stream = {stream, 0})); } /** * Set up logging to a file * * @param ctx Logging configurations and state * @param dirfd File descriptor to the directory `path` is relative to if * it is a relative path, or -1 to for the path to be absolute, * failing with EINVAL if it is relative); AT_FDCWD for the * current working directory * @param path The path of the file to write to, if `NULL` or `""` * dirfd will be used as the file descriptor to write to; * if the file exists, it is opened in append mode, otherwise * it is created to readable by every user but only writable * by the current user * @param prefixfmt See `.prefixfmt` in `struct liblog_output` * @param use_backtrace Whether each log message should be prefix with a log backtrace * @return The new output configuration (this is an object * owned by `ctx` and should not be deallocated, * it is returned so that changes can be made) * on success, `NULL` on failure */ struct liblog_output *liblog_use_file(struct liblog_context *ctx, int dirfd, const char *path, const char *prefixfmt, int use_backtrace); /** * Set up logging to a file * * @param ctx Logging configurations and state * @param dirfd File descriptor to the directory `path` is relative to if * it is a relative path, or -1 to for the path to be absolute, * failing with EINVAL if it is relative); AT_FDCWD for the * current working directory * @param path The path of the file to write to, if `NULL` or `""` * dirfd will be used as the file descriptor to write to; * if the file exists, it is opened in append mode, otherwise * it is created to readable by every user but only writable * by the current user * @param prefixfmt See `.prefixfmt` in `struct liblog_output` * @param use_backtrace Whether each log message should be prefix with a log backtrace * @param least_verbose Lower (in regard to verbosity, upper in regards to criticality), * inclusive bound for the range liblog log level for which log * messages should be output to the new output * @param most_verbose Upper (in regard to verbosity, lower in regards to criticality), * inclusive bound for the range liblog log level for which log * messages should be output to the new output * @return The new output configuration (this is an object * owned by `ctx` and should not be deallocated, * it is returned so that changes can be made) * on success, `NULL` on failure */ struct liblog_output *liblog_use_file_for_range(struct liblog_context *ctx, int dirfd, const char *path, const char *prefixfmt, int use_backtrace, enum liblog_level least_verbose, enum liblog_level most_verbose); /** * Set up logging to the standard output * * @param ctx Logging configurations and state * @param prefixfmt See `.prefixfmt` in `struct liblog_output` * @param use_backtrace Whether each log message should be prefix with a log backtrace * @return The new output configuration (this is an object * owned by `ctx` and should not be deallocated, * it is returned so that changes can be made) * on success, `NULL` on failure */ inline struct liblog_output * liblog_use_stderr(struct liblog_context *ctx, const char *prefixfmt, int use_backtrace) { return liblog_use_fd(ctx, 2, prefixfmt, use_backtrace); } /** * Set up logging to the standard output * * @param ctx Logging configurations and state * @param prefixfmt See `.prefixfmt` in `struct liblog_output` * @param use_backtrace Whether each log message should be prefix with a log backtrace * @param least_verbose Lower (in regard to verbosity, upper in regards to criticality), * inclusive bound for the range liblog log level for which log * messages should be output to the new output * @param most_verbose Upper (in regard to verbosity, lower in regards to criticality), * inclusive bound for the range liblog log level for which log * messages should be output to the new output * @return The new output configuration (this is an object * owned by `ctx` and should not be deallocated, * it is returned so that changes can be made) * on success, `NULL` on failure */ inline struct liblog_output * liblog_use_stderr_for_range(struct liblog_context *ctx, const char *prefixfmt, int use_backtrace, enum liblog_level least_verbose, enum liblog_level most_verbose) { return liblog_use_fd_for_range(ctx, 2, prefixfmt, use_backtrace, least_verbose, most_verbose); } /** * Write a log message with a custom log level * * This function's behaviour is customisable * using its `flags` parameter * * @param ctx Logging configurations and state * @param level The log level for the message; does not have to * be predefined in `enum liblog_level` * @param flags Modifications the the function's behaviour; * may be 0 or the OR of any of the following values: * - LIBLOG_XLOG_CORK: * Mark the message as incomplete an deferred * printing until LIBLOG_XLOG_UNCORK is used * - LIBLOG_XLOG_UNCORK: * Output message printed since the first * LIBLOG_XLOG_CORK (after the last * LIBLOG_XLOG_UNCORK if any) as one complete * message * - LIBLOG_XLOG_BACKTRACE: * Output a backtrace even if the it is not * configured that backtraces should be printed * for the selected log level * - LIBLOG_XLOG_NO_BACKTRACE: * Do not output a backtrace even if the it is * configured that backtraces should be printed * for the selected log level * - LIBLOG_XLOG_NO_TEXT: * Do not output any new text (apport from potential * backtrace); allowing `fmt` to be `NULL` * However, LIBLOG_XLOG_CORK and LIBLOG_XLOG_UNCORK * cannot be combined, nor can LIBLOG_XLOG_BACKTRACE * and LIBLOG_XLOG_NO_BACKTRACE be combined * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(4) int liblog_vxlog(struct liblog_context *ctx, enum liblog_level level, unsigned flags, const char *fmt, va_list args); /** * Write a log message with a custom log level * * This function's behaviour is customisable * using its `flags` parameter * * @param ctx Logging configurations and state * @param level The log level for the message; does not have to * be predefined in `enum liblog_level` * @param flags Modifications the the function's behaviour; * may be 0 or the OR of any of the following values: * - LIBLOG_XLOG_CORK: * Mark the message as incomplete an deferred * printing until LIBLOG_XLOG_UNCORK is used * - LIBLOG_XLOG_UNCORK: * Output message printed since the first * LIBLOG_XLOG_CORK (after the last * LIBLOG_XLOG_UNCORK if any) as one complete * message * - LIBLOG_XLOG_BACKTRACE: * Output a backtrace even if the it is not * configured that backtraces should be printed * for the selected log level * - LIBLOG_XLOG_NO_BACKTRACE: * Do not output a backtrace even if the it is * configured that backtraces should be printed * for the selected log level * - LIBLOG_XLOG_NO_TEXT: * Do not output any new text (apport from potential * backtrace); allowing `fmt` to be `NULL`. * However, LIBLOG_XLOG_CORK and LIBLOG_XLOG_UNCORK * cannot be combined, nor can LIBLOG_XLOG_BACKTRACE * and LIBLOG_XLOG_NO_BACKTRACE be combined * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(4) inline int liblog_xlog(struct liblog_context *ctx, enum liblog_level level, unsigned flags, const char *fmt, ...) { LIBLOG_VA__(liblog_vxlog, ctx, level, flags, fmt); } /** * If there is an incomplete log message being constructed, * terminate it and print it * * @param ctx Logging configurations and state * @return 0 on success, -1 on failure * * @seealso liblog_xlog * @seealso liblog_dump_backtrace_cork * @seealso liblog_log_cork * @seealso liblog_log_no_backtrace_cork * @seealso liblog_emergency_cork * @seealso liblog_alert_cork * @seealso liblog_critical_cork * @seealso liblog_error_cork * @seealso liblog_warning_cork * @seealso liblog_notice_cork * @seealso liblog_info_cork * @seealso liblog_trace_cork * @seealso liblog_debug_cork */ inline int liblog_uncork(struct liblog_context *ctx) { return liblog_xlog(ctx, 0, LIBLOG_XLOG_NO_BACKTRACE | LIBLOG_XLOG_NO_TEXT | LIBLOG_XLOG_UNCORK, NULL); } /** * Write the backtrace as a log message with a custom log level * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param level The log level for the message; does not have to * be predefined in `enum liblog_level` * @return 0 on success, -1 on failure */ inline int liblog_dump_backtrace(struct liblog_context *ctx, enum liblog_level level) { return liblog_xlog(ctx, level, LIBLOG_XLOG_BACKTRACE | LIBLOG_XLOG_NO_TEXT, NULL); } /** * Write the backtrace as a log message with a custom log level * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * The backtrace will be terminated by a new line * * @param ctx Logging configurations and state * @param level The log level for the message; does not have to * be predefined in `enum liblog_level` * @return 0 on success, -1 on failure */ inline int liblog_dump_backtrace_cork(struct liblog_context *ctx, enum liblog_level level) { return liblog_xlog(ctx, level, LIBLOG_XLOG_BACKTRACE | LIBLOG_XLOG_NO_TEXT | LIBLOG_XLOG_CORK, NULL); } /** * Write a log message with a custom log level * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param level The log level for the message; does not have to * be predefined in `enum liblog_level` * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(3) inline int liblog_vlog(struct liblog_context *ctx, enum liblog_level level, const char *fmt, va_list args) { return liblog_xlog(ctx, level, 0, fmt, args); } /** * Write a log message with a custom log level * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param level The log level for the message; does not have to * be predefined in `enum liblog_level` * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(3) inline int liblog_log(struct liblog_context *ctx, enum liblog_level level, const char *fmt, ...) { LIBLOG_VA__(liblog_vlog, ctx, level, fmt); } /** * Write a log message with a custom log level * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param level The log level for the message; does not have to * be predefined in `enum liblog_level` * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(3) inline int liblog_vlog_cork(struct liblog_context *ctx, enum liblog_level level, const char *fmt, va_list args) { return liblog_xlog(ctx, level, LIBLOG_XLOG_CORK, fmt, args); } /** * Write a log message with a custom log level * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param level The log level for the message; does not have to * be predefined in `enum liblog_level` * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(3) inline int liblog_log_cork(struct liblog_context *ctx, enum liblog_level level, const char *fmt, ...) { LIBLOG_VA__(liblog_vlog_cork, ctx, level, fmt); } /** * Write a log message with a custom log level * * Even if configured that backtraces should be printed for the * the specificed log level, no backtrace will be printed * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param level The log level for the message; does not have to * be predefined in `enum liblog_level` * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(3) inline int liblog_vlog_no_backtrace(struct liblog_context *ctx, enum liblog_level level, const char *fmt, va_list args) { return liblog_xlog(ctx, level, LIBLOG_XLOG_NO_BACKTRACE, fmt, args); } /** * Write a log message with a custom log level * * Even if configured that backtraces should be printed for the * the specificed log level, no backtrace will be printed * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param level The log level for the message; does not have to * be predefined in `enum liblog_level` * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(3) inline int liblog_log_no_backtrace(struct liblog_context *ctx, enum liblog_level level, const char *fmt, ...) { LIBLOG_VA__(liblog_vlog_no_backtrace, ctx, level, fmt); } /** * Write a log message with a custom log level * * Even if configured that backtraces should be printed for the * the specificed log level, no backtrace will be printed * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param level The log level for the message; does not have to * be predefined in `enum liblog_level` * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(3) inline int liblog_vlog_no_backtrace_cork(struct liblog_context *ctx, enum liblog_level level, const char *fmt, va_list args) { return liblog_xlog(ctx, level, LIBLOG_XLOG_NO_BACKTRACE | LIBLOG_XLOG_CORK, fmt, args); } /** * Write a log message with a custom log level * * Even if configured that backtraces should be printed for the * the specificed log level, no backtrace will be printed * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param level The log level for the message; does not have to * be predefined in `enum liblog_level` * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(3) inline int liblog_log_no_backtrace_cork(struct liblog_context *ctx, enum liblog_level level, const char *fmt, ...) { LIBLOG_VA__(liblog_vlog_no_backtrace_cork, ctx, level, fmt); } /* Everything from this point onwards is just for convenience */ /** * Write a log message with log level `LIBLOG_EMERGENCY` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_vemergency(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog(ctx, LIBLOG_EMERGENCY, fmt, args); } /** * Write a log message with log level `LIBLOG_EMERGENCY` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_emergency(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_vemergency, ctx, fmt); } /** * Write a log message with log level `LIBLOG_EMERGENCY` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_vemergency_cork(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog_cork(ctx, LIBLOG_EMERGENCY, fmt, args); } /** * Write a log message with log level `LIBLOG_EMERGENCY` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_emergency_cork(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_vemergency_cork, ctx, fmt); } /** * Write a log message with log level `LIBLOG_ALERT` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_valert(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog(ctx, LIBLOG_ALERT, fmt, args); } /** * Write a log message with log level `LIBLOG_ALERT` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_alert(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_valert, ctx, fmt); } /** * Write a log message with log level `LIBLOG_ALERT` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_valert_cork(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog_cork(ctx, LIBLOG_ALERT, fmt, args); } /** * Write a log message with log level `LIBLOG_ALERT` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_alert_cork(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_valert_cork, ctx, fmt); } /** * Write a log message with log level `LIBLOG_CRITICAL` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_vcritical(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog(ctx, LIBLOG_CRITICAL, fmt, args); } /** * Write a log message with log level `LIBLOG_CRITICAL` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_critical(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_vcritical, ctx, fmt); } /** * Write a log message with log level `LIBLOG_CRITICAL` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_vcritical_cork(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog_cork(ctx, LIBLOG_CRITICAL, fmt, args); } /** * Write a log message with log level `LIBLOG_CRITICAL` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_critical_cork(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_vcritical_cork, ctx, fmt); } /** * Write a log message with log level `LIBLOG_ERROR` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_verror(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog(ctx, LIBLOG_ERROR, fmt, args); } /** * Write a log message with log level `LIBLOG_ERROR` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_error(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_verror, ctx, fmt); } /** * Write a log message with log level `LIBLOG_ERROR` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_verror_cork(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog_cork(ctx, LIBLOG_ERROR, fmt, args); } /** * Write a log message with log level `LIBLOG_ERROR` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_error_cork(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_verror_cork, ctx, fmt); } /** * Write a log message with log level `LIBLOG_WARNING` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_vwarning(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog(ctx, LIBLOG_WARNING, fmt, args); } /** * Write a log message with log level `LIBLOG_WARNING` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_warning(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_vwarning, ctx, fmt); } /** * Write a log message with log level `LIBLOG_WARNING` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_vwarning_cork(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog_cork(ctx, LIBLOG_WARNING, fmt, args); } /** * Write a log message with log level `LIBLOG_WARNING` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_warning_cork(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_vwarning_cork, ctx, fmt); } /** * Write a log message with log level `LIBLOG_NOTICE` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_vnotice(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog(ctx, LIBLOG_NOTICE, fmt, args); } /** * Write a log message with log level `LIBLOG_NOTICE` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_notice(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_vnotice, ctx, fmt); } /** * Write a log message with log level `LIBLOG_NOTICE` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_vnotice_cork(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog_cork(ctx, LIBLOG_NOTICE, fmt, args); } /** * Write a log message with log level `LIBLOG_NOTICE` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_notice_cork(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_vnotice_cork, ctx, fmt); } /** * Write a log message with log level `LIBLOG_INFO` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_vinfo(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog(ctx, LIBLOG_INFO, fmt, args); } /** * Write a log message with log level `LIBLOG_INFO` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_info(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_vinfo, ctx, fmt); } /** * Write a log message with log level `LIBLOG_INFO` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_vinfo_cork(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog_cork(ctx, LIBLOG_INFO, fmt, args); } /** * Write a log message with log level `LIBLOG_INFO` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_info_cork(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_vinfo_cork, ctx, fmt); } /** * Write a log message with log level `LIBLOG_TRACE` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_vtrace(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog(ctx, LIBLOG_TRACE, fmt, args); } /** * Write a log message with log level `LIBLOG_TRACE` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_trace(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_vtrace, ctx, fmt); } /** * Write a log message with log level `LIBLOG_TRACE` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_vtrace_cork(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog_cork(ctx, LIBLOG_TRACE, fmt, args); } /** * Write a log message with log level `LIBLOG_TRACE` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_trace_cork(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_vtrace_cork, ctx, fmt); } /** * Write a log message with log level `LIBLOG_DEBUG` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_vdebug(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog(ctx, LIBLOG_DEBUG, fmt, args); } /** * Write a log message with log level `LIBLOG_DEBUG` * * The log message is printed immediately as one complete log message * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_debug(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_vdebug, ctx, fmt); } /** * Write a log message with log level `LIBLOG_DEBUG` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param args Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_VPRINTF__(2) inline int liblog_vdebug_cork(struct liblog_context *ctx, const char *fmt, va_list args) { return liblog_vlog_cork(ctx, LIBLOG_DEBUG, fmt, args); } /** * Write a log message with log level `LIBLOG_DEBUG` * * The log message is treated as incomplete, and can be extended using * any log message writing function using the same `ctx`, and will be * printed once `liblog_uncork` is called using the same `ctx` * * @param ctx Logging configurations and state * @param fmt printf(3) format string for the log message * @param ... Arguments for `fmt` * @return 0 on success, -1 on failure */ LIBLOG_PRINTF__(2) inline int liblog_debug_cork(struct liblog_context *ctx, const char *fmt, ...) { LIBLOG_VA__(liblog_vdebug_cork, ctx, fmt); } #if defined(__clang__) # pragma clang diagnostic pop #elif defined(__GNUC__) # pragma GCC diagnostic pop #endif #endif