diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | src/context.c | 149 | ||||
-rw-r--r-- | src/utils.c | 154 | ||||
-rw-r--r-- | src/utils.h | 37 | ||||
-rw-r--r-- | src/xkb-priv.h | 30 | ||||
-rw-r--r-- | xkbcommon/xkbcommon.h | 71 |
6 files changed, 255 insertions, 187 deletions
diff --git a/Makefile.am b/Makefile.am index ca715fe..02c0f57 100644 --- a/Makefile.am +++ b/Makefile.am @@ -75,7 +75,6 @@ libxkbcommon_la_SOURCES = \ src/state.c \ src/text.c \ src/text.h \ - src/utils.c \ src/utils.h \ src/xkb-priv.h diff --git a/src/context.c b/src/context.c index a0bb9a9..18a8222 100644 --- a/src/context.c +++ b/src/context.c @@ -25,8 +25,12 @@ #include <sys/types.h> #include <sys/stat.h> +#include <ctype.h> +#include <errno.h> +#include <stdarg.h> #include <stdio.h> #include <unistd.h> +#include <syslog.h> #include "xkb-priv.h" #include "atom.h" @@ -34,6 +38,12 @@ struct xkb_context { int refcnt; + ATTR_PRINTF(3, 0) void (*log_fn)(struct xkb_context *ctx, int priority, + const char *fmt, va_list args); + int log_priority; + int log_verbosity; + void *user_data; + darray(char *) includes; /* xkbcomp needs to assign sequential IDs to XkbFile's it creates. */ @@ -175,18 +185,97 @@ xkb_context_unref(struct xkb_context *ctx) free(ctx); } +static const char * +priority_to_prefix(int priority) +{ + switch (priority) { + case LOG_DEBUG: + return "Debug:"; + case LOG_INFO: + return "Info:"; + case LOG_WARNING: + return "Warning:"; + case LOG_ERR: + return "Error:"; + case LOG_CRIT: + case LOG_ALERT: + case LOG_EMERG: + return "Internal error:"; + default: + return ""; + } +} + +ATTR_PRINTF(3, 0) static void +default_log_fn(struct xkb_context *ctx, int priority, + const char *fmt, va_list args) +{ + const char *prefix = priority_to_prefix(priority); + + if (prefix) + fprintf(stderr, "%-15s", prefix); + vfprintf(stderr, fmt, args); +} + +static int +log_priority(const char *priority) { + char *endptr; + int prio; + + errno = 0; + prio = strtol(priority, &endptr, 10); + if (errno == 0 && (endptr[0] == '\0' || isspace(endptr[0]))) + return prio; + if (strncasecmp(priority, "err", 3) == 0) + return LOG_ERR; + if (strncasecmp(priority, "warn", 4) == 0) + return LOG_WARNING; + if (strncasecmp(priority, "info", 4) == 0) + return LOG_INFO; + if (strncasecmp(priority, "debug", 5) == 0) + return LOG_DEBUG; + + return LOG_ERR; +} + +static int +log_verbosity(const char *verbosity) { + char *endptr; + int v; + + errno = 0; + v = strtol(verbosity, &endptr, 10); + if (errno == 0) + return v; + + return 0; +} + /** * Create a new context. */ XKB_EXPORT struct xkb_context * xkb_context_new(enum xkb_context_flags flags) { + const char *env; struct xkb_context *ctx = calloc(1, sizeof(*ctx)); if (!ctx) return NULL; ctx->refcnt = 1; + ctx->log_fn = default_log_fn; + ctx->log_priority = LOG_ERR; + ctx->log_verbosity = 0; + + /* Environment overwrites defaults. */ + env = getenv("XKB_LOG"); + if (env) + xkb_set_log_priority(ctx, log_priority(env)); + + env = getenv("XKB_VERBOSITY"); + if (env) + xkb_set_log_verbosity(ctx, log_verbosity(env)); if (!(flags & XKB_CONTEXT_NO_DEFAULT_INCLUDES) && !xkb_context_include_path_append_default(ctx)) { @@ -220,3 +309,63 @@ xkb_atom_text(struct xkb_context *ctx, xkb_atom_t atom) { return atom_text(ctx->atom_table, atom); } + +void +xkb_log(struct xkb_context *ctx, int priority, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + /* NOTE: This test will be removed in a few commits. */ + if (ctx) + ctx->log_fn(ctx, priority, fmt, args); + else + default_log_fn(ctx, priority, fmt, args); + va_end(args); +} + +XKB_EXPORT void +xkb_set_log_fn(struct xkb_context *ctx, + void (*log_fn)(struct xkb_context *ctx, int priority, + const char *fmt, va_list args)) +{ + ctx->log_fn = log_fn; +} + +XKB_EXPORT int +xkb_get_log_priority(struct xkb_context *ctx) +{ + return ctx->log_priority; +} + +XKB_EXPORT void +xkb_set_log_priority(struct xkb_context *ctx, int priority) +{ + ctx->log_priority = priority; +} + +XKB_EXPORT int +xkb_get_log_verbosity(struct xkb_context *ctx) +{ + return ctx->log_verbosity; +} + +XKB_EXPORT void +xkb_set_log_verbosity(struct xkb_context *ctx, int verbosity) +{ + ctx->log_verbosity = verbosity; +} + +XKB_EXPORT void * +xkb_get_user_data(struct xkb_context *ctx) +{ + if (ctx) + return ctx->user_data; + return NULL; +} + +XKB_EXPORT void +xkb_set_user_data(struct xkb_context *ctx, void *user_data) +{ + ctx->user_data = user_data; +} diff --git a/src/utils.c b/src/utils.c deleted file mode 100644 index d1f79bb..0000000 --- a/src/utils.c +++ /dev/null @@ -1,154 +0,0 @@ -/*\ - * - * COPYRIGHT 1990 - * DIGITAL EQUIPMENT CORPORATION - * MAYNARD, MASSACHUSETTS - * ALL RIGHTS RESERVED. - * - * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND - * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. - * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE - * FOR ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED - * WARRANTY. - * - * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT - * RIGHTS, APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN - * ADDITION TO THAT SET FORTH ABOVE. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted, provided - * that the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Digital Equipment Corporation not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. - \*/ - -#include <ctype.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> - -#include "utils.h" - -static FILE *errorFile = NULL; -static int outCount = 0; -static char *preMsg = NULL; -static char *prefix = NULL; - -bool -uSetErrorFile(char *name) -{ - if ((errorFile != NULL) && (errorFile != stderr)) { - fprintf(errorFile, "switching to %s\n", name ? name : "stderr"); - fclose(errorFile); - } - if (name != NULL) - errorFile = fopen(name, "w"); - else - errorFile = stderr; - if (errorFile == NULL) { - errorFile = stderr; - return false; - } - return true; -} - -void -uInformation(const char *s, ...) -{ - va_list args; - - if (!errorFile) - errorFile = stderr; - - va_start(args, s); - vfprintf(errorFile, s, args); - va_end(args); - fflush(errorFile); -} - -/***====================================================================***/ - -void -uAction(const char *s, ...) -{ - va_list args; - - if (!errorFile) - errorFile = stderr; - - if (prefix != NULL) - fprintf(errorFile, "%s", prefix); - fprintf(errorFile, " "); - va_start(args, s); - vfprintf(errorFile, s, args); - va_end(args); - fflush(errorFile); -} - -/***====================================================================***/ - -void -uWarning(const char *s, ...) -{ - va_list args; - - if (!errorFile) - errorFile = stderr; - - if ((outCount == 0) && (preMsg != NULL)) - fprintf(errorFile, "%s\n", preMsg); - if (prefix != NULL) - fprintf(errorFile, "%s", prefix); - fprintf(errorFile, "Warning: "); - va_start(args, s); - vfprintf(errorFile, s, args); - va_end(args); - fflush(errorFile); - outCount++; -} - -/***====================================================================***/ - -void -uError(const char *s, ...) -{ - va_list args; - - if (!errorFile) - errorFile = stderr; - - if ((outCount == 0) && (preMsg != NULL)) - fprintf(errorFile, "%s\n", preMsg); - if (prefix != NULL) - fprintf(errorFile, "%s", prefix); - fprintf(errorFile, "Error: "); - va_start(args, s); - vfprintf(errorFile, s, args); - va_end(args); - fflush(errorFile); - outCount++; -} - -/***====================================================================***/ - -void -uInternalError(const char *s, ...) -{ - va_list args; - - if (!errorFile) - errorFile = stderr; - - if ((outCount == 0) && (preMsg != NULL)) - fprintf(errorFile, "%s\n", preMsg); - if (prefix != NULL) - fprintf(errorFile, "%s", prefix); - fprintf(errorFile, "Internal error: "); - va_start(args, s); - vfprintf(errorFile, s, args); - va_end(args); - fflush(errorFile); - outCount++; -} diff --git a/src/utils.h b/src/utils.h index 4ea703a..7d4e612 100644 --- a/src/utils.h +++ b/src/utils.h @@ -29,10 +29,6 @@ /***====================================================================***/ -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> - /* * We sometimes malloc strings and then expose them as const char*'s. This * macro is used when we free these strings in order to avoid -Wcast-qual @@ -73,33 +69,10 @@ #define ATTR_MALLOC #endif -extern bool -uSetErrorFile(char *name); - -#define INFO uInformation - -ATTR_PRINTF(1, 2) void -uInformation(const char *s, ...); - -#define ACTION uAction - -ATTR_PRINTF(1, 2) void -uAction(const char *s, ...); - -#define WARN uWarning - -ATTR_PRINTF(1, 2) void -uWarning(const char *s, ...); - -#define ERROR uError - -ATTR_PRINTF(1, 2) void -uError(const char *s, ...); - -/* WSGO stands for "Weird Stuff Going On" (wtf???) */ -#define WSGO uInternalError - -ATTR_PRINTF(1, 2) void -uInternalError(const char *s, ...); +#define INFO(...) xkb_log(NULL, LOG_INFO, __VA_ARGS__) +#define WARN(...) xkb_log(NULL, LOG_WARNING, __VA_ARGS__) +#define ERROR(...) xkb_log(NULL, LOG_ERR, __VA_ARGS__) +#define WSGO(...) xkb_log(NULL, LOG_CRIT, __VA_ARGS__) +#define ACTION(...) xkb_log(NULL, -1, __VA_ARGS__) #endif /* UTILS_H */ diff --git a/src/xkb-priv.h b/src/xkb-priv.h index 55a89f2..d1b135d 100644 --- a/src/xkb-priv.h +++ b/src/xkb-priv.h @@ -82,6 +82,7 @@ #include <stdbool.h> #include <string.h> #include <strings.h> +#include <syslog.h> #include <X11/extensions/XKB.h> #include <X11/X.h> @@ -518,4 +519,33 @@ xkb_keysym_is_upper(xkb_keysym_t keysym); bool xkb_keysym_is_keypad(xkb_keysym_t keysym); +ATTR_PRINTF(3, 4) void +xkb_log(struct xkb_context *ctx, int priority, const char *fmt, ...); + +#define xkb_log_cond(ctx, prio, ...) \ + do { \ + if (xkb_get_log_priority(ctx) >= (prio)) \ + xkb_log((ctx), (prio), __VA_ARGS__); \ + } while (0) + +#define xkb_log_cond_lvl(ctx, prio, lvl, ...) \ + do { \ + if (xkb_get_log_verbosity(ctx) >= (lvl)) \ + xkb_log_cond((ctx), (prio), __VA_ARGS__); \ + } while (0) + +/* + * The format is not part of the argument list in order to avoid the + * "ISO C99 requires rest arguments to be used" warning when only the + * format is supplied without arguments. Not supplying it would still + * result in an error, though. + */ +#define log_dbg(ctx, ...) xkb_log_cond((ctx), LOG_DEBUG, __VA_ARGS__) +#define log_info(ctx, ...) xkb_log_cond((ctx), LOG_INFO, __VA_ARGS__) +#define log_warn(ctx, ...) xkb_log_cond((ctx), LOG_WARNING, __VA_ARGS__) +#define log_err(ctx, ...) xkb_log_cond((ctx), LOG_ERR, __VA_ARGS__) +#define log_wsgo(ctx, ...) xkb_log_cond((ctx), LOG_CRIT, __VA_ARGS__) +#define log_lvl(ctx, lvl, ...) \ + xkb_log_cond_lvl((ctx), LOG_WARNING, (lvl), __VA_ARGS__) + #endif /* XKB_PRIV_H */ diff --git a/xkbcommon/xkbcommon.h b/xkbcommon/xkbcommon.h index 42f70ad..8c772ae 100644 --- a/xkbcommon/xkbcommon.h +++ b/xkbcommon/xkbcommon.h @@ -249,6 +249,77 @@ xkb_context_unref(struct xkb_context *context); /** @} */ /** + * @defgroup logging Logging handling + * These functions allow you to manipulate how logging from this library + * will be handled. + * + * @{ + */ + +/** + * Sets the function to be called for logging messages, instead of the + * default logger which writes to stderr. + **/ +void +xkb_set_log_fn(struct xkb_context *context, + void (*log_fn)(struct xkb_context *context, int priority, + const char *format, va_list args)); +/** + * Sets the current logging priority. The value controls which messages + * are logged. + * + * The value should be one of LOG_ERR, LOG_WARNING, LOG_DEBUG, etc., see + * syslog(3) or syslog.h. The default priority is LOG_ERR. + * The environment variable XKB_LOG, if set, overrides the default value + * and may be specified as a priority number or name. + */ +void +xkb_set_log_priority(struct xkb_context *context, int priority); + +/** + * Returns the current logging priority. + */ +int +xkb_get_log_priority(struct xkb_context *context); + +/** + * Sets the current logging verbosity, a value from 0 to 10. + * + * The library can generate a number of warnings which are not helpful to + * ordinary users of the library. The verbosity may be increased if more + * information is desired (e.g. when developing a keymap). Defaults to 0. + * The environment variable XKB_VERBOSITY, if set, overrdies the default + * value. + * + * Note that most verbose messages are of priority LOG_WARNING or lower. + */ +void +xkb_set_log_verbosity(struct xkb_context *ctx, int verbosity); + +/** + * Returns the current logging verbosity. + */ +int +xkb_get_log_verbosity(struct xkb_context *ctx); + +/** + * Retrieves stored data pointer from the context. This might be useful + * to access from callbacks like a custom logging function. + * + * If context is NULL, returns NULL. + **/ +void * +xkb_get_user_data(struct xkb_context *context); + +/** + * Store custom user data in the context. + */ +void +xkb_set_user_data(struct xkb_context *context, void *user_data); + +/** @} */ + +/** * @defgroup map Keymap management * These utility functions allow you to create and deallocate XKB keymaps. * |