Add new context API
authorDaniel Stone <daniel@fooishbar.org>
Tue, 27 Mar 2012 15:59:01 +0000 (16:59 +0100)
committerDaniel Stone <daniel@fooishbar.org>
Tue, 27 Mar 2012 15:59:01 +0000 (16:59 +0100)
Signed-off-by: Daniel Stone <daniel@fooishbar.org>
Makefile.am
configure.ac
include/xkbcommon/xkbcommon.h
src/context.c [new file with mode: 0644]
test/.gitignore
test/Makefile.am
test/context.c [new file with mode: 0644]
test/context.sh [new file with mode: 0755]

index 2bc6a35..6f37998 100644 (file)
@@ -63,6 +63,7 @@ libxkbcommon_la_SOURCES = \
        src/xkbcomp/xkbscan.l \
        src/alloc.c \
        src/atom.c \
+       src/context.c \
        src/keysym.c \
        src/malloc.c \
        src/map.c \
index 3a4519a..d149c21 100644 (file)
@@ -42,6 +42,9 @@ XORG_MACROS_VERSION(1.8)
 XORG_DEFAULT_OPTIONS
 XORG_CHECK_MALLOC_ZERO
 
+# Get _GNU_SOURCE and friends
+AC_USE_SYSTEM_EXTENSIONS
+
 # Check for programs
 AC_PROG_LEX
 AC_PROG_YACC
index b823890..e15dbac 100644 (file)
@@ -135,7 +135,19 @@ struct xkb_component_names {
 };
 
 /**
- * Opaque state object, may only be created, accessed, manipulated and
+ * Opaque context object; may only be created, accessed, manipulated and
+ * destroyed through the xkb_context_*() API.
+ */
+struct xkb_context;
+
+/**
+ * Opaque keymap object; may only be created, accessed, manipulated and
+ * destroyed through the xkb_state_*() API.
+ */
+struct xkb_desc;
+
+/**
+ * Opaque state object; may only be created, accessed, manipulated and
  * destroyed through the xkb_state_*() API.
  */
 struct xkb_state;
@@ -179,6 +191,66 @@ xkb_key_get_syms(struct xkb_state *state, xkb_keycode_t key,
                  xkb_keysym_t **syms_out);
 
 /**
+ * @defgroup ctx XKB contexts
+ * Every keymap compilation request must have an XKB context associated with
+ * it.  The context keeps around state such as the include path.
+ *
+ * @{
+ */
+
+/**
+ * Returns a new XKB context, or NULL on failure.  If successful, the caller
+ * holds a reference on the context, and must free it when finished with
+ * xkb_context_unref().
+ */
+_X_EXPORT struct xkb_context *
+xkb_context_new(void);
+
+/**
+ * Appends a new entry to the include path used for keymap compilation.
+ * Returns 1 on success, or 0 if the include path could not be added or is
+ * inaccessible.
+ */
+_X_EXPORT int
+xkb_context_include_path_append(struct xkb_context *context, const char *path);
+
+/**
+ * Appends the default include paths to the context's current include path.
+ * Returns 1 on success, or 0 if the primary include path could not be
+ * added.
+ */
+_X_EXPORT int
+xkb_context_include_path_append_default(struct xkb_context *context);
+
+/**
+ * Removes all entries from the context's include path, and inserts the
+ * default paths.  Returns 1 on success, or 0 if the primary include path
+ * could not be added.
+ */
+_X_EXPORT int
+xkb_context_include_path_reset(struct xkb_context *context);
+
+/**
+ * Removes all entries from the context's include path.
+ */
+_X_EXPORT void
+xkb_context_include_path_clear(struct xkb_context *context);
+
+/**
+ * Takes a new reference on an XKB context.
+ */
+_X_EXPORT void
+xkb_context_ref(struct xkb_context *context);
+
+/**
+ * Releases a reference on an XKB context, and possibly frees it.
+ */
+_X_EXPORT void
+xkb_context_unref(struct xkb_context *context);
+
+/** @} */
+
+/**
  * @defgroup map Keymap management
  * These utility functions allow you to create and deallocate XKB keymaps.
  *
diff --git a/src/context.c b/src/context.c
new file mode 100644 (file)
index 0000000..20f8c79
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Daniel Stone <daniel@fooishbar.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "xkbcommon/xkbcommon.h"
+#include "XKBcommonint.h"
+#include "utils.h"
+
+struct xkb_context {
+    int refcnt;
+    char **include_paths;
+    int num_include_paths;
+    int size_include_paths;
+};
+
+/**
+ * Append one directory to the context's include path.
+ */
+int
+xkb_context_include_path_append(struct xkb_context *context, const char *path)
+{
+    struct stat stat_buf;
+    int err;
+
+    if (context->size_include_paths <= context->num_include_paths) {
+        int new_size;
+        char **new_paths;
+        new_size = context->size_include_paths + 2;
+        new_paths = uTypedRecalloc(context->include_paths,
+                                   context->size_include_paths,
+                                   new_size,
+                                   typeof(new_paths));
+        if (!new_paths)
+            return 0;
+        context->include_paths = new_paths;
+        context->size_include_paths = new_size;
+    }
+
+    err = stat(path, &stat_buf);
+    if (err != 0)
+        return 0;
+    if (!S_ISDIR(stat_buf.st_mode))
+        return 0;
+    if (eaccess(path, R_OK | X_OK) != 0)
+        return 0;
+
+    context->include_paths[context->num_include_paths] = strdup(path);
+    if (!context->include_paths[context->num_include_paths])
+        return 0;
+    context->num_include_paths++;
+
+    return 1;
+}
+
+/**
+ * Append the default include directories to the context.
+ */
+int
+xkb_context_include_path_append_default(struct xkb_context *context)
+{
+    const char *home = getenv("HOME");
+    char *user_path;
+    int err;
+
+    (void) xkb_context_include_path_append(context, DFLT_XKB_CONFIG_ROOT);
+
+    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(context, user_path);
+
+    return 1;
+}
+
+/**
+ * Remove all entries in the context's include path.
+ */
+void
+xkb_context_include_path_clear(struct xkb_context *context)
+{
+    int i;
+
+    for (i = 0; i < context->num_include_paths; i++) {
+        free(context->include_paths[i]);
+        context->include_paths[i] = NULL;
+    }
+    context->num_include_paths = 0;
+}
+
+/**
+ * xkb_context_include_path_clear() + xkb_context_include_path_append_default()
+ */
+int
+xkb_context_include_path_reset_defaults(struct xkb_context *context)
+{
+    xkb_context_include_path_clear(context);
+    return xkb_context_include_path_append_default(context);
+}
+
+/**
+ * Returns the number of entries in the context's include path.
+ */
+unsigned int
+xkb_context_include_path_num_entries(struct xkb_context *context)
+{
+    return context->size_include_paths;
+}
+
+/**
+ * Returns the given entry in the context's include path, or NULL if an
+ * invalid index is passed.
+ */
+const char *
+xkb_context_include_path_get_entry(struct xkb_context *context,
+                                   unsigned int index)
+{
+    if (index >= xkb_context_include_path_num_entries(context))
+        return NULL;
+
+    return context->include_paths[index];
+}
+
+/**
+ * Take a new reference on the context.
+ */
+void
+xkb_context_ref(struct xkb_context *context)
+{
+    context->refcnt++;
+}
+
+/**
+ * Drop an existing reference on the context, and free it if the refcnt is
+ * now 0.
+ */
+void
+xkb_context_unref(struct xkb_context *context)
+{
+    if (--context->refcnt > 0)
+        return;
+
+    xkb_context_include_path_clear(context);
+    free(context);
+}
+
+/**
+ * Create a new context.
+ */
+struct xkb_context *
+xkb_context_new(void)
+{
+    struct xkb_context *context = calloc(1, sizeof(*context));
+
+    if (!context)
+        return NULL;
+
+    context->refcnt = 1;
+
+    if (!xkb_context_include_path_append_default(context)) {
+        xkb_context_unref(context);
+        return NULL;
+    }
+
+    return context;
+}
index eaf2cc6..e0e6667 100644 (file)
@@ -5,3 +5,4 @@ namescomp
 rulescomp
 xkey
 state
+context
index fb4e3e6..9a43e42 100644 (file)
@@ -4,7 +4,7 @@ LDADD = $(top_builddir)/libxkbcommon.la
 
 TESTS_ENVIRONMENT = $(SHELL)
 
-check_PROGRAMS = xkey filecomp namescomp rulescomp canonicalise state
+check_PROGRAMS = xkey filecomp namescomp rulescomp canonicalise state context
 TESTS = $(check_PROGRAMS:=.sh)
 
 EXTRA_DIST =           \
diff --git a/test/context.c b/test/context.c
new file mode 100644 (file)
index 0000000..1ed965e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Daniel Stone <daniel@fooishbar.org>
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+#include <linux/input.h>
+#include "xkbcommon/xkbcommon.h"
+#include "utils.h"
+#include "XKBcommonint.h"
+
+int
+main(int argc, char *argv[])
+{
+    struct xkb_context *context = xkb_context_new();
+
+    assert(context);
+
+    /* FIXME: Test include path stuff. */
+
+    xkb_context_unref(context);
+
+    return 0;
+}
diff --git a/test/context.sh b/test/context.sh
new file mode 100755 (executable)
index 0000000..730e5a5
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+srcdir=${srcdir-.}
+builddir=${builddir-.}
+
+name=context
+prog="$builddir/$name$EXEEXT"
+log="$builddir/$name.log"
+
+rm -f "$log"
+srcdir=${srcdir-.}
+builddir=${builddir-.}
+$builddir/$name$EXEEXT >> $log 2>&1