Add xkbcomp/keymap.c and move some code there
authorRan Benita <ran234@gmail.com>
Wed, 29 Aug 2012 12:02:40 +0000 (15:02 +0300)
committerRan Benita <ran234@gmail.com>
Sun, 2 Sep 2012 16:17:09 +0000 (19:17 +0300)
Add CompileKeymap to do most of what compile_keymap_file does now, and
move UpdateKeymapFromModifiers along with it from (mostly unrelated)
compat.c.
Also rename UpdateKeymapFromModifiers to UpdateDerivedKeymapFields,
because it does more than update the modifiers.

Signed-off-by: Ran Benita <ran234@gmail.com>
Makefile.am
src/xkbcomp/compat.c
src/xkbcomp/keymap.c [new file with mode: 0644]
src/xkbcomp/xkbcomp-priv.h
src/xkbcomp/xkbcomp.c

index ed96b66..011cbe2 100644 (file)
@@ -51,6 +51,7 @@ libxkbcommon_la_SOURCES = \
        src/xkbcomp/include.h \
        src/xkbcomp/keycodes.c \
        src/xkbcomp/keycodes.h \
+       src/xkbcomp/keymap.c \
        src/xkbcomp/parser.y \
        src/xkbcomp/parser-priv.h \
        src/xkbcomp/rules.c \
index bcdc2ee..c387310 100644 (file)
@@ -1113,249 +1113,3 @@ err_info:
     ClearCompatInfo(&info);
     return false;
 }
-
-static void
-ComputeEffectiveMask(struct xkb_keymap *keymap, struct xkb_mods *mods)
-{
-    xkb_mod_index_t i;
-    xkb_mod_mask_t vmask = mods->mods >> XkbNumModifiers;
-
-    /* The effective mask is only real mods for now. */
-    mods->mask = mods->mods & 0xff;
-
-    for (i = 0; i < XkbNumVirtualMods; i++) {
-        if (!(vmask & (1 << i)))
-            continue;
-        mods->mask |= keymap->vmods[i];
-    }
-}
-
-static void
-UpdateActionMods(struct xkb_keymap *keymap, union xkb_action *act,
-                 xkb_mod_mask_t rmodmask)
-{
-    unsigned int flags;
-    struct xkb_mods *mods;
-
-    switch (act->type) {
-    case XkbSA_SetMods:
-    case XkbSA_LatchMods:
-    case XkbSA_LockMods:
-        flags = act->mods.flags;
-        mods = &act->mods.mods;
-        break;
-
-    case XkbSA_ISOLock:
-        flags = act->iso.flags;
-        mods = &act->iso.mods;
-        break;
-
-    default:
-        return;
-    }
-
-    if (flags & XkbSA_UseModMapMods) {
-        /* XXX: what's that. */
-        mods->mods &= 0xff;
-        mods->mods |= rmodmask;
-    }
-    ComputeEffectiveMask(keymap, mods);
-}
-
-/**
- * Find an interpretation which applies to this particular level, either by
- * finding an exact match for the symbol and modifier combination, or a
- * generic XKB_KEY_NoSymbol match.
- */
-static struct xkb_sym_interpret *
-FindInterpForKey(struct xkb_keymap *keymap, struct xkb_key *key,
-                 xkb_group_index_t group, xkb_level_index_t level)
-{
-    struct xkb_sym_interpret *ret = NULL;
-    struct xkb_sym_interpret *interp;
-    const xkb_keysym_t *syms;
-    int num_syms;
-
-    num_syms = xkb_key_get_syms_by_level(keymap, key, group, level, &syms);
-    if (num_syms == 0)
-        return NULL;
-
-    darray_foreach(interp, keymap->sym_interpret) {
-        uint32_t mods;
-        bool found;
-
-        if ((num_syms > 1 || interp->sym != syms[0]) &&
-            interp->sym != XKB_KEY_NoSymbol)
-            continue;
-
-        if (level == 0 || !(interp->match & XkbSI_LevelOneOnly))
-            mods = key->modmap;
-        else
-            mods = 0;
-
-        switch (interp->match & XkbSI_OpMask) {
-        case XkbSI_NoneOf:
-            found = !(interp->mods & mods);
-            break;
-        case XkbSI_AnyOfOrNone:
-            found = (!mods || (interp->mods & mods));
-            break;
-        case XkbSI_AnyOf:
-            found = !!(interp->mods & mods);
-            break;
-        case XkbSI_AllOf:
-            found = ((interp->mods & mods) == interp->mods);
-            break;
-        case XkbSI_Exactly:
-            found = (interp->mods == mods);
-            break;
-        default:
-            found = false;
-            break;
-        }
-
-        if (found && interp->sym != XKB_KEY_NoSymbol)
-            return interp;
-        else if (found && !ret)
-            ret = interp;
-    }
-
-    return ret;
-}
-
-static bool
-ApplyInterpsToKey(struct xkb_keymap *keymap, struct xkb_key *key)
-{
-#define INTERP_SIZE (8 * 4)
-    struct xkb_sym_interpret *interps[INTERP_SIZE];
-    xkb_mod_mask_t vmodmask = 0;
-    int num_acts = 0;
-    xkb_group_index_t group;
-    xkb_level_index_t level;
-    unsigned int i;
-
-    /* If we've been told not to bind interps to this key, then don't. */
-    if (key->explicit & XkbExplicitInterpretMask)
-        return true;
-
-    for (i = 0; i < INTERP_SIZE; i++)
-        interps[i] = NULL;
-
-    for (group = 0; group < key->num_groups; group++) {
-        for (level = 0; level < XkbKeyGroupWidth(keymap, key, group);
-             level++) {
-            i = (group * key->width) + level;
-            if (i >= INTERP_SIZE) /* XXX FIXME */
-                return false;
-            interps[i] = FindInterpForKey(keymap, key, group, level);
-            if (interps[i])
-                num_acts++;
-        }
-    }
-
-    if (num_acts && !key->actions) {
-        key->actions = calloc(key->num_groups * key->width,
-                              sizeof(*key->actions));
-        if (!key->actions)
-            return false;
-    }
-
-    for (group = 0; group < key->num_groups; group++) {
-        for (level = 0; level < XkbKeyGroupWidth(keymap, key, group);
-             level++) {
-            struct xkb_sym_interpret *interp;
-
-            i = (group * key->width) + level;
-            interp = interps[i];
-
-            /* Infer default key behaviours from the base level. */
-            if (group == 0 && level == 0) {
-                if (!(key->explicit & XkbExplicitAutoRepeatMask) &&
-                    (!interp || (interp->flags & XkbSI_AutoRepeat)))
-                    key->repeats = true;
-            }
-
-            if (!interp)
-                continue;
-
-            if ((group == 0 && level == 0) ||
-                !(interp->match & XkbSI_LevelOneOnly)) {
-                if (interp->virtual_mod != XkbNoModifier)
-                    vmodmask |= (1 << interp->virtual_mod);
-            }
-
-            key->actions[i] = interp->act;
-        }
-    }
-
-    if (!(key->explicit & XkbExplicitVModMapMask))
-        key->vmodmap = vmodmask;
-
-    return true;
-#undef INTERP_SIZE
-}
-
-/**
- * This collects a bunch of disparate functions which was done in the server
- * at various points that really should've been done within xkbcomp.  Turns out
- * your actions and types are a lot more useful when any of your modifiers
- * other than Shift actually do something ...
- */
-bool
-UpdateModifiersFromCompat(struct xkb_keymap *keymap)
-{
-    xkb_mod_index_t vmod;
-    xkb_led_index_t led;
-    unsigned int i, j;
-    struct xkb_key *key;
-
-    /* Find all the interprets for the key and bind them to actions,
-     * which will also update the vmodmap. */
-    xkb_foreach_key(key, keymap)
-        if (!ApplyInterpsToKey(keymap, key))
-            return false;
-
-    /* Update keymap->vmods, the virtual -> real mod mapping. */
-    for (vmod = 0; vmod < XkbNumVirtualMods; vmod++)
-        keymap->vmods[vmod] = 0;
-
-    xkb_foreach_key(key, keymap) {
-        if (!key->vmodmap)
-            continue;
-
-        for (vmod = 0; vmod < XkbNumVirtualMods; vmod++) {
-            if (!(key->vmodmap & (1 << vmod)))
-                continue;
-            keymap->vmods[vmod] |= key->modmap;
-        }
-    }
-
-    /* Now update the level masks for all the types to reflect the vmods. */
-    for (i = 0; i < keymap->num_types; i++) {
-        ComputeEffectiveMask(keymap, &keymap->types[i].mods);
-
-        for (j = 0; j < keymap->types[i].num_entries; j++) {
-            ComputeEffectiveMask(keymap, &keymap->types[i].map[j].mods);
-            ComputeEffectiveMask(keymap, &keymap->types[i].map[j].preserve);
-        }
-    }
-
-    /* Update action modifiers. */
-    xkb_foreach_key(key, keymap) {
-        if (!key->actions)
-            continue;
-
-        for (i = 0; i < key->num_groups * key->width; i++)
-            UpdateActionMods(keymap, &key->actions[i], key->modmap);
-    }
-
-    /* Update vmod -> indicator maps. */
-    for (led = 0; led < XkbNumIndicators; led++)
-        ComputeEffectiveMask(keymap, &keymap->indicators[led].mods);
-
-    /* Find maximum number of groups out of all keys in the keymap. */
-    xkb_foreach_key(key, keymap)
-        keymap->num_groups = MAX(keymap->num_groups, key->num_groups);
-
-    return true;
-}
diff --git a/src/xkbcomp/keymap.c b/src/xkbcomp/keymap.c
new file mode 100644 (file)
index 0000000..0cc1d58
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2009  Dan Nicholson
+ *
+ * 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 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 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.
+ *
+ * Except as contained in this notice, the names of the authors or their
+ * institutions shall not be used in advertising or otherwise to promote the
+ * sale, use or other dealings in this Software without prior written
+ * authorization from the authors.
+ */
+
+#include "xkbcomp-priv.h"
+
+static void
+ComputeEffectiveMask(struct xkb_keymap *keymap, struct xkb_mods *mods)
+{
+    xkb_mod_index_t i;
+    xkb_mod_mask_t vmask = mods->mods >> XkbNumModifiers;
+
+    /* The effective mask is only real mods for now. */
+    mods->mask = mods->mods & 0xff;
+
+    for (i = 0; i < XkbNumVirtualMods; i++) {
+        if (!(vmask & (1 << i)))
+            continue;
+        mods->mask |= keymap->vmods[i];
+    }
+}
+
+static void
+UpdateActionMods(struct xkb_keymap *keymap, union xkb_action *act,
+                 xkb_mod_mask_t rmodmask)
+{
+    unsigned int flags;
+    struct xkb_mods *mods;
+
+    switch (act->type) {
+    case XkbSA_SetMods:
+    case XkbSA_LatchMods:
+    case XkbSA_LockMods:
+        flags = act->mods.flags;
+        mods = &act->mods.mods;
+        break;
+
+    case XkbSA_ISOLock:
+        flags = act->iso.flags;
+        mods = &act->iso.mods;
+        break;
+
+    default:
+        return;
+    }
+
+    if (flags & XkbSA_UseModMapMods) {
+        /* XXX: what's that. */
+        mods->mods &= 0xff;
+        mods->mods |= rmodmask;
+    }
+    ComputeEffectiveMask(keymap, mods);
+}
+
+/**
+ * Find an interpretation which applies to this particular level, either by
+ * finding an exact match for the symbol and modifier combination, or a
+ * generic XKB_KEY_NoSymbol match.
+ */
+static struct xkb_sym_interpret *
+FindInterpForKey(struct xkb_keymap *keymap, struct xkb_key *key,
+                 xkb_group_index_t group, xkb_level_index_t level)
+{
+    struct xkb_sym_interpret *ret = NULL;
+    struct xkb_sym_interpret *interp;
+    const xkb_keysym_t *syms;
+    int num_syms;
+
+    num_syms = xkb_key_get_syms_by_level(keymap, key, group, level, &syms);
+    if (num_syms == 0)
+        return NULL;
+
+    darray_foreach(interp, keymap->sym_interpret) {
+        uint32_t mods;
+        bool found;
+
+        if ((num_syms > 1 || interp->sym != syms[0]) &&
+            interp->sym != XKB_KEY_NoSymbol)
+            continue;
+
+        if (level == 0 || !(interp->match & XkbSI_LevelOneOnly))
+            mods = key->modmap;
+        else
+            mods = 0;
+
+        switch (interp->match & XkbSI_OpMask) {
+        case XkbSI_NoneOf:
+            found = !(interp->mods & mods);
+            break;
+        case XkbSI_AnyOfOrNone:
+            found = (!mods || (interp->mods & mods));
+            break;
+        case XkbSI_AnyOf:
+            found = !!(interp->mods & mods);
+            break;
+        case XkbSI_AllOf:
+            found = ((interp->mods & mods) == interp->mods);
+            break;
+        case XkbSI_Exactly:
+            found = (interp->mods == mods);
+            break;
+        default:
+            found = false;
+            break;
+        }
+
+        if (found && interp->sym != XKB_KEY_NoSymbol)
+            return interp;
+        else if (found && !ret)
+            ret = interp;
+    }
+
+    return ret;
+}
+
+static bool
+ApplyInterpsToKey(struct xkb_keymap *keymap, struct xkb_key *key)
+{
+#define INTERP_SIZE (8 * 4)
+    struct xkb_sym_interpret *interps[INTERP_SIZE];
+    xkb_mod_mask_t vmodmask = 0;
+    int num_acts = 0;
+    xkb_group_index_t group;
+    xkb_level_index_t level;
+    unsigned int i;
+
+    /* If we've been told not to bind interps to this key, then don't. */
+    if (key->explicit & XkbExplicitInterpretMask)
+        return true;
+
+    for (i = 0; i < INTERP_SIZE; i++)
+        interps[i] = NULL;
+
+    for (group = 0; group < key->num_groups; group++) {
+        for (level = 0; level < XkbKeyGroupWidth(keymap, key, group);
+             level++) {
+            i = (group * key->width) + level;
+            if (i >= INTERP_SIZE) /* XXX FIXME */
+                return false;
+            interps[i] = FindInterpForKey(keymap, key, group, level);
+            if (interps[i])
+                num_acts++;
+        }
+    }
+
+    if (num_acts && !key->actions) {
+        key->actions = calloc(key->num_groups * key->width,
+                              sizeof(*key->actions));
+        if (!key->actions)
+            return false;
+    }
+
+    for (group = 0; group < key->num_groups; group++) {
+        for (level = 0; level < XkbKeyGroupWidth(keymap, key, group);
+             level++) {
+            struct xkb_sym_interpret *interp;
+
+            i = (group * key->width) + level;
+            interp = interps[i];
+
+            /* Infer default key behaviours from the base level. */
+            if (group == 0 && level == 0) {
+                if (!(key->explicit & XkbExplicitAutoRepeatMask) &&
+                    (!interp || (interp->flags & XkbSI_AutoRepeat)))
+                    key->repeats = true;
+            }
+
+            if (!interp)
+                continue;
+
+            if ((group == 0 && level == 0) ||
+                !(interp->match & XkbSI_LevelOneOnly)) {
+                if (interp->virtual_mod != XkbNoModifier)
+                    vmodmask |= (1 << interp->virtual_mod);
+            }
+
+            key->actions[i] = interp->act;
+        }
+    }
+
+    if (!(key->explicit & XkbExplicitVModMapMask))
+        key->vmodmap = vmodmask;
+
+    return true;
+#undef INTERP_SIZE
+}
+
+/**
+ * This collects a bunch of disparate functions which was done in the server
+ * at various points that really should've been done within xkbcomp.  Turns out
+ * your actions and types are a lot more useful when any of your modifiers
+ * other than Shift actually do something ...
+ */
+static bool
+UpdateDerivedKeymapFields(struct xkb_keymap *keymap)
+{
+    xkb_mod_index_t vmod;
+    xkb_led_index_t led;
+    unsigned int i, j;
+    struct xkb_key *key;
+
+    /* Find all the interprets for the key and bind them to actions,
+     * which will also update the vmodmap. */
+    xkb_foreach_key(key, keymap)
+        if (!ApplyInterpsToKey(keymap, key))
+            return false;
+
+    /* Update keymap->vmods, the virtual -> real mod mapping. */
+    for (vmod = 0; vmod < XkbNumVirtualMods; vmod++)
+        keymap->vmods[vmod] = 0;
+
+    xkb_foreach_key(key, keymap) {
+        if (!key->vmodmap)
+            continue;
+
+        for (vmod = 0; vmod < XkbNumVirtualMods; vmod++) {
+            if (!(key->vmodmap & (1 << vmod)))
+                continue;
+            keymap->vmods[vmod] |= key->modmap;
+        }
+    }
+
+    /* Now update the level masks for all the types to reflect the vmods. */
+    for (i = 0; i < keymap->num_types; i++) {
+        ComputeEffectiveMask(keymap, &keymap->types[i].mods);
+
+        for (j = 0; j < keymap->types[i].num_entries; j++) {
+            ComputeEffectiveMask(keymap, &keymap->types[i].map[j].mods);
+            ComputeEffectiveMask(keymap, &keymap->types[i].map[j].preserve);
+        }
+    }
+
+    /* Update action modifiers. */
+    xkb_foreach_key(key, keymap) {
+        if (!key->actions)
+            continue;
+
+        for (i = 0; i < key->num_groups * key->width; i++)
+            UpdateActionMods(keymap, &key->actions[i], key->modmap);
+    }
+
+    /* Update vmod -> indicator maps. */
+    for (led = 0; led < XkbNumIndicators; led++)
+        ComputeEffectiveMask(keymap, &keymap->indicators[led].mods);
+
+    /* Find maximum number of groups out of all keys in the keymap. */
+    xkb_foreach_key(key, keymap)
+        keymap->num_groups = MAX(keymap->num_groups, key->num_groups);
+
+    return true;
+}
+
+typedef bool (*compile_file_fn)(XkbFile *file,
+                                struct xkb_keymap *keymap,
+                                enum merge_mode merge);
+
+static const compile_file_fn compile_file_fns[LAST_KEYMAP_FILE_TYPE + 1] = {
+    [FILE_TYPE_KEYCODES] = CompileKeycodes,
+    [FILE_TYPE_TYPES] = CompileKeyTypes,
+    [FILE_TYPE_COMPAT] = CompileCompatMap,
+    [FILE_TYPE_SYMBOLS] = CompileSymbols,
+};
+
+bool
+CompileKeymap(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge)
+{
+    bool ok;
+    const char *main_name;
+    XkbFile *files[LAST_KEYMAP_FILE_TYPE + 1] = { NULL };
+    enum xkb_file_type type;
+    struct xkb_context *ctx = keymap->ctx;
+
+    main_name = file->name ? file->name : "(unnamed)";
+
+    /* Collect section files and check for duplicates. */
+    for (file = (XkbFile *) file->defs; file;
+         file = (XkbFile *) file->common.next) {
+        if (file->file_type < FIRST_KEYMAP_FILE_TYPE ||
+            file->file_type > LAST_KEYMAP_FILE_TYPE) {
+            log_err(ctx, "Cannot define %s in a keymap file\n",
+                    xkb_file_type_to_string(file->file_type));
+            continue;
+        }
+
+        if (files[file->file_type]) {
+            log_err(ctx,
+                    "More than one %s section in keymap file; "
+                    "All sections after the first ignored\n",
+                    xkb_file_type_to_string(file->file_type));
+            continue;
+        }
+
+        if (!file->topName) {
+            free(file->topName);
+            file->topName = strdup(main_name);
+        }
+
+        files[file->file_type] = file;
+    }
+
+    /*
+     * Check that all required section were provided.
+     * Report everything before failing.
+     */
+    ok = true;
+    for (type = FIRST_KEYMAP_FILE_TYPE;
+         type <= LAST_KEYMAP_FILE_TYPE;
+         type++) {
+        if (files[type] == NULL) {
+            log_err(ctx, "Required section %s missing from keymap\n",
+                    xkb_file_type_to_string(type));
+            ok = false;
+        }
+    }
+    if (!ok)
+        return false;
+
+    /* Compile sections. */
+    for (type = FIRST_KEYMAP_FILE_TYPE;
+         type <= LAST_KEYMAP_FILE_TYPE;
+         type++) {
+        log_dbg(ctx, "Compiling %s \"%s\"\n",
+                xkb_file_type_to_string(type), files[type]->topName);
+
+        ok = compile_file_fns[type](files[type], keymap, merge);
+        if (!ok) {
+            log_err(ctx, "Failed to compile %s\n",
+                    xkb_file_type_to_string(type));
+            return false;
+        }
+    }
+
+    return UpdateDerivedKeymapFields(keymap);
+}
index 2bf2b51..6175f69 100644 (file)
@@ -62,7 +62,8 @@ CompileSymbols(XkbFile *file, struct xkb_keymap *keymap,
                enum merge_mode merge);
 
 bool
-UpdateModifiersFromCompat(struct xkb_keymap *keymap);
+CompileKeymap(XkbFile *file, struct xkb_keymap *keymap,
+              enum merge_mode merge);
 
 bool
 LookupKeysym(const char *str, xkb_keysym_t *sym_rtrn);
index 9ceaa0c..722dc91 100644 (file)
 #include "xkbcomp-priv.h"
 #include "rules.h"
 
-typedef bool (*compile_file_fn)(XkbFile *file,
-                                struct xkb_keymap *keymap,
-                                enum merge_mode merge);
-
-static const compile_file_fn compile_file_fns[LAST_KEYMAP_FILE_TYPE + 1] = {
-    [FILE_TYPE_KEYCODES] = CompileKeycodes,
-    [FILE_TYPE_TYPES] = CompileKeyTypes,
-    [FILE_TYPE_COMPAT] = CompileCompatMap,
-    [FILE_TYPE_SYMBOLS] = CompileSymbols,
-};
-
 static struct xkb_keymap *
 compile_keymap_file(struct xkb_context *ctx, XkbFile *file)
 {
-    bool ok;
-    const char *main_name;
     struct xkb_keymap *keymap;
-    XkbFile *files[LAST_KEYMAP_FILE_TYPE + 1] = { NULL };
-    enum xkb_file_type type;
 
     keymap = xkb_map_new(ctx);
     if (!keymap)
         goto err;
 
-    main_name = file->name ? file->name : "(unnamed)";
-
     if (file->file_type != FILE_TYPE_KEYMAP) {
         log_err(ctx, "Cannot compile a %s file alone into a keymap\n",
                 xkb_file_type_to_string(file->file_type));
         goto err;
     }
 
-    /* Collect section files and check for duplicates. */
-    for (file = (XkbFile *) file->defs; file;
-         file = (XkbFile *) file->common.next) {
-        if (file->file_type < FIRST_KEYMAP_FILE_TYPE ||
-            file->file_type > LAST_KEYMAP_FILE_TYPE) {
-            log_err(ctx, "Cannot define %s in a keymap file\n",
-                    xkb_file_type_to_string(file->file_type));
-            continue;
-        }
-
-        if (files[file->file_type]) {
-            log_err(ctx,
-                    "More than one %s section in keymap file; "
-                    "All sections after the first ignored\n",
-                    xkb_file_type_to_string(file->file_type));
-            continue;
-        }
-
-        if (!file->topName) {
-            free(file->topName);
-            file->topName = strdup(main_name);
-        }
-
-        files[file->file_type] = file;
-    }
-
-    /*
-     * Check that all required section were provided.
-     * Report everything before failing.
-     */
-    ok = true;
-    for (type = FIRST_KEYMAP_FILE_TYPE;
-         type <= LAST_KEYMAP_FILE_TYPE;
-         type++) {
-        if (files[type] == NULL) {
-            log_err(ctx, "Required section %s missing from keymap\n",
-                    xkb_file_type_to_string(type));
-            ok = false;
-        }
-    }
-    if (!ok)
+    if (!CompileKeymap(file, keymap, MERGE_OVERRIDE)) {
+        log_err(ctx, "Failed to compile keymap\n");
         goto err;
-
-    /* Compile sections. */
-    for (type = FIRST_KEYMAP_FILE_TYPE;
-         type <= LAST_KEYMAP_FILE_TYPE;
-         type++) {
-        log_dbg(ctx, "Compiling %s \"%s\"\n",
-                xkb_file_type_to_string(type), files[type]->topName);
-        ok = compile_file_fns[type](files[type], keymap, MERGE_OVERRIDE);
-        if (!ok) {
-            log_err(ctx, "Failed to compile %s\n",
-                    xkb_file_type_to_string(type));
-            goto err;
-        }
     }
 
-    ok = UpdateModifiersFromCompat(keymap);
-    if (!ok)
-        goto err;
-
     return keymap;
 
 err:
-    log_err(ctx, "Failed to compile keymap\n");
     xkb_map_unref(keymap);
     return NULL;
 }