X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fcontext.c;h=b8b214bcda86d75d1c72b1b1c38d5da44e9b2261;hb=ef81d04eef4b1a60ff42bd9ccbe2918b0a5420ec;hp=a0bb9a9e478fc09b5a4da4a3bc3836f5ec8634e2;hpb=58f8d2c151d95bb920d346dcae3e6c429789f257;p=platform%2Fupstream%2Flibxkbcommon.git diff --git a/src/context.c b/src/context.c index a0bb9a9..b8b214b 100644 --- a/src/context.c +++ b/src/context.c @@ -1,5 +1,6 @@ /* * Copyright © 2012 Intel Corporation + * Copyright © 2012 Ran Benita * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,24 +24,16 @@ * Author: Daniel Stone */ +#include "config.h" + #include #include -#include -#include - -#include "xkb-priv.h" -#include "atom.h" - -struct xkb_context { - int refcnt; +#include - darray(char *) includes; +#include "xkbcommon/xkbcommon.h" +#include "utils.h" +#include "context.h" - /* xkbcomp needs to assign sequential IDs to XkbFile's it creates. */ - unsigned file_id; - - struct atom_table *atom_table; -}; /** * Append one directory to the context's include path. @@ -49,29 +42,51 @@ XKB_EXPORT int xkb_context_include_path_append(struct xkb_context *ctx, const char *path) { struct stat stat_buf; - int err; + int err = ENOMEM; char *tmp; - err = stat(path, &stat_buf); - if (err != 0) - return 0; - if (!S_ISDIR(stat_buf.st_mode)) - return 0; - -#if defined(HAVE_EACCESS) - if (eaccess(path, R_OK | X_OK) != 0) - return 0; -#elif defined(HAVE_EUIDACCESS) - if (euidaccess(path, R_OK | X_OK) != 0) - return 0; -#endif - tmp = strdup(path); if (!tmp) - return 0; + goto err; + + err = stat(path, &stat_buf); + if (err != 0) { + err = errno; + goto err; + } + if (!S_ISDIR(stat_buf.st_mode)) { + err = ENOTDIR; + goto err; + } + + if (!check_eaccess(path, R_OK | X_OK)) { + err = EACCES; + goto err; + } darray_append(ctx->includes, tmp); + log_dbg(ctx, "Include path added: %s\n", tmp); + return 1; + +err: + darray_append(ctx->failed_includes, tmp); + log_dbg(ctx, "Include path failed: %s (%s)\n", tmp, strerror(err)); + return 0; +} + +const char * +xkb_context_include_path_get_extra_path(struct xkb_context *ctx) +{ + const char *extra = xkb_context_getenv(ctx, "XKB_CONFIG_EXTRA_PATH"); + return extra ? extra : DFLT_XKB_CONFIG_EXTRA_PATH; +} + +const char * +xkb_context_include_path_get_system_path(struct xkb_context *ctx) +{ + const char *root = xkb_context_getenv(ctx, "XKB_CONFIG_ROOT"); + return root ? root : DFLT_XKB_CONFIG_ROOT; } /** @@ -80,22 +95,42 @@ xkb_context_include_path_append(struct xkb_context *ctx, const char *path) XKB_EXPORT int xkb_context_include_path_append_default(struct xkb_context *ctx) { - const char *home; + const char *home, *xdg, *root, *extra; char *user_path; - int err; + int ret = 0; + + home = xkb_context_getenv(ctx, "HOME"); + + xdg = xkb_context_getenv(ctx, "XDG_CONFIG_HOME"); + if (xdg != NULL) { + user_path = asprintf_safe("%s/xkb", xdg); + if (user_path) { + ret |= xkb_context_include_path_append(ctx, user_path); + free(user_path); + } + } else if (home != NULL) { + /* XDG_CONFIG_HOME fallback is $HOME/.config/ */ + user_path = asprintf_safe("%s/.config/xkb", home); + if (user_path) { + ret |= xkb_context_include_path_append(ctx, user_path); + free(user_path); + } + } - (void) xkb_context_include_path_append(ctx, DFLT_XKB_CONFIG_ROOT); + if (home != NULL) { + user_path = asprintf_safe("%s/.xkb", home); + if (user_path) { + ret |= xkb_context_include_path_append(ctx, user_path); + free(user_path); + } + } - home = getenv("HOME"); - if (!home) - return 1; - err = asprintf(&user_path, "%s/.xkb", home); - if (err <= 0) - return 1; - (void) xkb_context_include_path_append(ctx, user_path); - free(user_path); + extra = xkb_context_include_path_get_extra_path(ctx); + ret |= xkb_context_include_path_append(ctx, extra); + root = xkb_context_include_path_get_system_path(ctx); + ret |= xkb_context_include_path_append(ctx, root); - return 1; + return ret; } /** @@ -107,9 +142,12 @@ xkb_context_include_path_clear(struct xkb_context *ctx) char **path; darray_foreach(path, ctx->includes) - free(*path); - + free(*path); darray_free(ctx->includes); + + darray_foreach(path, ctx->failed_includes) + free(*path); + darray_free(ctx->failed_includes); } /** @@ -144,12 +182,6 @@ xkb_context_include_path_get(struct xkb_context *ctx, unsigned int idx) return darray_item(ctx->includes, idx); } -unsigned -xkb_context_take_file_id(struct xkb_context *ctx) -{ - return ctx->file_id++; -} - /** * Take a new reference on the context. */ @@ -167,29 +199,113 @@ xkb_context_ref(struct xkb_context *ctx) XKB_EXPORT void xkb_context_unref(struct xkb_context *ctx) { - if (--ctx->refcnt > 0) + if (!ctx || --ctx->refcnt > 0) return; + free(ctx->x11_atom_cache); xkb_context_include_path_clear(ctx); atom_table_free(ctx->atom_table); free(ctx); } +static const char * +log_level_to_prefix(enum xkb_log_level level) +{ + switch (level) { + case XKB_LOG_LEVEL_DEBUG: + return "xkbcommon: DEBUG: "; + case XKB_LOG_LEVEL_INFO: + return "xkbcommon: INFO: "; + case XKB_LOG_LEVEL_WARNING: + return "xkbcommon: WARNING: "; + case XKB_LOG_LEVEL_ERROR: + return "xkbcommon: ERROR: "; + case XKB_LOG_LEVEL_CRITICAL: + return "xkbcommon: CRITICAL: "; + default: + return NULL; + } +} + +ATTR_PRINTF(3, 0) static void +default_log_fn(struct xkb_context *ctx, enum xkb_log_level level, + const char *fmt, va_list args) +{ + const char *prefix = log_level_to_prefix(level); + + if (prefix) + fprintf(stderr, "%s", prefix); + vfprintf(stderr, fmt, args); +} + +static enum xkb_log_level +log_level(const char *level) { + char *endptr; + enum xkb_log_level lvl; + + errno = 0; + lvl = strtol(level, &endptr, 10); + if (errno == 0 && (endptr[0] == '\0' || is_space(endptr[0]))) + return lvl; + if (istreq_prefix("crit", level)) + return XKB_LOG_LEVEL_CRITICAL; + if (istreq_prefix("err", level)) + return XKB_LOG_LEVEL_ERROR; + if (istreq_prefix("warn", level)) + return XKB_LOG_LEVEL_WARNING; + if (istreq_prefix("info", level)) + return XKB_LOG_LEVEL_INFO; + if (istreq_prefix("debug", level) || istreq_prefix("dbg", level)) + return XKB_LOG_LEVEL_DEBUG; + + return XKB_LOG_LEVEL_ERROR; +} + +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_level = XKB_LOG_LEVEL_ERROR; + ctx->log_verbosity = 0; + ctx->use_environment_names = !(flags & XKB_CONTEXT_NO_ENVIRONMENT_NAMES); + ctx->use_secure_getenv = !(flags & XKB_CONTEXT_NO_SECURE_GETENV); + + /* Environment overwrites defaults. */ + env = xkb_context_getenv(ctx, "XKB_LOG_LEVEL"); + if (env) + xkb_context_set_log_level(ctx, log_level(env)); + + env = xkb_context_getenv(ctx, "XKB_LOG_VERBOSITY"); + if (env) + xkb_context_set_log_verbosity(ctx, log_verbosity(env)); if (!(flags & XKB_CONTEXT_NO_DEFAULT_INCLUDES) && !xkb_context_include_path_append_default(ctx)) { + log_err(ctx, "failed to add default include path %s\n", + DFLT_XKB_CONFIG_ROOT); xkb_context_unref(ctx); return NULL; } @@ -200,23 +316,54 @@ xkb_context_new(enum xkb_context_flags flags) return NULL; } + ctx->x11_atom_cache = NULL; + return ctx; } -xkb_atom_t -xkb_atom_intern(struct xkb_context *ctx, const char *string) +XKB_EXPORT void +xkb_context_set_log_fn(struct xkb_context *ctx, + void (*log_fn)(struct xkb_context *ctx, + enum xkb_log_level level, + const char *fmt, va_list args)) { - return atom_intern(ctx->atom_table, string); + ctx->log_fn = (log_fn ? log_fn : default_log_fn); } -char * -xkb_atom_strdup(struct xkb_context *ctx, xkb_atom_t atom) +XKB_EXPORT enum xkb_log_level +xkb_context_get_log_level(struct xkb_context *ctx) { - return atom_strdup(ctx->atom_table, atom); + return ctx->log_level; } -const char * -xkb_atom_text(struct xkb_context *ctx, xkb_atom_t atom) +XKB_EXPORT void +xkb_context_set_log_level(struct xkb_context *ctx, enum xkb_log_level level) +{ + ctx->log_level = level; +} + +XKB_EXPORT int +xkb_context_get_log_verbosity(struct xkb_context *ctx) +{ + return ctx->log_verbosity; +} + +XKB_EXPORT void +xkb_context_set_log_verbosity(struct xkb_context *ctx, int verbosity) +{ + ctx->log_verbosity = verbosity; +} + +XKB_EXPORT void * +xkb_context_get_user_data(struct xkb_context *ctx) +{ + if (ctx) + return ctx->user_data; + return NULL; +} + +XKB_EXPORT void +xkb_context_set_user_data(struct xkb_context *ctx, void *user_data) { - return atom_text(ctx->atom_table, atom); + ctx->user_data = user_data; }